Architecture overview
v1.0 · effective 2026-04-27
Data residency
Mill’s own infrastructure is EU-only. Application servers, database, object storage and backups run in the European Union, on German hardware.
Model inference is a separate question, and we answer it per provider in the table below rather than in one sentence. Where a provider processes outside the EU, or on a global endpoint that carries no region, the table says so and the transfer runs under Standard Contractual Clauses. Organisations that need generation inside the EU can select the EU AI region — separately for outline and content, for section images, and for narration, since each is its own choice: outline and section writing then run on Mistral in Paris, images on FLUX in Germany, and narration on the speech endpoint your operator has configured. Your AI settings page shows the provider each part will actually use.
Stack
| Layer | Component | Region |
|---|---|---|
| Edge / TLS | Caddy reverse proxy on the application server (no separate CDN) | Nuremberg, DE |
| App runtime | Next.js 15 on a Hetzner CX server | Nuremberg, DE |
| Database | PostgreSQL, self-hosted on the same server | Nuremberg, DE |
| Object storage | Local filesystem on the application server | Nuremberg, DE |
| Architect + writer LLM | Claude Sonnet via Anthropic EU endpoint | EU inference |
| Translator LLM | Claude Haiku via Anthropic EU endpoint | EU inference |
| Image generation (default) | Google Gemini, via the Gemini Developer API | Global endpoint, no region set |
| Image generation (EU AI on) | FLUX by Black Forest Labs | Freiburg, DE — pinned to the EU API host |
| Text-to-speech (default) | Google Cloud Text-to-Speech | Global endpoint, no region set |
| Text-to-speech (EU AI on) | Operator-configured speech endpoint | Wherever the operator points it |
| Architect + writer (EU AI on) | Mistral Large | Paris, FR |
| Translation (machine-translation engines) | Google Cloud Translation; DeepL where configured | Global endpoint / Cologne, DE |
| Workflow automation | n8n self-hosted | Hetzner DE |
| Bot protection | Cloudflare Turnstile | Global edge (no PII) |
Encryption
- TLS 1.2+ everywhere at the edge.
- AES-256 at rest for application data.
- Per-org KMS-managed data encryption keys (DEK).
- Key rotation API; audit-logged.
Identity
- NextAuth.js with email + OAuth + per-org SSO (OIDC).
- SCIM v2 for SCIM-capable IDPs (Azure AD, Okta).
- TOTP MFA available for all users; required for org admins.
- Audit-logged admin actions (Postgres + 90-day retention).
SCORM / xAPI
- SCORM 1.2 + SCORM 2004 4th + cmi5 + xAPI emission supported.
- Generated zips are immutable — published courses ship a frozen runtime.
- xAPI extension namespace:
https://mill.colport.eu/xapi/extensions. - LRS replicator forwards statements to customer-configured LRS endpoints with HMAC + retry.
Multi-tenancy
- Logical isolation: every row carries an
organizationId. - Per-org KMS keys protect at-rest blobs.
- Row-level access control enforced at every API boundary (Zod + DB-level WHERE clauses).
- Cross-tenant data leakage is monitored via a quarterly red-team test.
Detailed runbooks (deploy, rotation, restore): ops@colport.eu