Project · Lifebot V2

lifebot-v2 — Security Design

type referencestatus activelifebot · security · zero-knowledge · e2ee

Scope

The zero-knowledge platform: crypto envelope, key lifecycle, tenant isolation, auth, and the AI path. Derived from the rev. 3 plan's 4-persona adversarial review (all must-fixes implemented or tracked below).

Threat model

Threat Control
Full server/DB compromise Server holds ciphertext + salts + wrapped keys only; no decryption possible
Cross-tenant read (app bug) Postgres FORCE RLS, non-owner role, SET LOCAL GUC per transaction; negative test
Multi-device nonce reuse XChaCha20-Poly1305 192-bit random nonces (not AES-GCM)
Envelope downgrade/tamper Header bound as AAD; unknown versions rejected
Password oracle Verifier = AEAD-sealed constant; wrong password fails tag, uniform error
Account takeover via email claim Identity keyed on immutable (iss,sub), email_verified required
Dedupe-key enumeration HMAC/keyed-hash derivation — server can't confirm a record id it hasn't seen
Coach plaintext exposure Client-direct to Gemini (scoped short-lived cred); server never in plaintext path
Malicious web bundle (server pushes JS) Known weaker tier vs native: CSP/SRI planned; reviewed native binary is the anchor

Encryption

Layer Mechanism
KDF Argon2id, per-user 16B salt, params pinned + carried in vault (ops=3, mem=64MiB baseline)
Key wrap XChaCha20-Poly1305, AAD lifebot/wrap/v1; recovery key = second high-entropy wrap (planned)
Records XChaCha20-Poly1305-IETF, AAD-authenticated header, compact nonce.ct blobs
Transit TLS everywhere (Cloudflare Tunnel ingress; loopback-only host binds)
At rest (defense-in-depth) Postgres on the box; LUKS recommended; backups gzip + vaults-integrity check

GDPR product features

  • Consent before coach disclosure; minimised summary only.
  • Export + erasure planned as GET /v1/me/export, POST /v1/me/erase; crypto-erasure by wrapped-key destruction.
  • Special-category minimisation: cleartext metadata is routing-only (opaque ids, counters, timestamps).

Residual risks

Audited 2026-07-26 — see lifebot-v2/security-review. The first risk below was confirmed as the audit's single critical finding: CSP/SRI were never added, so the web tier's trust-on-every-load defeats the "operator can never decrypt" claim outright. Several controls tabulated above are also aspirational rather than implemented — email_verified is dead code, the recovery key does not exist, and FORCE RLS is bypassed by the superuser credential the API container holds. Treat this page as the intended design and the review as the actual state.

  • Web-tier trust-on-every-load (server-shipped JS) — mitigate CSP/SRI; document tier honestly.
  • Recovery key not yet implemented — forgotten password currently = data loss (by design, but UX must say so).
  • Gemini sees the consented summary — vendor trust bounded by paid-tier no-training terms + DPA (Stage 3).
  • In-app spend cap is per-deployment today; per-tenant caps land with the control plane (Stage 3).
Compiled from wiki/projects/lifebot-v2/security-design.md · git is the source of truth