Skip to content

Architecture overview ​

Status: slice 34 · October 2026.

Locus is a multi-service platform for arranging, lending, investing in, and legally reviewing debt in the CEMAC zone. The architecture deliberately separates presentation, durable truth, heavy deterministic computation, and immutable document storage. This page gives the topology, ports, request paths, and a reading map into the rest of the site.

Topology ​

mermaid
flowchart TB
  subgraph clients [Clients]
    Bank[locus-web :3000]
    Ops[locus-ops :3001]
  end
  subgraph sor [System of record]
    API[locus-backend :5000]
    PG[(PostgreSQL)]
    Redis[(Redis)]
  end
  Workers[locus-workers :8000]
  R2[(Cloudflare R2)]

  Bank -->|Bearer AuthSession| API
  Ops -->|Bearer AuthSession| API
  API --> PG
  API --> Redis
  API -->|analyze / OCR| Workers
  Bank -->|tenant PDFs| R2
  Ops -->|vault PDFs| R2
  API -.->|artifact meta| R2

Additional edges not drawn above:

  • locus-web also calls locus-workers directly for OCR escalation (POST /api/v1/ocr, via LOCUS_WORKER_URL) when native text and printable-harvest extraction are insufficient.
  • locus-web uses Redis (BullMQ) for DOCUMENT_OCR, CONTRADICTION_SCAN, and MEMO_COMPILATION jobs; locus-backend uses Redis for RedisAnalysisJobStore.
  • The backend can host the Watchtower loop (LEGAL_VAULT_WATCHTOWER_INTERVAL_MINUTES), which fetches regulator listing pages.
  • An optional LLM provider (COPILOT_LLM_PROVIDER) is called from locus-web for prose polish only.

Services and ports ​

ServiceRoleDefault portStack
locus-webBank UI (/workspace/*) + BFF /api/locus/*, auth cookie mint, document upload, copilot, exports proxy3000 (Docker image defaults PORT=3002)Next.js 15 App Router, React 19, TypeScript, Bun tests
locus-opsPlatform operator UI + regulatory / access-request / market BFF3001Next.js 15, Bun
locus-backendSystem of record API, EF Core, migrations, seed (off by default), Watchtower host5000ASP.NET Core 10, EF Core, Npgsql
locus-workersOCR (Tesseract fra+eng), SYSCOHADA extract, full analysis, fixed-income math8000Python 3.12, FastAPI
PostgreSQLRelational state, RLS, FTS5432Coolify managed in production
RedisDurable queues / job store6379Coolify managed in production
Cloudflare R2Immutable PDFs (S3 API)—Tenant deal room + platform vault

Local start: Deploy & environment (./start-services.sh launches workers, backend, and web; start locus-ops separately).

Request paths you should know ​

Authenticated bank request ​

text
Browser → middleware (locus_session ticket)
  → /workspace/** SSR or /api/locus/* BFF
  → requireBffSession + enforceRbacGuard (+ Zod validation)
  → Authorization: Bearer <sessionId> + X-Organization-Id (from session)
  → locus-backend InstitutionalAuthMiddleware → claims → controller RequirePermission
  → EF query filters + FORCE RLS GUCs → PostgreSQL

Dossier → OCR → analysis ​

text
Deal Room upload → SHA-256 → R2 (encrypted) → POST /api/documents
  → extract pages (native | harvest | Tesseract worker) → ExtractedPages + Citations
  → SYSCOHADA cells / ratios → FinancialStatements, ExtractedCells, RatioSnapshots
Enqueue analysis (POST /api/locus/deals/{id}/analysis → 202 + Location)
  → AnalysisOrchestrator → Python worker /api/v1/analyze
  → Contradictions, Blockers, Alerts; poll /api/locus/analysisjobs/{jobId}

Full detail: Dossier → OCR → analysis. Analysis jobs replaced the old synchronous child_process.exec() bridge: long workloads (30 s – 4 min) return 202 Accepted and are tracked QUEUED → PROCESSING → COMPLETED; the worker returns a typed AnalysisResult (metrics, covenants, findings, sources, artifacts). Next.js never spawns OS subprocesses.

Platform operator request ​

text
locus-ops (locus_ops_session) → requireOpsSession → SoR /api/admin/regulatory/* | /api/access-requests/* | /api/market/ingest
  → PLATFORM_OPERATOR + system:manage → platform legal tables / onboarding / tenant-targeted market ingest

Tenant read of platform law ​

text
Bank finding carries vault ids → GET /api/legal-vault/resolve → open-statute BFF
  → hash-verified PDF stream (regulatory:read)

See Legal vault & Watchtower.

Monorepo layout ​

text
locus/
├── locus-web/          # Next.js bank app (UI + BFF + TS domains + copilot)
├── locus-ops/          # Next.js ops app (vault, onboarding, market ingest)
├── locus-backend/      # ASP.NET Core SoR (controllers, EF, migrations, seed)
├── locus-workers/      # Python FastAPI (OCR, extract, analyze, FI)
├── docs-site/          # This documentation (VitePress)
├── docs/               # Legacy markdown stubs → point here
├── data/regulatory/    # CI vault fixtures (not production law)
├── config/regulatory-sources/
├── scripts/            # attach-vault-fixtures.sh, backup-and-migrations-verify.sh, fixture generator
├── run-all-tests.sh · start-services.sh
└── IMPLEMENTATION_TRACKER.md

Design principles ​

  1. C# SoR owns durable state; Next never opens Postgres directly for product writes.
  2. Bearer session > spoofable headers (dev headers only when Auth:AllowDevHeaders).
  3. Fail closed — empty tenant stays empty; no cross-tenant demo injection; production refuses plaintext documents and in-memory queues.
  4. Zero LLM math — ratios, contradictions, FI pricing are deterministic code; the LLM only polishes prose.
  5. Human publish gate for legal editions — discovery ≠ in-force law.
  6. Two libraries, never mixed — platform statutory vault vs tenant deal room.
  7. One engine, many editions — editions switch modules and home questions; they do not fork business logic.

Design decisions (rationale) ​

  • C# SoR instead of Prisma inside Next — clean UI / durable-truth split, AuthSessions, tenant filters in EF, institutional migrations.
  • Bearer session instead of spoofable headers — org and role come from the session at both BFF and SoR.
  • R2 instead of local disk — private object vault, checksums, presigned or proxied reads.
  • Workers in Python — quant, PDF, curve ecosystem; C# orchestrates and persists.
  • Copilot = tools + retrieval + optional LLM — suitable for credit committees; no hallucinated DSCR.

Reading map ​

If you are…Start withThen
New to the productWhat Locus isHow to read, Glossary
Changing a serviceThe service page: web · ops · backend · workersThe matching flow
Touching auth or permissionsTrust boundariesAuth & sessions, Security
Touching persistenceData storeslocus-backend
Working on analysisDossier → OCR → analysisSYSCOHADA & ratios, Contradictions, Citations
Working on legal textLegal vault & WatchtowerRegulatory analyze, Regulatory fixtures, Regulatory admin
Operating the platformOps overviewAccess requests, Market ingest, Deploy
Explaining a screenWorkspace route mapFull guide
DeployingDeploy & environmentOCR override SOP, Doc map & deferred work

Source of trust for Locus. If this conflicts with code, code + IMPLEMENTATION_TRACKER.md win.