Versioning standard now states services must read their VERSION (e.g. a build arg) rather than hardcoding it; the compliance prompt repeats it. build_bundle also bundles src/wiki/** as wiki_-prefixed modules (e.g. docs://modules/wiki_development_releasing), so the release runbook is reachable from the MCP. Bundle grows to 22 modules.
8 lines
5.1 KiB
JSON
8 lines
5.1 KiB
JSON
{
|
||
"module": "wiki_components",
|
||
"content": {
|
||
"path": "wiki_components",
|
||
"docstring": "# App Components\n\nWhat ships in every standard app, and how the pieces relate. This is the\nblueprint's component model — `templates/app/` is a runnable instance of it.\n\n---\n\n## 🗂️ Component model\n\nThe blueprint has two orthogonal views: **runtime flow** (who calls whom) and\n**composition-root wiring** (who constructs whom). Keeping them separate makes\nthe layering visible instead of hiding it behind a hub.\n\n### 🔀 Runtime flow\n\nWho calls whom at request and job time:\n\n```mermaid\n%%{init: {\"flowchart\": {\"nodeSpacing\": 50, \"rankSpacing\": 80}}}%%\nflowchart TB\n subgraph REQ[\"Request path — API process\"]\n direction LR\n CL([\"Client<br/>operationId\"]) --> RT[\"interfaces/<resource>/routes.py\"]\n RT --> SVC[\"<resource>_svc\"]\n SVC --> REPO[\"<resource>_repo\"]\n end\n\n subgraph WRK[\"Background path — worker process\"]\n direction LR\n W[\"worker.py\"] --> JSVC[\"job_svc\"]\n W --> PIPE[\"pipelines/<family>\"]\n PIPE --> ISVC[\"item_svc\"]\n JSVC --> JREPO[\"job_repo\"]\n ISVC --> IREPO[\"item_repo\"]\n end\n\n subgraph INFRA[\"infra/ — adapters\"]\n MONGO[(\"MongoDB / mongo_ops\")]\n end\n\n REPO --> MONGO\n JREPO --> MONGO\n IREPO --> MONGO\n```\n\n> **Legend** — solid arrows are runtime calls. Nothing is self-constructed.\n\n### 🧵 Composition-root wiring\n\nWho constructs what at startup:\n\n```mermaid\n%%{init: {\"flowchart\": {\"nodeSpacing\": 50, \"rankSpacing\": 80}}}%%\nflowchart TB\n INIT[\"init.py — composition root\"]\n SETUP[\"infra/db/setup.py\"]\n FACT[\"domain/*/ports/*<br/>factory seams\"]\n REPOS[\"repos<br/>infra/db/repos/mongo.py\"]\n SVCES[\"services<br/>CrudsServiceAdaptor\"]\n STATE[\"app.state.db_resources\"]\n HEXA[\"hexa.build\"]\n RT[\"routes.py\"]\n WK[\"worker.py\"]\n\n INIT --> SETUP\n INIT --> FACT\n FACT --> REPOS\n FACT --> SVCES\n REPOS --> SVCES\n HEXA -.-> SVCES\n INIT --> STATE\n STATE --> RT\n INIT --> WK\n```\n\n> **Legend** — `init.py` is the only place that imports concrete adapters. The\n> `ports/` factory seams bind `infra`; the API reads resources from\n> `app.state.db_resources`, the worker calls `init()` directly.\n\n---\n\n## 📦 Component roles\n\n### 1. `interfaces/` — the edge\n\nThin handlers bound to `openapi.yaml` `operationId`s. They parse the request,\ncall a service, and shape the response. No business rules, no I/O.\n\n- `interfaces/openapi.py` re-exports every route module so the OpenAPI-first\n app can resolve handlers.\n- Routes may mount the `cache` decorator on read endpoints.\n\n### 2. `domain/` — the core\n\nModels, ports, and services (use cases). No framework imports. The `ports/`\npackage is the one seam allowed to reach into `infra/`: each port module declares\nthe document shape and a factory that binds the adapter.\n\n- `<aggregate>/models.py` — dataclasses, enums, document shapes.\n- `<aggregate>/ports/db.py` — document model + `create_<aggregate>_repo()`.\n- `<aggregate>/ports/service.py` — service + `get_<aggregate>_service(repo)`.\n- Services compose ports and enforce the business rules; the port factories bind\n the implementations, and the composition root calls them.\n\n### 3. `infra/` — the adapters\n\nConcrete implementations of the domain ports plus cross-cutting infrastructure:\n\n- `db/` — mongo-ops repositories and the connection lifecycle.\n- `adapters/` — cache store, progress bus, storages, fetchers (library-backed).\n- Anything else the domain needs, implemented against its ports.\n\n### 4. `pipelines/` — data-driven families *(optional)*\n\nExtraction and enrichment families, each a deterministic step chain\n(`abc.py` / `impl.py` / `pipeline.yaml` / `resources/`). Roots are registered\nin the pattern registry and driven either by a worker job or a CLI.\n\n### 5. `worker.py` — the job worker *(optional)*\n\nA separate process that polls durable job collections, runs pipeline roots, and\npublishes progress to the progress bus. It shares the same composition root as\nthe API.\n\n### 6. `init.py` — the composition root\n\nThe only place anything is constructed: leaf repositories → dependent\nrepositories → services → adapters. Exposes `get_svc` overloads and starts /\nstops resources on the app lifespan.\n\n---\n\n## 🔗 How the request flows\n\n```mermaid\nsequenceDiagram\n participant C as Client\n participant R as route (interfaces)\n participant S as service (port factory / adapter)\n participant P as repo (infra)\n participant DB as MongoDB\n\n C->>R: POST /items (operationId)\n R->>S: svc.create(payload)\n S->>P: repo.insert(doc)\n P->>DB: insert\n DB-->>P: ack\n P-->>S: doc\n S-->>R: result\n R-->>C: 200 JSON\n```\n\n---\n\n## Related\n\n- [01 – Overview](01_overview.md) · [03 – Start an App](03_start_an_app.md) · [04 – Testing & Quality](04_development/01_testing.md)\n",
|
||
"objects": {}
|
||
}
|
||
} |