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