Skip to main content

Architecture Overview

This document describes the system architecture of the C_AI Platform, a compliance intelligence platform for regulatory license readiness.

System Layers

┌─────────────────────────────────────────────────────────────┐
│ Client Layer │
│ React + Vite + TailwindCSS + Radix UI │
│ client/src/ │
├─────────────────────────────────────────────────────────────┤
│ API Layer │
│ Express REST API │
│ server/routes.ts │
├─────────────────────────────────────────────────────────────┤
│ Service Layer │
│ Assessment Pipeline | Pack Resolver | Vector Store │
│ server/lib/ │
├─────────────────────────────────────────────────────────────┤
│ Data Layer │
│ PostgreSQL + pgvector | Drizzle ORM │
│ shared/schema.ts | server/db.ts │
├─────────────────────────────────────────────────────────────┤
│ Observability Layer │
│ OpenTelemetry → Phoenix (Arize) │
│ server/lib/tracing.ts │
└─────────────────────────────────────────────────────────────┘

Key Directories

DirectoryPurposeKey Files
client/src/React frontendApp.tsx, pages/, components/
server/Express backendroutes.ts, storage.ts, db.ts
server/lib/Business logic servicesassessmentPipeline.ts, packResolver.ts
shared/Shared types and schemaschema.ts, constants.ts
docs-site/Documentation (Docusaurus)docs/, docusaurus.config.ts

(Verified: directory structure via ls command)

Core Subsystems

1. Evidence Ingestion Pipeline

Handles document upload, text extraction, chunking, and vector indexing.

Entry point: server/routes.tsPOST /api/documents/upload (line 88 defines 100MB limit)

Processing flow:

  1. Uploadserver/lib/evidenceStorage.ts stores file with SHA256 hash
  2. Extractserver/lib/contentExtractor.ts extracts text from PDF/DOCX/XLSX
  3. Chunkserver/lib/chunker.ts splits text into indexed segments
  4. Embedserver/lib/embeddings/openai.ts generates 1536-dimensional vectors
  5. Indexserver/lib/vectorStore.ts stores embeddings in pgvector

Status enum: EvidenceStatus in shared/schema.ts:160-167 tracks lifecycle:

  • UPLOADED → EXTRACTED → PARSED → INDEXED → READY (or FAILED)

2. Assessment Pipeline

Evaluates evidence against requirements using LLM and vector search.

Entry point: server/lib/assessmentPipeline.ts

Key functions:

  • startAssessmentRun() (line 92) - Creates run, resolves pack binding, processes requirements
  • checkForInProgressRun() (line 80) - Prevents concurrent runs per tenant

Processing per requirement:

  1. Generate embedding for requirement text
  2. Vector search for similar chunks (server/lib/vectorStore.ts:59-80)
  3. LLM evaluation with retrieved context (server/lib/llmProvider.ts)
  4. Store assessment with status, confidence, citations

Status enum: AssessmentStatus in shared/schema.ts:318-323:

  • COMPLETE | PARTIAL | MISSING | FAILED

3. Pack Resolution System

Resolves effective configuration bindings for a tenant+pack+environment.

Entry point: server/lib/packResolver.ts

Key functions:

  • resolvePackBinding() (line 25) - Resolves criteria, corpus, engine bindings
  • createRunSnapshot() (line 107) - Creates snapshot for deterministic replay

Resolved bindings (EffectivePackBinding interface, lines 12-23):

  • criteriaVersionId - Which criteria set version to use
  • corpusActivationId - Which regulatory corpus activation
  • retrievalVersionId, promptVersionId, chunkingVersionId, agentVersionId - Engine configs

4. Tenant Isolation

All data operations are scoped by tenant_id.

Security helpers in server/routes.ts:107-172:

  • resolveTenantSecure() - Resolves tenant from session with security checks
  • requireTenant() - Express helper that returns 400/403 on missing/invalid tenant

Hard rules:

  • No silent fallbacks - missing tenant returns error
  • Query param override requires SUPER_ADMIN_MODE=true AND SUPER_ADMIN role
  • Every DB query must include tenant_id in WHERE clause

5. Observability

Distributed tracing via OpenTelemetry exported to Phoenix (Arize).

Entry point: server/lib/tracing.ts

Key functions:

  • initTracing() (line 117) - Initializes OTLP exporter
  • startRunSpan() (line 178) - Creates root span for assessment run
  • startStepSpan() (line 197) - Creates child span for processing steps
  • recordLLMCall() (line 305) - Records LLM usage metrics

Allowed attributes: Lines 7-47 define allowlist for trace attributes (prevents PII leakage)

Phoenix endpoint: Configured via PHOENIX_OTLP_ENDPOINT env var (default: http://localhost:6006/v1/traces)

Request Flow Example

User uploads document


POST /api/documents/upload (server/routes.ts)


uploadAndProcess() (server/lib/pipeline.ts)

├─► evidenceStorage.saveFile()

├─► contentExtractor.extract()

├─► chunker.chunk()

└─► vectorStore.storeEmbedding()


Document status: READY


User triggers assessment


POST /api/runs (server/routes.ts)


startAssessmentRun() (server/lib/assessmentPipeline.ts)

├─► resolvePackBinding() (server/lib/packResolver.ts)

├─► For each requirement:
│ ├─► vectorStore.searchSimilar()
│ ├─► llmProvider.evaluate()
│ └─► db.insert(assessments)

└─► captureReplaySnapshot() (server/lib/adminService.ts)


Run status: COMPLETED

Database Architecture

See Data Model for full schema reference.

Key tables (defined in shared/schema.ts):

TablePurposeKey Columns
tenants (line 39)Multi-tenant isolationid, name
packs (line 67)Requirement packsid, name, regulator_code
documents (line 192)Evidence filestenant_id, status, sha256_hash
chunks (line 236)Text segmentsdocument_id, content, token_count
runs (line 330)Assessment runstenant_id, pack_id, status, snapshot_*
assessments (line 419)Requirement evaluationsrun_id, status, confidence, citations

Environment Configuration

VariablePurposeDefault
DATABASE_URLPostgreSQL connectionRequired
OPENAI_API_KEYEmbeddings and LLMRequired
PHOENIX_OTLP_ENDPOINTTracing endpointhttp://localhost:6006/v1/traces
APP_ENVIRONMENTDEV/STAGING/PRODDEV
SUPER_ADMIN_MODEEnable cross-tenant accessfalse
Legacy identifier

Legacy (internal identifier): the current codebase uses WALLY_ENVIRONMENT as the environment variable name.

(Verified: server/routes.ts:99, server/lib/tracing.ts:120, server/lib/assessmentPipeline.ts:118)