Security by design
Security
Last updated: April 27, 2026
Encryption
- In transit: TLS 1.3 mandatory on all endpoints (web, API, database). HSTS active.
- At rest: Cloudflare R2 encrypts each object with AES-256 server-side. PostgreSQL on disk-encrypted volume.
- Direct upload: audio goes from your browser to R2 via presigned URL. Our API never touches the binary — reduces attack surface and latency.
Identity and authentication
- Federated identity with Keycloak 26 on auth.codelabs.studio (our own server). Supports MFA, Google/Microsoft login.
- JWT tokens signed with rotatable keys. Validated against Keycloak's public JWKS.
- Renewable sessions with refresh tokens. We never store passwords — Keycloak is the sole custodian.
European infrastructure, data sovereignty
- Dedicated server in Europe under our exclusive management. Hosts PostgreSQL, job queue, and semantic embedding engine. We do NOT use cloud DB services (Neon, Supabase, PlanetScale): total control over where your data lives.
- Local embeddings with bge-m3 — your transcription texts never leave the European server to generate semantic search vectors. A key differentiator versus competitors that send every transcript to OpenAI/USA.
- Application on Docker Swarm with Traefik + automatic Let's Encrypt. Deployment managed via Dokploy.
- Async job queue on Redis (BullMQ). Exponential backoff retries and per-note idempotency.
Consent audit log
Every time you accept a consent (process audio, store it, etc.), we record an append-only row in the consents table with: UTC timestamp, IP address, user-agent, legal text version, and hash of the accepted document.
We never update rows: when you revoke a consent, we insert a NEW row with revoked_at set. This allows reconstructing state at any historical moment — key if we ever receive a legal request.
Vulnerability management
- Sentry monitors every production error. Filters prevent sending sensitive content (transcripts, audio).
- Dependencies audited with
pnpm auditin CI; high CVEs block merges. - Responsible disclosure policy: [email protected]. We respond within 48 hours.