App Components
What ships in every standard app, and how the pieces relate. This is the
blueprint's component model — templates/app/ is a runnable instance of it.
🗂️ Component model
%%{init: {"flowchart": {"nodeSpacing": 55, "rankSpacing": 120}}}%%
flowchart TB
subgraph EDGE["interfaces/ — HTTP edge"]
OAS["openapi.yaml"]
RU["resource routes"]
JU["job routes"]
end
subgraph CORE["domain/ — business core"]
RI["<resource> · models · ports · services"]
JI["<job/worker> · models · ports · services"]
PI["pipelines/<family>"]
end
subgraph INFRA["infra/ — adapters"]
DB[("MongoDB repos")]
CA["redis cache"]
ST["stores · progress bus"]
LL["llm clients"]
end
W["worker.py"]
CR["init.py — composition root"]
OAS --> RU
OAS --> JU
RU --> RI
JU --> JI
JI --> PI
PI --> DB
PI --> LL
RI --> CA
RI --> DB
JI --> ST
W --> JI
W --> PI
CR === RU
CR === JU
CR === RI
CR === JI
CR === PI
CR === W
CR === DB
CR === CA
CR === ST
Legend — solid arrows are direct calls; thick links are wires created by the composition root. Every component is injected, never self-constructed.
📦 Component roles
1. interfaces/ — the edge
Thin handlers bound to openapi.yaml operationIds. They parse the request,
call a service, and shape the response. No business rules, no I/O.
interfaces/openapi.pyre-exports every route module so the OpenAPI-first app can resolve handlers.- Routes may mount the
cachedecorator on read endpoints.
2. domain/ — the core
Pure models, ports (abstract contracts), and services (use cases). No framework imports, no drivers.
<aggregate>/models.py— dataclasses, enums, document shapes.<aggregate>/ports/db.py— repo contract;<aggregate>/ports/service.py— service contract.- Services compose ports and enforce the business rules; the composition root injects the implementations.
3. infra/ — the adapters
Concrete implementations of the domain ports plus cross-cutting infrastructure:
db/— mongo-ops repositories and the connection lifecycle.adapters/— cache store, progress bus, storages, fetchers (library-backed).- Anything else the domain needs, implemented against its ports.
4. pipelines/ — data-driven families (optional)
Extraction and enrichment families, each a deterministic step chain
(abc.py / impl.py / pipeline.yaml / resources/). Roots are registered
in the pattern registry and driven either by a worker job or a CLI.
5. worker.py — the job worker (optional)
A separate process that polls durable job collections, runs pipeline roots, and publishes progress to the progress bus. It shares the same composition root as the API.
6. init.py — the composition root
The only place anything is constructed: leaf repositories → dependent
repositories → services → adapters. Exposes get_svc overloads and starts /
stops resources on the app lifespan.
🔗 How the request flows
sequenceDiagram
participant C as Client
participant R as route (interfaces)
participant S as service (domain)
participant P as repo (infra)
participant DB as MongoDB
C->>R: POST /items (operationId)
R->>S: svc.create(payload)
S->>P: repo.insert(doc)
P->>DB: insert
DB-->>P: ack
P-->>S: doc
S-->>R: result
R-->>C: 200 JSON