Repository navigation
refactor: move shared backend mechanism into app/core - #82
Merged
Merged
Conversation
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
This was referenced Oct 18, 2026
* fix: percent-encode database credentials in the dsn * fix: declare the indexes and column types the migrations built * refactor: move tables into app/core/db * test: cover the schema against migrations, the engine and ledger writes * refactor: split backend domains into app/features (#84) * refactor: split backend domains into app/features * refactor: type app/features for mypy strict * fix: keep links on a shared platform's subdomains with the aggregator * fix: drop a newsletter product whose picked link is past the search results * test: cover approve and reject against the schema, and publisher resolution edges * chore: point the end-of-file exclude at the moved email templates * refactor: tidy comments and test helpers from the features split * refactor: move mcp tools and scripts into app/entry (#85) * refactor: expose what entry needs through each feature's service * refactor: split the mcp tools into app/entry/mcp and fold the router into main * refactor: move scripts and the timer entrypoints into app/entry/cli * test: cover the mcp token gate end to end over http * test: cover the cli entrypoints' targets and exit codes * fix: fail the backup when pg_dump writes nothing * refactor: make app/entry pass strict mypy * fix: keep sentry off in development * chore: name the seed module in restore-db's hint without backticks * docs: say what tests-start.sh does with its argument * test: return the tool result's error flag and text from the gate tests' helper * fix: stop importing the email module from configuring the root logger * fix: require the alembic that reads its config from pyproject * test: check the collect run leaves the root logger alone * docs: say where command-line entrypoints live * refactor: name the newsletter service alike in every mcp tool * test: colocate backend tests beside their modules (#86) * test: colocate backend tests beside their modules * test: cover the curation tools, sign-in refusals, publisher lookups and the known-URL filter * fix: fail the daily report when its mail does not send * test: pin that the report reaches the send, and clean up the filter's publisher * ci: enforce backend import layers (#87) * fix: run mypy and ty in pre-commit with the backend config * ci: enforce backend import layers * fix: name the exact claude-code-action tag in its pin comments * ci: deploy only what the box runs (#88) * docs: point the deploy README's env table at app/features * ci: deploy only what the box runs * test: check the deploy filter ships every path the units and the job use * docs: record the layered backend (#89) * docs: record the layered backend * fix: address the backend migration review (#91) * fix: configure logging for the api process * fix: let a publisher's link claim a platform subdomain * fix: fail a link loudly on a non-numeric jev answer * docs: point stale docstrings at where the code moved --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 1 of
backend-architecture.md: thecore/layer.What moved
app/platform/toapp/core/: settings, logging, security, dates, email, db, email-templates.pipeline/fetching/http.pytocore/http.py.tavily_searchis split out intocore/web_search.py.pipeline/fetching/extract_content.pytocore/extract.py. It also takesoutbound_links,group_linksand the link host sets frompipeline/fetching/page_facts.py.pipeline/github.pytocore/github.py. It also takesrepo_for,has_readmeandaccount_typefrompipeline/sources/github_stars.py.pipeline/urls.pyandpipeline/first_party.pymerge intocore/urls.py.pipeline/embedding.pytocore/embedding.py. It also takesSNIPPET_CAPfrompipeline/steps/__init__.pyandcosine_distances,nearest,story_groupsfrompipeline/curation.py.pipeline/jev.pyandpipeline/llm_text.pymove tocore/unchanged.parse_datemoves frompipeline/freshness.pytocore/dates.py.send_mailmoves frompipeline/report.pytocore/email.py.Every import, plus the
monkeypatchtargets in tests, now points at the new paths.Differences from the plan's tree
core/db.pyis the oldplatform/db.py, kept as a flat module. Step 2 replaces it with thecore/db/package.core/for now. Step 3 moves them toaudience/andnewsletter/.pipeline/sources/github_stars.pyis deleted. It held only the three API helpers, which now live incore/github.py, so the plan'scollect/github_stars.pyhas nothing left to hold.covering()stays inpipeline/curation.py, because curation is its only caller.pipeline/fetching/page_facts.pykeepscheck_link(the futurecuration/links.py). It importsHF_HOSTS,HF_SITE_PAGESandGITLAB_SITE_PAGESfromcore/extract.py.Behaviour changes
parse_datereads a date with no offset, or RFC 2822's-0000, as UTC. Before, it returned a naive datetime.is_within_windowthen read that datetime in the server's local time, andpublished_atwas stored in the session timezone. On a UTC box the values are the same. The fix is its own commit (fix: read a feed date with no timezone as utc).Settings(), becausecore/email.pyimports it. See below.Tests added
/login/test-token.send_mail: with no key it logs instead of sending, it sends toPIPELINE_ALERT_EMAILwith the body escaped, and a failed send does not raise.core/github.py:account_typeandrepo_forreturn None on a 404, a rate limit, a non-JSON body, a body of the wrong shape, or a failed request.parse_datereads a date with no offset as UTC.tests/platform/is renamed totests/core/, where the new core tests live. Step 5 flattens it.Other changes beyond moving
mypy --strict.jev.pyusesQuestionandJsonaliases in place ofAnyand baredict.web_search.pyandhttp.pygot typed dicts.embedding.pytakes and returnsNDArray[np.float32]. The values are the same:np.asarraydoes not copy a float32 array, and2.0**attemptgives the same backoff numbers.http.pybuilds its client ashttpx.Client(follow_redirects=True, proxy=proxy or None)instead of building a kwargs dict. The behaviour is the same.types-regexdev dependency so mypy can checkllm_text.py.send_mailstill readsos.environ(ADR 7). Importingcore/email.pybuildsSettings(), so the report process now builds it too. The report unit already loads the full/opt/agentique/.env, so nothing changes on the box.unparseablebecameunparsableinpipeline/freshness.pyandpipeline/sources/substack.py. CI runs typos on changed files, and both files are in this diff..pre-commit-config.yaml(template exclude),deploy/README.md,docs/backend.md,docs/style.mdanddocs/glossary.md. ADRs are left as written.No systemd unit, workflow or script path changes.
pipeline.runandpipeline.reportkeep their module paths, so the units don't need reinstalling.Note for later steps
Pre-commit runs
uv run mypy backend/app backend/scriptsfrom the repo root. From there mypy doesn't readbackend/pyproject.toml's[tool.mypy], so CI type-checks non-strict. With the strict config (run frombackend/), the count goes from 144 errors on master to 126 here, with none left inapp/core.Verification
backend/appandbackend/scripts, typos and the banned-names hook: all pass (prek runon the changed files).prestart.sh, thentests-start.sh): 592 passed, 1 failed. The failure istest_read_endpoints_are_public[/search?q=agents], which downloads the embedding model from Hugging Face. The sandbox proxy blocks that download, and the same test fails the same way on master here.scripts/generate-client.sh:frontend/src/clientis unchanged.tools/listdump from master and from this branch: identical.🤖 Generated with Claude Code
https://claude.ai/code/session_01Tprah8Se8dG6ykxn1hV2C9