Skip to content

Architecture Overview

Application Stack

Layer Technology Purpose
Framework Next.js 15 (App Router) Server-rendered React, API routes
Language TypeScript 5.7 (strict) Type safety across client and server
UI Material UI + Fastmarkets theme Data-dense editorial interface
Data Grid MUI X Data Grid / Charts Tables with sorting, filtering; sparklines
Database Prisma + AWS RDS SQL Server ORM with migrations
Auth NextAuth.js v5 (credentials) ADMIN / ANALYST roles, bcrypt passwords
AI Orchestration LangGraph.js Multi-step pipeline graphs
Observability Logfire Tracing and instrumentation

AI Services

Stage Purpose Providers
Transcription Audio → text AssemblyAI, Azure Speech, Whisper, ElevenLabs Scribe
Extraction Transcript → structured prices Gemini Flash, Claude Haiku, GPT-5.2
Review Extraction quality scoring Gemini Flash, Claude Haiku, GPT-5.2
Assessment Observations → assessed prices Gemini Flash, Claude Haiku, GPT-5.2

All AI services are abstracted behind interfaces (ITranscriptionService, IExtractionService, etc.) so providers can be swapped via environment variables. See AI Pipeline for details.

Infrastructure

Component Technology Purpose
Compute AWS App Runner Serverless container hosting
Database AWS RDS SQL Server Private subnet, VPC connector
Container Registry AWS ECR Docker image storage
DNS / CDN Cloudflare DNS, caching
Security Cloudflare Access (Zero Trust) JWT-based gateway authentication
CI/CD GitHub Actions Build, test, deploy
IaC Terraform Infrastructure provisioning
Secrets AWS Secrets Manager Sensitive configuration

Data Model

Key entities and their relationships:

erDiagram
    MarketAssessmentGroup ||--o{ Market : contains
    MarketAssessmentGroup ||--o{ Assessment : has
    Market ||--o{ PriceObservation : receives
    Market ||--o{ FinalMarketPrice : produces
    Contact ||--o{ PriceObservation : provides
    Contact ||--o{ ContactMarket : "linked via"
    Market ||--o{ ContactMarket : "linked via"
    Assessment ||--o{ FinalMarketPrice : groups
    Assessment ||--o| AiAssessmentResult : "AI output"
    Assessment ||--o{ AssessmentObservationExclusion : overrides
    PriceObservation ||--o{ AssessmentObservationExclusion : "overridden by"
    User ||--o{ Assessment : assesses
    User ||--o{ PriceEntryForm : captures
    PriceEntryForm ||--o{ PriceObservation : sources
    Contact ||--o{ PriceEntryForm : "call with"
Entity Purpose
MarketAssessmentGroup (MAG) Collection of related markets (e.g., Cobalt-London)
Market Individual commodity market with unit, location, methodology
Contact Person who provides market intelligence
PriceObservation Decoupled price data point from any source (calls, imports, chat)
PriceEntryForm A call/capture session with a contact
FinalMarketPrice Published price assessment for a market
Assessment Groups final prices for a MAG within a date range
AiAssessmentResult Structured AI output (per-market results, summary, rationale)
AssessmentObservationExclusion Per-assessment include/exclude override for an observation (takes priority over global discarded flag)

Full schema: prisma/schema.prisma

API Routes

Domain APIs

Route Methods Purpose
/api/mags GET, POST Market Assessment Groups
/api/mags/[id] GET, PUT, DELETE MAG detail
/api/mags/[id]/assessment-readiness GET Assessment readiness status
/api/markets GET, POST Markets
/api/markets/[id] GET, PUT, DELETE Market detail
/api/markets/price-history POST Historical prices for a market
/api/markets/resolve POST Market name → ID resolution
/api/contacts GET, POST Contacts
/api/contacts/[id] GET, PUT, DELETE Contact detail
/api/contact-markets GET, POST Contact–market relationships
/api/price-observations/[id] GET, PATCH Observation include/exclude toggle
/api/price-entry-forms GET, POST Call sessions
/api/price-entry-forms/[id]/complete POST Complete post-call review
/api/final-market-prices GET, POST Published prices

Assessment APIs

Route Methods Purpose
/api/assessments GET, POST Assessment list and creation
/api/assessments/[id] GET, PUT, DELETE Assessment detail
/api/assessments/[id]/observations GET Observations grouped by market
/api/assessments/[id]/observations/[observationId] PATCH Per-assessment observation exclusion toggle
/api/assessments/[id]/ai-inputs GET AI input data (observations + related context)
/api/assessments/[id]/run-ai POST Trigger AI assessment workflow
/api/assessments/[id]/amend PATCH Amendment workflow
/api/assessments/[id]/reference-prices GET Reference prices for assessment

Eval Pipeline APIs

Route Methods Purpose
/api/eval/run POST Run full pipeline
/api/eval/run-stream POST Run pipeline with SSE progress
/api/eval/transcription POST Transcription step
/api/eval/extraction POST Extraction step
/api/eval/review POST Review step
/api/eval/evaluation POST Evaluation step
/api/eval/results GET Result retrieval
/api/eval/results/list GET List all results

Other APIs

Route Methods Purpose
/api/health GET Health check (public)
/api/auth/[...nextauth] GET, POST Authentication
/api/users GET, POST User management (ADMIN)
/api/notifications/price-inbox GET Unreviewed chat-sourced prices
/api/test-audio/* various TTS generation and test audio

Project Structure

luminarium-proof/
├── src/
│   ├── app/              # Next.js App Router (pages + API routes)
│   ├── components/       # React components (AppShell, AI panels, shared/)
│   ├── features/         # Feature modules (admin pages, auth, MUI theme)
│   ├── services/         # Backend services (see AI Pipeline docs)
│   ├── cli/              # E2E evaluation pipeline CLI
│   ├── lib/              # Shared utilities (db, ai-config, logfire)
│   ├── utils/            # Domain utilities (date, assessment-period)
│   ├── hooks/            # React hooks (use-debounce)
│   └── context/          # React contexts (EffectiveDateContext)
├── configs/              # Commodity configuration YAML
├── prompts/              # LLM prompt templates
├── prisma/               # Schema, migrations, seed scripts
├── test-data/            # Test cases, golden records, audio profiles
├── infra/                # Terraform (managed by infra owners)
├── docs/                 # MkDocs documentation (this site)
└── .rules/               # Coding standards

Request Flow

  1. User navigates to luminarium-proof-dev.luminarium.ai
  2. Cloudflare Access intercepts, authenticates (email OTP or Google SSO)
  3. Cloudflare issues JWT → request forwarded to App Runner
  4. Next.js middleware validates JWT using embedded public keys
  5. NextAuth session provides application-level auth (ADMIN/ANALYST roles)
  6. API routes use Prisma for database queries via VPC connector to RDS
  7. AI pipeline calls go through LangGraph graphs → provider services → external APIs