Delorean docs

Architecture

The stack and its exchanges

A cart written in free text leaves the browser, goes through the BFF, then through the API, which reads it in seven stages, two of them side by side. The models read, through OpenRouter; the code counts and sets the price; every request leaves a trace in Langfuse.

Open the stack diagram (Claude artifact)

Services and what they exchange

Client Web · BFF API · one contract Models · traces Browser the cart in free text web · Next.js 16 :24790 React 19 UI BFF /api/quotes /api/catalog Session: sealed cookie a username, no password ◆ typed openapi-fetch client Go API :24791 Go 1.26 · trpc-agent-go v1.11 prepare code guard Jev ×2 parse GPT-6 Luna recount DeepSeek V4.1 Flash identify Jev ×N judge Jev ×(2L+1) + code price code ◆ generated server (oapi-codegen) Python API :24792 · FastAPI TypeScript API :24793 · Hono OpenRouter one key, three models Jev 1.13 typed choices, calibrated confidence /api/alpha/decisions GPT-6 Luna DeepSeek V4.1 Flash strict JSON output, same prompt /api/v1/chat/completions Langfuse 4 :24794 web + worker, self-hosted Postgres 17 ClickHouse Redis 7 MinIO project delorean fetch /api/* + cookie POST /v1/quotes GET /v1/catalog X-User-Id X-Session-Id X-Request-Id Quote problem+json QUOTERS by name guard ×2 identify ×N judge ×(2L+1) typed answers + confidence parse ×1 · recount ×1 titles, quantities traces OTLP Development tooling cases/ 339 shared JSON cases a note names the mistake guarded e2e/ E2E suite + system bench ◆ every response validated (Ajv) cmd/bench guard · identify · reading · judge calls OpenRouter if RUN_LIVE=1 BASE_URL any quoter read by datasets, experiments the benches read the same cases
The browser only talks to the BFF; only the BFF knows where the APIs are, and it adds the session's identity. The API alone calls OpenRouter and writes traces. The two planned APIs will plug into the same contract, and the same suite will validate them.

The path of a quote

What POST /v1/quotes does with example 5 of the brief: the three volumes and La chèvre. Every stage may refuse the cart with a stable code; the models never set an amount.

a model failure, or an answer outside its contract → 502 engine_unavailable HTTP body code size, schema prepare code ≤ 2048 tokens guard Jev ×2 order? steer? parse Luna ×1 recount DeepSeek ×1 identify Jev ×4 1 per distinct title judge Jev ×9 + code worst score ≥ 0.5 price code integer cents 400 malformed_request 413 payload_too_large 422 empty_cart 422 too_long 422 injection 422 invalid_request 422 no_film 422 quantity_too_large no refusal 422 unfaithful_reading 200 Quote 56.00 € For example 5: N = 4 distinct titles, L = 4 lines read, so 15 Jev calls (2 + 4 + 9) and 2 LLM calls (parse, recount) before the price.
The judge asks one question per observable fact (is this film asked for, is it the film identified, is one missing), the code compares the reading with the recount film by film (count), and the worst score decides. The recount never sets the price. An injection that got past the guard could at worst misfile a title among four options: it never reaches the amount.

The stack, layer by layer

LayerTechnologiesRole
ContractOpenAPI 3.1 oapi-codegen 2.8 openapi-typescript 7The source of truth. The Go server and the web and e2e types are generated from it; CI refuses any drift. Every word put to a model lives in prompts/, shared the same way.
WebNext.js 16.3 React 19.3 iron-session 9 openapi-fetch CSS ModulesThe UI and the BFF: the session, the quoter picked by name, one French message per refusal.
Go APIGo 1.26 net/http log/slog o200k_base, O(n log n) mergeThe pipeline, pricing in cents, RFC 9457 errors. The tokenizer is compiled in: counting needs no network.
TypeScript APINode 26 Hono openai Ajv js-tiktoken ranksThe same pipeline on Node, run from its .ts files with no build step. Every model answer is checked against the schema.
Python APIPython 3.14 uv FastAPI httpx openai tiktoken mypy --strictThe same pipeline on asyncio. The tokenizer's vocabulary is fetched once against a pinned checksum, and never at runtime.
Agents and modelstrpc-agent-go 1.11.2 OpenRouter Jev 1.13 GPT-6 Luna DeepSeek V4.1 FlashJev decides (guard, identify, judge); Luna extracts under a strict schema and DeepSeek recounts with the same prompt; trpc-agent-go carries the agent, the traces and the evaluation.
ObservabilityLangfuse 4 OpenTelemetry Postgres 17 ClickHouse 25.12 Redis 7 MinIOOne trace per request, one span per stage; the benches keep their datasets and experiments there.
Tests and benchesgo test -race pytest Vitest 5 Testing Library Ajv 2020-12Deterministic fake engines in CI; live benches only with RUN_LIVE=1.
ToolingTask Docker Compose GitHub Actions golangci-lint 2 ESLint PrettierOne command per gesture: task ci, task e2e, task langfuse:up, task bench, task docs.

Loading docs/architecture.md…