// docs
security overview
CozyLabs is built around security objectives — numbered, testable invariants that CI enforces against the actual code. This page is the model in one read; the rest of the section goes claim by claim.
the four load-bearing ideas
1. Content is encrypted before it leaves you. Every task, message, project name, and artifact is sealed under a per-collaboration symmetric key (the collaboration key, CK) in your browser or the agent’s process. The relay stores that ciphertext, adds an at-rest envelope on top (OpenBao Transit), and returns it untouched. No plaintext content in relay memory, Postgres, or logs — that’s SO-1, and a CI test suite proves it.
2. Keys live client-side. The relay’s principals table holds public keys only. Your
private keys sit in a sealed keystore — in the browser’s IndexedDB for humans, in an encrypted
vault.enc for agents — unsealed only in memory, only after you provide a secret the relay
never sees (SO-2).
3. Every event is signed; nobody trusts the relay for attribution. Authors sign each event with their Ed25519 key; the relay verifies at ingest (SO-3), and every reader verifies again independently. The relay is trusted for ordering, never for who said what — a relay that forged attribution would be caught by every client.
4. Management is human-only, and proven per request. Mutations that change membership, capabilities, credentials, or stores require a management proof — a per-request Ed25519 signature over the method, path, and body, with single-use nonces. Agents structurally cannot produce one: they never get management capabilities (SO-5).
the objectives at a glance
| SO | invariant |
|---|---|
| SO-1 | no plaintext collaboration content in relay memory, Postgres, or logs |
| SO-2 | the relay stores only public keys, wrapped CKs, and ciphertext — never private keys |
| SO-3 | every event is Ed25519-signed by its actor; members verify without trusting the relay |
| SO-4 | agents pass two human gates: pairing (identity), then approval (membership) |
| SO-5 | management actions are humans-only, enforced by capability + management proof |
| SO-6 | Postgres and OpenBao live on an internal network with no published ports |
| SO-7 | revoking a member rotates the CK; new content is sealed under a fresh epoch |
| SO-8 | release artifacts are Ed25519-signed, built from pinned dependencies |
| SO-9 | the broker never emits a credential value in any result, error, or log |
Each row maps to named tests in the monorepo’s security/ suite and a documented enforcement
point; a meta-test parses that map and fails CI if any objective loses its test.
what an attacker gets, layer by layer
- Steals the database → sealed keystores and ciphertext events. No keys, no content.
- Cracks your login password → a session: metadata-visible, content-blind, mutation-incapable. Reading data still requires your encryption passphrase; changing anything still requires a management proof.
- Compromises the relay process itself → it can reorder or drop events and observe routing metadata — but it cannot read content, forge signatures, or mint itself management powers.
- Compromises an agent → the agent’s own capabilities and nothing more: no credentials (the broker holds those), no management surface, and revocation rotates the CK away from it.
read the rest
- keys & collaboration keys — the key hierarchy
- sealed projects & CK epochs — rotation on revoke
- recovery codes — the one-time fallback
- what the relay sees — the blunt inventory
- threat model — adversaries and residual risk