docs(standards): mirror doc-forge wiki style; mermaid + copyable build prompt
- move templates into src/templates; renumber wiki pages; add app-components page - embed agentic build prompt as a copyable markdown block; add mermaid diagrams - build.py writes <name>/mcp; config static bundle -> standards/mcp - registry reads libraries.json as bytes (committed file was UTF-16LE); normalize to UTF-8 - Dockerfile: drop stale blog copy; per-repo <name>/mcp copies - drop nested standards/mcp/standards duplicate and empty root mcp/
This commit is contained in:
@@ -1,54 +1,99 @@
|
||||
# Overview
|
||||
|
||||
## Summary
|
||||
|
||||
The blueprint is a **hexagonal (ports and adapters) application** with a
|
||||
The blueprint is a **hexagonal (ports & adapters) application** with a
|
||||
**spec-first** web edge and a **single composition root**. It favors explicit
|
||||
wiring over implicit magic, and it prefers existing internal libraries over
|
||||
hand-written infrastructure.
|
||||
wiring over implicit magic and existing internal libraries over hand-written
|
||||
infrastructure. Start here to build the mental model; the enforceable details
|
||||
live in the reference pages.
|
||||
|
||||
---
|
||||
|
||||
## The three layers
|
||||
## 🏗️ Architecture
|
||||
|
||||
```
|
||||
interfaces/ ← HTTP edge: thin handlers bound to an OpenAPI operationId
|
||||
domain/ ← business core: models, ports (interfaces), services, orchestrators
|
||||
infra/ ← adapters: databases, caches, external clients, hardware
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph EDGE["interfaces/ — HTTP edge"]
|
||||
OAS["openapi.yaml<br/>operationId contract"]
|
||||
RT["<resource>/routes.py<br/>thin handlers"]
|
||||
end
|
||||
|
||||
subgraph CORE["domain/ — pure business core"]
|
||||
MD["models"]
|
||||
PT["ports (abstract)"]
|
||||
SV["services"]
|
||||
end
|
||||
|
||||
subgraph INFRA["infra/ — adapters"]
|
||||
RP["mongo repos (mongo-ops)"]
|
||||
AD["cache · stores · llm · mail"]
|
||||
DB[("MongoDB")]
|
||||
end
|
||||
|
||||
CR["init.py<br/>composition root"]
|
||||
|
||||
OAS --> RT
|
||||
RT --> SV
|
||||
SV --> PT
|
||||
SV --> RP
|
||||
PT -. depends on .- RP
|
||||
CR --- RT
|
||||
CR --- SV
|
||||
CR --- RP
|
||||
RP --> DB
|
||||
AD --- CR
|
||||
```
|
||||
|
||||
Plus two optional layers:
|
||||
The rule holds at every edge: code in an outer ring may depend on a ring closer
|
||||
to the core, never the reverse. `domain/` never imports a web framework or a
|
||||
database driver.
|
||||
|
||||
```
|
||||
pipelines/ ← data-driven transformation graphs (extraction, enrichment)
|
||||
scripts/ ← operator scripts that reuse the composition root
|
||||
```
|
||||
> **Legend** — solid arrows are compile-time calls; dotted arrows are the
|
||||
> port/adapter contract, resolved by the composition root at startup.
|
||||
|
||||
## Core principles
|
||||
---
|
||||
|
||||
1. **One-way dependencies.** `interfaces -> domain -> infra` is allowed;
|
||||
the reverse is forbidden. The domain never imports a framework it does not
|
||||
own.
|
||||
2. **Ports in the domain, adapters in infra.** A service depends on an
|
||||
abstract port; the composition root injects a concrete adapter.
|
||||
## 🔄 The one-way dependency rule
|
||||
|
||||
| Ring | May import | Never imports |
|
||||
|-------------|------------------------------------|----------------------------------|
|
||||
| `interfaces/` | `domain`, framework glue (glue only) | business logic, `infra` directly |
|
||||
| `domain/` | nothing but its own ports | web frameworks, drivers, `infra` |
|
||||
| `infra/` | `domain` ports, drivers, libraries | — |
|
||||
| `init.py` | everything (the wiring point) | — |
|
||||
|
||||
---
|
||||
|
||||
## 🧭 Core principles
|
||||
|
||||
1. **One-way dependencies.** `interfaces -> domain -> infra` is allowed; the
|
||||
reverse is forbidden.
|
||||
2. **Ports in the domain, adapters in infra.** A service depends on an abstract
|
||||
port; the composition root injects a concrete adapter.
|
||||
3. **One composition root.** Nothing constructs its own dependencies. All
|
||||
wiring lives in one module (`init.py`) and is exposed as a flat resource
|
||||
registry.
|
||||
4. **Spec-first.** The HTTP contract is declared in an OpenAPI document. Route
|
||||
wiring lives in one module (`init.py`) exposed as a flat resource registry.
|
||||
4. **Spec-first.** The HTTP contract is declared in `openapi.yaml`; route
|
||||
handlers are looked up by `operationId`. There are no decorator routers.
|
||||
5. **Reuse the libraries.** Pipeline orchestration, DI, Mongo repositories,
|
||||
ingestion, auth, and docs are provided by internal libraries. Do not
|
||||
reimplement them — see the library registry.
|
||||
5. **Reuse the libraries.** Orchestration, DI, Mongo repositories, ingestion,
|
||||
auth, and docs come from internal libraries — see the [Library
|
||||
Registry](../lib/13_library_registry/).
|
||||
6. **Explicit state machines.** Long-running work moves through explicit,
|
||||
durable statuses and can pause for human input.
|
||||
|
||||
## Runtime processes
|
||||
---
|
||||
|
||||
A standard app may run as up to three processes that share the same
|
||||
composition root:
|
||||
## ⚙️ Runtime processes
|
||||
|
||||
| Process | Entry point | Responsibility |
|
||||
|---|---|---|
|
||||
| API | `main.py` | serve HTTP; start/stop resources via lifespan |
|
||||
| Worker | `worker.py` | poll durable jobs, run pipelines, publish progress |
|
||||
| Scripts | `python -m scripts.<name>` | one-shot operator tasks |
|
||||
A standard app may run as up to three processes that share the same composition
|
||||
root:
|
||||
|
||||
| Process | Entry point | Responsibility |
|
||||
|---------|------------------------|-------------------------------------------|
|
||||
| API | `main.py` | serve HTTP; start/stop resources via lifespan |
|
||||
| Worker | `worker.py` | poll durable jobs, run pipelines, publish progress |
|
||||
| Scripts | `python -m scripts.<name>` | one-shot operator tasks |
|
||||
|
||||
---
|
||||
|
||||
## ➡️ Read Next
|
||||
|
||||
- [02 – App Components](02_components.md) · [03 – Build Recipe](03_build_recipe.md)
|
||||
Reference in New Issue
Block a user