Architecture
The services, the database, and where the code lives.
people ──► web UI ─┐
├──► FastAPI app ──► PostgreSQL (model, versions, search index, users, audit, activity, settings; schema `library`: collections, sources and their chunks, source wikis and their chunks, topics and their chunks, claims, links, jobs)
agents ──► /mcp ───┘ │
├──► embedding model (in the container)
├──► job workers (in the app, or the optional worker container)
├──► file storage (data folder, or the S3 bucket: optional container or your own)
├──► browser service (optional container, isolated, for JavaScript pages)
├──► chat model (OpenRouter, for Alfred)
└──► your database (connector, read-only) or the built-in demo database
One PostgreSQL database with pgvector holds the model, its versions, the search index and the app's own data; no separate graph or vector store is needed at this scale (thousands of chunks, an exact vector scan; tens of entities and hundreds of joins, an in-memory graph). The model is stored as rows per version (entity, field, relationship, example); the Library lives in its own schema, library, in the same database; search chunks are derived from it and never edited. The query planner and the join-path finder are deterministic code. Database-specific behaviour (connecting, structure, dialect, masking expression, forbidden functions) lives in one driver class per database kind; SQL is parsed and generated with sqlglot. The UI is React, served by the app.
| Area | Code (backend/studio/) |
|---|---|
| Model storage, versions, editing | ontology.py, versions.py, editing.py, excel_io.py, modelview.py |
| Search | chunker.py, indexer.py, embeddings.py, search.py |
| Tools, planner, MCP, Alfred | tools.py, planner.py, graph.py, filtermatch.py, mcp_server.py, alfred.py, llm.py |
| Data access | connectors.py, drivers.py, datastore.py, enforce.py, reverse.py |
| Model check, demo data | conformance.py, databuild.py, synth/ (generic.py generates, ddl.py derives tables, load.py loads, export.py copies) |
| Users, access, limits, settings, activity | auth.py, access.py, clientinfo.py, ratelimit.py, settings.py, activity.py |
| API, configuration, schema | api.py, config.py, db.py, schema.sql |
| Library (documents, topics, bridge) | library/: api.py, scope.py (access), jobs.py, pipeline.py, wiki.py, topics.py, bridge.py, agent.py, retrieval.py, interview.py, export.py, fetch.py, netguard.py, storage.py, schema.sql (schema library); worker.py and fetcher.py (optional browser service) in studio/ |
App tables (schema.sql, applied at startup): ontology_version, entity, field, relationship, example, meta (the model per version); chunk, embedding_cache (search); audit_log; app_user, session, api_token, login_attempt (access); question_log; data_build (demo database builds); connector; app_setting (Settings page values); activity_session, activity_event. The Library's tables are in the library schema (library/schema.sql): collections and grants, sources, jobs, passages, source-page versions and checks, topics with versions, aliases, links and sources, statements with their evidence, the vocabulary and its proposals, conflicts, redirects, health runs, model links and interviews.
HTTP API: the UI's own API under /api (signed-in cookie; admin routes under /api/admin), the MCP endpoint at /mcp (bearer token), /api/health. The Excel template and exports are /api/template.xlsx and /api/export.xlsx?version=published|draft.