Design Rationale
Why No Database
The documentation system already has a data model. It has been refined over 15 months across 3,486 files. The directory structure IS the schema:
pages/
├── standards/ → 21 governance documents (STD-001 through STD-020 + template)
├── case-studies/ → 80 operational records (5 types)
├── patterns/ → 95 experiential knowledge entries (18 domains)
├── codex/ → 114 CLI reference cards (17 categories)
├── projects/ → 369 project documents (55 projects)
├── education/ → 808 learning materials (44% of the system)
├── sessions/ → 16 AI collaboration logs
├── 2026/ → 105 chronological worklogs
└── ... → 20 top-level categories total
Adding a database would create a copy. Copies drift. The filesystem is the single source of truth — the API reads from it directly and writes to it directly. When you create an incident through the API, the file appears in case-studies/incidents/ immediately. When you search, the API reads the actual files. There is no sync, no migration, no cache invalidation problem.
The only concession is an in-memory metadata cache loaded at startup. Titles, attributes, and file paths for all files are parsed once and held in a Python dict. Content is loaded on demand. The cache makes list operations instant. The filesystem makes writes durable.
The Stack
| Component | Why This One |
|---|---|
FastAPI |
Auto-generates OpenAPI schema. Every endpoint self-documents. Pydantic validation rejects malformed requests before they reach your code. Async by default. |
Pydantic v2 |
Type-safe models for every request and response. Enums enforce controlled vocabularies (P1-P4 severity, low-critical risk levels). Validation errors return structured JSON, not stack traces. |
uvicorn |
ASGI server. Starts in under 2 seconds. |
PyYAML |
Parses antora.yml for the 127 attributes that define every mutable value in the system. |
No ORM |
There is no database. |
How It Connects
Terminal (curl/jq) domus-api (FastAPI) Filesystem (AsciiDoc)
│ │ │
│ GET /search?q=mandiant │ │
├─────────────────────────►│ grep across cached files │
│ ├─────────────────────────────►│
│ │ 13 results, ranked │
│◄─────────────────────────┤ │
│ JSON response │ │
│ │ │
│ POST /case-studies/ │ │
│ incidents │ scaffold from template │
├─────────────────────────►│ validate via Pydantic │
│ │ write INC-2026-04-06.adoc │
│ ├─────────────────────────────►│
│◄─────────────────────────┤ │
│ {"id": "INC-...", │ │
│ "file_path": "..."} │ │
The API is a bridge between the terminal and the filesystem. It does not replace either. It makes the filesystem programmable without requiring the human to remember file paths, naming conventions, or template structures. The standards are embedded in the scaffolder service — STD-011 for incidents, STD-005 for changes, STD-010 for RCAs, STD-001 for projects. Compliance is automatic.
What This Enables
Today: curl -s localhost:8080/search?q=mandiant | jq finds 13 documents in milliseconds.
Tomorrow: Your Z Fold 7 queries the API over Tailscale. An Ollama model reads your documentation and answers questions in natural language. A webhook watches for resolved incidents and auto-scaffolds RCAs. A CI pipeline queries /standards to verify that every standard is Active before deploying.
The system scales because the architecture is simple. Add a spoke repository to the config and the API indexes it. Add an endpoint to a route file and it appears in the OpenAPI schema. The filesystem grows, the cache grows, the API grows. Nothing breaks because nothing is coupled.
This is not a prototype. It loaded 3,486 files in under 2 seconds. It serves responses in single-digit milliseconds. It runs on localhost with zero infrastructure. It was built in one session because the documentation system it exposes was built correctly in the first place.
The API did not make the documentation system valuable. The documentation system was already valuable. The API made it accessible.