Genericity Matrix
Summary
This page states precisely what is library-backed, what is template-provided, and what is app-specific and must be authored. Use it to scope a new build and to know, for any given capability, whether to call a library, copy template code, or write it yourself.
Tier A — Library-backed (use; never reimplement)
These capabilities already exist as internal libraries. Reach them through the
library registry MCP (find_library(capability)) and read the library's own MCP
for its API. Writing a private copy of any of these is a defect.
| Capability | Library | MCP |
|---|---|---|
| Persistence: repositories, cache, populate, transactions | Mongo Ops (mongo_ops) |
:8007 |
| Dependency injection / composition | Hexa (hexa) |
:8008 |
| Deterministic multi-step transformation engine | DAG Pipe (dagpipe) |
:8006 |
| Spec-first HTTP edge, client, codegen | OpenAPI First (openapi_first) |
:8004 |
| Format-agnostic fetch + parse (HTML, PDF, CSV, XLSX) | Omniread (omniread) |
:8003 |
| Read-only email ingestion | Mail Intake (mail_intake) |
:8002 |
| JWT auth primitives (register, login, introspect) | Py JWT (jwtlib) |
:8005 |
| Documentation build (MkDocs + MCP) | Doc Forge (docforge) |
:8001 |
Tier B — Template-provided (copy from templates/app, then adapt)
These are reusable internal components shipped inside the template — they are
not independent libraries. Copy them as-is, then rename/populate only what is
app-specific. They give every app the same wiring shape as the reference app.
Fetch them by kind with get_app_component, or the whole tree with
get_app_template.
| Component | Template location | Action | Shipped |
|---|---|---|---|
| Layering & dependency rule | the package layout + import rules | keep | ✅ |
| Composition root shape | init.py (get_svc/get_db, idempotency) |
keep | ✅ |
| Spec-first web edge | interfaces/openapi.py, thin handlers bound to operationId |
keep | ✅ |
| CRUD slice pattern | domain/<resource>/{models.py, ports/db.py, ports/service.py, converters.py} |
rename + fill | ✅ |
| Generic CRUD service | infra/adapters/service.py (CrudsServiceAdaptor) |
keep | ✅ |
| Repository factory | infra/db/repos/mongo.py (_repo_factory) |
keep | ✅ |
| Worker poll + status loop | worker.py |
keep | ✅ |
| Progress bus | infra/adapters/sse.py (keyed in-memory bus) + an app SSE endpoint |
keep | ✅ |
| HTTP response cache | infra/http_cache.py (cache_response + generation invalidation) |
keep | ✅ |
| Key-value store | infra/adapters/kv.py (port + in-memory + Redis adaptor) |
keep | ✅ |
| Pipeline scaffold | pipelines/shared/{ports,loader,registry}.py + pipelines/<family>/ |
rename + fill | ✅ |
| Operator scripts | scripts/ (init() / get_svc() / shutdown()) |
rename | ✅ |
| Testing harness | integration fakes + fixture-parity pattern | keep | ✅ |
| Project scaffolding | pyproject.toml, Dockerfile, docker-compose.yaml, .env.example, openapi.yaml |
rename + fill | ✅ |
Tier B (patterns) — port from the reference app
A few Tier B capabilities are real and reusable, but are shaped by the app or the provider, so the template does not ship them verbatim — copying them blindly would carry app-specific names. Treat them as patterns: lift the shape from the reference app and rename per app.
| Component | Reference location | Action | Shipped |
|---|---|---|---|
| Human-in-the-loop | durable pause + question document + resolve endpoint + resume map | port + reshape | ✗ |
| LLM client pool | provider-select + retry/rotation pool scaffold | port + reshape | ✗ |
Tier C — App-specific (must be authored)
| Artifact | Why |
|---|---|
| Resource models | the business shape |
| Repository populate/cache rules | the relationships |
| Service business logic | domain behaviour |
| Pipeline families | the transformation graph |
| Pattern/rule resources | data-driven policy |
| Fixtures & golden outputs | test data |
The two axes
Everything app-specific reduces to two axes:
- Resource model — the set of resources, their fields, relationships, and the OpenAPI contract.
- Pipeline family — only if inputs require multi-step transformation.
If you can specify those two axes, the rest of the app follows mechanically: Tier A is imported, Tier B is copied, and Tier C is the only thing you author.