AI-assisted intake of quote requests for industrial sales teams: extract structured data from e-mails and PDF/Excel/Word attachments, review every value beside its source, and export each approved request exactly once to an ERP.
Status: pilot scope built and released as v0.1.0 (2026-09-28); acceptance pending (roadmap, M2). A synthetic showcase runs on Vercel for invited visitors. Reference project: built like a real customer engagement for a mid-sized machine-building company; the customer is fictional and all data in this repository is synthetic.
upload (.eml/.msg/PDF/XLSX/DOCX) → parse → extract with evidence → verify grounding
→ review & correct beside the source → approve / reject → idempotent export to the ERP (mock)
- No invented data: the model must quote its source; a deterministic verifier checks that the quote exists in the cited segment – otherwise the value is flagged for review.
- Nothing lost, nothing doubled: jobs are enqueued in the same database transaction as the status change; the export uses an idempotency key, a unique export record and a row lock.
- Tenant isolation: repository scoping plus forced PostgreSQL row-level security per company.
- Measurable AI quality: an eval set with per-field metrics gates prompt and model changes.
Each line is a merged PR; details in the CHANGELOG.
- Invite-only login, companies, user and role management for admins; forced row-level security on every
company-data table (schema
app), guarded by a test (#31, #37, #38) - Upload of
.eml,.msg, PDF (scanned pages via OCR whenAI_PDF_OCR=auto, marked as such), XLSX and DOCX, several files per request; duplicates flagged and decided in the UI (#32, #40, #44) - AI extraction of the header fields and line items with a grounding verifier (#33, #39)
- Review beside the source with a status per value, audited corrections, approve or reject (#35, #42)
- Exactly-once export of the reviewed values and positions to the ERP mock (#36, #54)
- Request list led by the next action, with diagnosis, retries and reprocessing, paged (#43, #58, #95)
- Eval set of 15 synthetic cases as a CI gate (#41); correlated structured logs and health (#45, #56, #88)
- Showcase: prepared sample requests replayed from recorded AI answers (#83)
TypeScript modular monolith (Next.js, Node 24, Drizzle, PostgreSQL 17, pg-boss, Better Auth, S3 API) plus a stateless Python AI service (FastAPI, docling, Gemini on Vertex AI in the EU; the showcase uses the Gemini API free tier with synthetic data only – a dated exception, ADR-0001 D11). Rationale, alternatives and trade-offs: ADR-0001.
| Topic | Where |
|---|---|
| Architecture map and exceptions register | docs/technical/architecture.md |
| Decisions | docs/decisions/ |
| Project brief, roadmap | docs/product/ |
| Customer proposal (German) | docs/product/pilot-vorschlag.md |
| Discovery and approvals (German) | PROJECT-START.md |
| Working rules for humans and agents | AGENTS.md |
Requirements: Docker, Node 24 with corepack (corepack enable → pnpm 9.15.9).
cp .env.example .env # optional – the defaults are local, synthetic-data-only values
docker compose up --build # postgres, storage, setup (migrations + bucket), web, worker
curl localhost:3000/api/health # {"status":"ok","checks":{"database":"ok","storage":"ok"}}Developing against local services only:
pnpm install
docker compose up -d postgres storage
pnpm setup:deploy # migrations as app_owner + bucket (needs the .env.example variables)
pnpm dev
pnpm verify # lint, types, unit + integration tests, architecture check, build, auditEvery change starts as an issue, lands through a pull request with a plain-language summary and a
green CI, and is never merged by its author. The process follows the fluory-system rulebook
(guard hooks in .claude/, docs and PR guards in scripts/).
KI-gestützte Erfassung von Angebotsanfragen: Daten aus E-Mails und Anhängen extrahieren, jede Angabe neben ihrer Fundstelle prüfen und freigegebene Anfragen genau einmal ans ERP übergeben. Referenzprojekt mit fiktivem Kunden – alle Daten sind synthetisch.