— Security

The substrate is yours.

Zero-knowledge architecture. No frontier-model API anywhere in the runtime path. Encrypted at rest, encrypted in transit, deletable on demand.

No frontier model

No Anthropic, no OpenAI, no Google, no Mistral, no Meta API call ever fires on your behalf. Reasoning runs on our own Belisama-native engine inside infrastructure we control. Your messages are never seen by a third-party model provider.

Encryption

AES-256 at rest (Postgres column-level for substrate). TLS 1.3 in transit. Per-user substrate envelope keys derived from a server-held master + per-user salt. The substrate row in the database is unreadable without an active user session decrypting it.

Deletion

Settings → Privacy → Delete my substrate. Cryptographic shred within 24 hours. Backups overwritten within 30 days. Cancel deletion within a 7-day grace window.

Export

Signed JSON or CSV, any time, no charge. The complete graph: nodes, edges, metadata, timestamps. Re-import elsewhere or archive offline.

No training on your data

Your conversations and substrate are never used to train any model. The only opt-in flow that contributes to learning is anonymous, summary-only Minima-Cursie coding traces — and you control that switch.

Sovereignty

Primary database in Frankfurt (IONOS). Sydney processing on request for AU residents. Your substrate doesn't cross borders without your permission — see the privacy policy for the SCC framework.

Hardened controls (what we run, end-to-end)

LayerControlWhere to verify
EdgeCloudflare WAF, DDoS L3/4/7, rate-limits per route, bot managementHTTP cf-ray headers; Cloudflare dashboard
TransportTLS 1.3 only, HSTS preload, OCSP stapling. Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadSSL Labs A+ rating · ssllabs.com
BrowserStrict CSP, X-Frame-Options: DENY, Cross-Origin-Opener-Policy: same-origin, Cross-Origin-Embedder-Policy: require-corp, Referrer-Policy: no-referrer, Permissions-Policy locked downsecurityheaders.com
Auth (web)Cookie session, PBKDF2-SHA256 600,000 iterations, SHA-256 session token hash, CSRF on every state-changing requestSource: fiduci/products/odahl/functions/_lib/auth-shared.ts
Auth (API)Bearer tokens (fdc_live_…), SHA-256 hashed at rest, per-key class allowlist, per-key budgetSource: fiduci/products/odahl/functions/_lib/api-auth.ts
Founder auth3 layers: password → email OTP → TOTP. Founder-only path; everything inside /api/admin/* requires is_founder = TRUE + a TOTP-fresh sessionAudit table: founder_admin_audit
DatabasePostgres on a private internal docker network. Pages never connect directly — they speak to a single Bearer-gated pg-proxy service. /pg/migrate is admin-tunnel-only and explicitly 404'd on the public nginx.Source: fiduci/services/pg-proxy/, fiduci/deploy/nginx-public.conf
Substrate at restPer-user envelope encryption (AES-256-GCM). The plaintext content is never co-located with the account identifier in any backup.Source: fiduci/products/odahl/functions/_lib/substrate-envelope.ts
SecretsCloudflare Pages secrets + IONOS .env with file permissions 600. Quarterly rotation runbook. No secret in source.Runbook: docs/SECRETS_ROTATION.md
BackupsPostgres logical backups every 6 hours, retained 30 days. Encrypted with a separate key from the live database. Restore tested quarterly.Runbook: docs/BACKUP_RUNBOOK.md
LoggingStructured JSON, no message bodies, 30-day retention then aggregated. Founder admin actions logged with IP & UA into founder_admin_audit.Schema: migration 016

Reporting a vulnerability

We want to hear from you. Acknowledged within 24 hours; substantive response within 5 business days; disclosure timeline negotiated with you.

Supported versions

Odahl is a single live service — there are no "versions" to keep on life-support. Every patch is rolled out to all users. Old API key formats (fdc_test_… beta keys issued before May 2026) remain valid; if we ever sunset a key format we will give 90 days' notice and roll all affected keys for free.

Threat model summary

We design against four kinds of attacker:

  1. Drive-by abuse — bots, scrapers, password-spray. Mitigated by per-IP rate limits at Cloudflare + nginx + the auth handler.
  2. Single-account compromise — stolen cookie, leaked password. Mitigated by short session TTL, per-session TOTP gates for sensitive paths, audit log, anomaly alerts on login from new IP/UA.
  3. Sub-processor compromise — one of our vendors is breached. Mitigated by per-user envelope encryption (we never co-locate plaintext + identifier), no third-party model API in the runtime path, secrets rotation, principle of least privilege on every vendor.
  4. Infrastructure compromise — full VPS takeover. Mitigated by zero-knowledge architecture (the substrate is encrypted; full disk read still doesn't yield plaintext substrate without live session keys), short-TTL JWTs, daily off-server backup, and an incident-response plan that triggers customer notification within 72 hours.

What is not in scope

Honesty up front:

Contact

Security: [email protected]. Privacy: [email protected]. Founder & DPO: [email protected].