SealedSpace Security Whitepaper
How SealedSpace protects customer data. This document describes the architecture as implemented; it is the technical reference behind our Trust page, security questionnaire answers, and (future) SOC 2 / ISO 27001 evidence.
Last updated: 2026-06-11 · Status: living document
1. Summary
SealedSpace is a zero-knowledge, end-to-end encrypted collaboration suite (notes, chat, files, email, calls, calendar, and tracker). All user content is encrypted on the client before it ever reaches our servers. The server stores only ciphertext and a minimal layer of plaintext routing metadata (who is a member of what, message ordering, timestamps). It holds no key that can decrypt note bodies, titles, file contents, file names, chat messages, email bodies, or space names — so a breach or legal demand can yield only ciphertext plus the routing metadata listed in §4. (One scoped exception — inbound external email at the moment of SMTP receipt — is described in §2.4a.)
This design is a deliberate compliance and risk posture: by holding no plaintext content, our breach blast-radius and regulated-data-processing scope are structurally smaller than those of a conventional SaaS.
1.1 Scope & assumptions (read this before quoting us)
- The guarantees above protect stored content. Plaintext routing metadata the service needs to operate is enumerated in §4 — we hold it, and it can be disclosed under legal process like any provider’s records.
- As with every web-delivered E2EE product (including our competitors), the encryption code itself is delivered by our servers: a compromised or coerced build pipeline could undermine the model. Mitigations: published source for client crypto (planned), signed desktop/mobile builds, and this document.
- These statements describe the system as built today; we update this whitepaper whenever the architecture changes.
2. Cryptographic architecture
All primitives are implemented in a single client crypto module
(CryptoProvider.ts) using established open-source libraries: the
independently audited @noble/curves (Ed25519 / X25519) and @scure/bip39,
hash-wasm (Argon2id), and the browser-native SubtleCrypto API (AES-GCM,
HKDF, SHA-256). No custom cipher implementations.
2.1 Password-derived keys (Argon2id)
On login/registration the user’s password is stretched with Argon2id
(memory-hard, tunable memoryCost/timeCost/parallelism, salt derived from
the normalized email). A single 64-byte output is split into two independent
32-byte keys:
authKey— the authentication credential. Sent to the server, where it is stored only as a bcrypt hash. The server never sees the password.vaultKey— never leaves the device. Encrypts the user’s identity-key vault locally.
2.2 Identity keys (BIP39 → HKDF → Ed25519 / X25519)
A 24-word BIP39 mnemonic (256-bit entropy) deterministically seeds the user’s long-term identity. The seed is run through HKDF-SHA-256 with distinct domain-separation labels so the signing and agreement keys never share raw material:
- Ed25519 signing keypair (
sealedspace/identity/ed25519/v1) — digital signatures (e.g. signing recovery challenges). - X25519 key-agreement keypair (
sealedspace/identity/x25519/v1) — ECDH for wrapping space keys to members.
The four key components are packed into a 128-byte payload, encrypted under
vaultKey (AES-256-GCM), and stored on the server as an encrypted private-key
blob — opaque bytes the server cannot decrypt. Only the public keys are
stored in the clear, as is required for other members to encrypt to the user.
2.3 Space keys & per-member wrapping
Each collaborative space has a random AES-256 Space Key generated client-side. To share it with a member, the sender performs X25519 ECDH with the member’s box public key, hashes the shared secret with SHA-256 to derive an AES-GCM wrapping key, and stores the wrapped Space Key as an opaque envelope. Key rotation is tracked by a key epoch. The server routes these wrapped blobs but never holds an unwrapped key.
2.4 Content encryption (AES-256-GCM)
All content — note bodies, titles, file bytes, file names, chat messages, email
bodies, version snapshots, space names — is encrypted with AES-256-GCM
(96-bit random nonce per message, 128-bit auth tag). Where applicable, the
ciphertext is bound with Additional Authenticated Data (AAD) to its routing
identity (e.g. space id, entity id, version), so the server cannot substitute
or replay envelopes across contexts. Large file blobs use a compact raw binary
envelope ([version][nonce][ciphertext+tag]) to avoid base64 inflation.
2.4a Email: end-to-end internally, sealed-on-receipt externally
Email bodies (including the subject, which lives inside the sealed body — the server stores no subject column) are sealed per-recipient to each user’s X25519 box public key:
- Internal mail (member → member) is sealed on the sender’s device — end-to-end encrypted; the server never sees plaintext.
- Inbound external mail necessarily arrives as plaintext over SMTP — this is inherent to interoperable email for every provider. We seal it per-recipient immediately on receipt and delete the raw message once sealed; plaintext exists only transiently during ingestion and is never stored. After ingestion the server can no longer read it.
We state this distinction explicitly rather than calling all email “end-to-end encrypted” — sealed-on-receipt protects data at rest, but is a weaker guarantee than true E2EE and we label it as such.
2.5 Account recovery (zero-knowledge preserved)
Two recovery paths, neither of which gives the server access to plaintext:
- Mnemonic recovery — the user re-enters their 24-word phrase, which re-derives the identity keys locally.
- Passkey-wrapped recovery — the mnemonic is encrypted under a key derived (HKDF) from a WebAuthn passkey’s PRF extension output and stored as opaque ciphertext. The server stores only the credential descriptor and PRF salt; it cannot derive the PRF output. Recovery still requires signing a server-issued recovery challenge (32 random bytes, rate-limited, single-use, expiring) with the recovered key.
2.6 Organization custody (managed accounts)
For organizations that need admin provisioning/recovery of members, the owner generates a random Org Custody Key (OCK) at space creation. The OCK is wrapped to each admin’s X25519 box key, and managed members’ identity keys are escrowed under the OCK. This delivers admin control without the host ever holding the OCK — custody is distributed among the org’s own admins, not us.
2.7 Agent delegation (Claude Code / MCP)
A user can link a headless agent — e.g. the Claude Code MCP server
(@sealedspace/mcp) — and grant it specific spaces, so an AI assistant can help
plan and work on their tracker. It reuses the per-member key-wrapping primitives
and preserves zero-knowledge against our servers:
- Device-link key delegation. The agent generates its own X25519 keypair on the user’s machine; at approval the user’s own client wraps the selected Space Keys to it, and the server stores only those envelopes plus SHA-256 hashes of the agent’s credentials. The agent never gets identity keys, the vault, or anything password-derived.
- Fingerprint ceremony + decrypt-proof. The CLI and the in-app card each show a four-word fingerprint of the agent key the user must confirm; the agent then proves it can decrypt the granted spaces before linking. Together these close malicious-server key-substitution.
- Default-deny scope. Agent tokens reach only the tracker routes of granted spaces; everything else is rejected, and revocation is immediate.
- Disclosed boundary extension. This is the one place content leaves E2E — by the user’s explicit, per-space choice: the client decrypts the granted spaces locally and sends that content to the user’s own AI-provider account (Anthropic), under that provider’s terms. We never receive or control it; the provider is not a sub-processor (Privacy §5a / Sub-processors). Encryption against our servers is unchanged, and the app shows exactly what will leave E2E before you approve.
3. Authentication & session security
- Access token — JWT, 15-minute TTL, held in memory only (never persisted to
disk/localStorage). Sent as
Authorization: Bearer. - Refresh token — opaque 32 random bytes, stored only as a SHA-256 hash, transported in an HttpOnly cookie, with single-use rotation on every refresh.
- Default-deny authorization — a global auth guard protects every server endpoint; routes opt out explicitly.
- Authorization model — capability-based access control with Teams (capability bundles) and per-note/per-file access grants, enforced server-side.
4. What the server can and cannot see
Cannot see (encrypted client-side, zero-knowledge): note bodies & titles · file contents & file names · folder names · chat message bodies · email bodies & attachments (internal mail E2EE; inbound external mail sealed on receipt, see §2.4a) · space/organization names · version-history snapshots · identity private keys · the user’s password.
Can see (plaintext routing metadata, required to operate): account email & chosen display name · user/space/membership relationships · message/update sequence numbers & timestamps · file size & MIME type · audit events (who did what admin action, when) · email envelope routing (sender/ recipient addresses, subject is not stored in clear — body is sealed).
This boundary is documented per-table in our database schema (encrypted fields are typed as opaque envelopes; routing fields are plain columns) and is enforceable evidence for an auditor.
5. Infrastructure & data handling
- Application tier — AWS (us-east-1): EC2 compute behind Caddy (TLS), RDS PostgreSQL for the metadata/ciphertext store.
- Static/web tier — AWS S3 + CloudFront, TLS via ACM.
- Encrypted media — AWS S3, accessed via short-lived presigned URLs; objects are ciphertext only.
- Email — AWS SES v2 (send/receive) + SNS (inbound); message bodies sealed per-recipient (see §2.4a — raw inbound MIME is deleted once sealed).
- Real-time calls/media — self-hosted LiveKit SFU + coturn on Oracle Cloud Infrastructure.
- Push notifications — Firebase Cloud Messaging (Android/web) and Apple APNs (iOS); pushes are content-free wake signals (routing ids only).
- Transport security — TLS 1.2+ everywhere (Let’s Encrypt for the API, ACM for web/app).
- Self-hosting — the architecture is designed to be fully self-hostable for data sovereignty. A packaged, supported self-host distribution is in development; enterprise deployments are available by arrangement — contact us.
See the sub-processor list for the authoritative list of third-party providers.
6. Compliance status & roadmap
Current: zero-knowledge architecture, encryption in transit + at rest, default- deny authorization, audit logging. Planned: SOC 2 Type II + ISO 27001 (jointly), GDPR program build-out, annual penetration testing. None of these audits/certifications has started yet — we say “planned”, not “in progress” or “certified”, until engagements are actually underway.
7. Reporting a vulnerability
See our Vulnerability Disclosure Policy. Contact: security@sealedspace.com.
Note: This whitepaper describes the system as built. Any claim made publicly (Trust page, sales) must trace back to a control verifiable in this document or the codebase. We update this file whenever the architecture changes.