Architecture
Git is canonical. YAML is validated against JSON Schema and Pydantic, cross-record integrity is checked, then a single transaction synchronizes PostgreSQL. The API and website read PostgreSQL; exports read the validated canonical snapshot bundled in the same release. Neo4j is an optional projection and never required for the web process.
Git / YAML → JSON Schema + semantic validation → CI / human review
├─ atomic import → PostgreSQL → FastAPI → Jinja atlas / clients
├─ release exports → YAML / JSON / CSV
└─ graph projection → optional Neo4j
The Jinja website keeps one deployable container and avoids a frontend build or client-side data cache. Forms and links work without JavaScript. Swagger/ReDoc use their framework-provided documentation assets; the atlas itself uses only local CSS and a favicon.
Relational design
Entities use a shared identity table with indexed kind, slug, name, evidence status, valence, and family. UUIDv5 identifiers are deterministically derived from namespaced IDs. The validated type-specific payload is retained as JSON for round trips. Relationships, claims, claim-source stances, and expert reviews are normalized into foreign-key tables. This is a deliberate hybrid rather than eleven sparse entity tables; no relations rely on numeric IDs or JSON-only joins.
The importer validates before touching the database, serializes PostgreSQL writers with a transaction advisory lock, reconciles a complete snapshot, and commits atomically. Re-importing produces the same identities and content digest. Deleted canonical records are removed from the projection; use deprecation for publicly referenced concepts. Readers see the old or new transaction, never a partially imported state.
Schema migration and data import are separate operational steps, combined by the bootstrap command for local convenience. Production migrations should remain additive while old app instances are serving. The web process never automatically migrates or imports on startup.
Operational boundaries
SQLite is a local test/development fallback, not the production target. Docker Compose and CI exercise PostgreSQL. SQLAlchemy uses bounded pooled connections and connection liveness checks. API requests are read-only; a production deployment should use a SELECT-only web credential and a separately managed migration credential.
The built-in rate limiter is bounded and per process. For replicas, deploy a trusted edge quota service; do not treat this limiter as distributed accounting. Authentication and billing are intentionally absent. Add API key resolution and usage accounting at the request-policy boundary in later versions.
Canonical downloads are cached for a process lifetime. Deploy a fresh process together with each canonical import. The source commit is unknown until built from a Git commit; content digest remains available in API metadata.
Semantic search readiness
A future entity_embeddings table can reference entities.id, dataset digest, provider/model ID, embedding dimension, creation time, and text hash. Add pgvector by migration, backfill asynchronously, and invalidate vectors when the source text hash changes. Embeddings are derived indexes, never canonical claims. Hybrid lexical/vector ranking must preserve provenance and filters. No embedding service or pgvector extension is needed in v0.1.