Trust model
Witbitz makes one trust claim: privacy you can verify — the double blind. A Space is sealed to a key the platform never holds; the app has no backend of its own; the browser egress footprint is locked; and the deployed render can be rebuilt from published source and checked against a signed certificate. Neither the operator nor the app's own owner can read the users' data — and that's a property you check, not a promise.
This page states it in full. It is intentionally explicit about what is live today and what is not — start with Status if you need the shipped / preview / designed map, and Verify it yourself to run the checks in your own terminal.
What is protected today
| Claim | Production status |
|---|---|
| A gated Space refuses reads and writes without an allow-listed identity | Live and checkable |
| The stored Space ledger is ciphertext sealed to the room key | Live and checkable |
| There is no operator recovery recipient in the production envelope | Live and checkable |
| The app's browser egress is locked to a published allowlist | Live and checkable |
| The deployed render publishes a signed build certificate | Live and checkable |
| The render source can be rebuilt to the deployed hash | Live and checkable |
Run the checks: Verify it yourself.
What is not hidden
Witbitz does not hide everything, and the docs should never imply that it does.
- Metadata remains visible. The platform sees that a room exists, when it changes, and roughly how large writes are. A passive observer on your network sees the same shape in both directions. Hiding it is traffic shaping — a client half (the only half that can hide anything from the platform) and a server half (verifiable, because the server is measured) — and it is Design, not shipped: privacy tiers §4.
- Endpoints still matter. A compromised member device can read what that member can read.
- Availability is not privacy. The operator can refuse service. The content-blind claim is about reading, not guaranteeing access forever.
The double blind
Witbitz's core privacy claim: for an app built on it, neither the platform operator nor the app's own owner can read the users' data — and, the part that makes it a property not a promise, that claim is meant to be checkable from the code, not taken on faith. What holds today, exactly where it stops, and how the remaining "readable in use" gap is closed by the attested tier, now in production.
Sealed to a key we never hold → the platform is blind
A Space's data is a snapshot sealed under the room key mk and stored as ciphertext; the platform never holds mk
(agent/envelope.mjs seal/open; the key is committed only as commit(mk)). To the operator, a Space is opaque
bytes — storage and transport are content-blind, because the platform holds no key. There is no operator recovery
key: every record is sealed to the room key alone, so there is nothing on the platform that can read it. The double
blind is the only configuration that runs in production.
The confidential room → plaintext only inside the enclave
A sealed store is not enough: a Space has to be opened somewhere to run a turn. In a confidential room, that somewhere is a measured AWS Nitro enclave, and the key that opens the room never reaches anything we operate outside it.
- The key is made on your device. The member's app creates the room and its key
mk. The server stores only a commitment to it. - Your device checks the enclave before trusting it. The enclave makes its keypair inside itself at boot and never exports it. Its public half comes bound into an attestation document signed by AWS Nitro hardware. Your app verifies that document against the pinned AWS root, and checks the image measurement against the published one — which anyone can rebuild from source — before it sends anything.
- The key is sealed to that enclave alone. Your app seals
mkto the enclave's public key. Our servers carry the sealed bytes and cannot open them; only the measured image can. - Plaintext exists only inside the enclave. The enclave opens the room, runs the turn, re-seals the result and writes ciphertext back. The model call leaves the enclave only through an attested no-log gateway into confidential-compute inference, and is refused if that gateway does not attest.
So the operator is blind both at rest and in use: storage holds ciphertext, and the one place plaintext opens is a machine whose code you can check and whose key we cannot reach. How each link is measured, and what you can verify yourself: the attested tier.
A standard room has no enclave: its turns and reads open on our server while a member is active, and its model is a frontier vendor's. The difference is the room's tier — see privacy tiers.
The app's owner is blind too
A Witbitz app is a static page with no backend of its own, and its browser egress is locked to the Witbitz API. The users' content is sealed to keys the app's owner never holds, and the page has nowhere else to send it.
The chain: each side checks the other
The guarantee holds only if the code at both ends is the published code. Each side checks the other.
- The page is a reproducible build with a public audit trail. Every Official release of the web app is rebuilt
from its source commit inside a separate build enclave. The enclave signs its verdict — the release's hash
(
frontendSha256), commit and version — with a key born inside it, and the verdict goes into an append-only release log and into Rekor, Sigstore's public transparency log. A deploy is refused unless the bytes match the logged hash, and the page's signed/cert.jsonnames the same hash, so you can compare what you were served with what was logged. - The server checks the client. In an attested room every turn and read names the release it came from; the server accepts it only if that version is in the published release log and on the room's accepted list, and refuses an unlogged build. A browser can prove its version but not its device, so the room marks such a message "Witbitz-served vN" — a level below a hardware-attested app.
- On a phone, the hardware vouches for the app. In the native app the phone's hardware attests the app itself — Apple App Attest on iOS (the App Store build and its version), Android Keystore key attestation on Android — and the web bundle ships inside the app, pinned to its logged hash. The server verifies the attestation on each request and marks the message "attested app". The server's verifiers are built; the native apps are not released yet (status).
- The client checks the server. Before it seals a room key, your app verifies the enclave's hardware attestation and its published measurement — the confidential room, above.
Each link checks the next: a page you can match to a logged build, a server that accepts only logged builds (and, on a phone, only a hardware-attested app), and an enclave your app verifies before it trusts it with a key. The commands to run each check yourself: Verify it yourself.
Status — what holds today
| Property | Status |
|---|---|
| Sealed ledger, platform holds no key (nothing on the platform can read it) | shipped |
| No operator recovery key (sealed to the room key alone) | shipped & CHECKABLE — POST {"op":"sealed"} → recipients:["room"] (verify Test 5) |
| Admission gate enforces (reads and writes refused without an allow-listed identity) | shipped & CHECKABLE (verify Tests 1–3) |
Decrypt-once render, mk from the client only, dropped after |
shipped |
| Backendless static app (no backend of its own) | shipped |
Egress-lock (CSP connect-src/script-src allowlist) |
shipped & ENFORCED (block-mode) (verify Test 4) |
| Client E2EE primitive (the sealed-blob envelope) | shipped |
| Signed build certificate (deployed build hash + egress, signed from ground truth) | shipped & CHECKABLE — /cert.json (verify Test 6) |
| Reproducible build of published source (rebuild it → the deployed hash) | shipped & CHECKABLE — /source.tar.gz (verify Test 7) |
| Attested tier (operator provably blind in use) | Production — verifiable on real Nitro hardware, always on; the app builder enables the enclave per room (attested tier) |
| Attested client (a hardware-attested native shell carrying the audited bundle) | Design — native shells not shipped; the deployed web app already verifies the enclave's attestation, which is part of the attested tier above (verified client) |
Code map
| Concern | Where |
|---|---|
At-rest ledger seal (symmetric, under mk only) + key commitment |
agent/envelope.mjs (seal, open, commit, newRoomKey); agent/sessionStore.mjs encodeMemory — one recipient, mk. No operator/beta/admin recipient in prod. |
Recipient sealing (ECDH sealTo/openBox) — seals to a member/agent public key, never an operator |
scoped agent reads (agent/spaceScopedView.mjs) and Bridge epoch keys (agent/bridgeMembership.mjs) — a separate mechanism from the at-rest ledger above |
| Sealed ledger + decrypt-once render | agent/sessionStore.mjs, agent/asyncTurn.mjs |
| Content-blind poll (etag over ciphertext) | agent/spacePoll.mjs |
| Egress-lock CSP (block-mode, enforced on prod Spaces) | spaces/tools/gen-space-csp.mjs |
| The render, published and readable (about 2,700 lines; 1,500 for the core) | the published render source |
The double blind is not "trust us less." It is "you don't have to" — sealed to your key by default, and provably unobservable in use for any Space that turns on the attested tier.
Identity and admission
A Space starts with key possession: holding the room key proves membership. Gated Spaces add signed identity on top — Google/OIDC identity, signed invites, agent keys, owner policies. The link is the admission capability; the owner decides who may join and at what tier; and members join, rotate devices, and are revoked over a Space's life. The full mechanism — identity, the verified room, admission tiers, the owner rule, member lifecycle, and recovery — is one doc: Identity and admission.
Where to go next
- Check the claims: Verify it yourself
- Configure privacy: Privacy tiers · privacy in the Spaces app
- Understand admission and lifecycle: Identity and admission
- Go unobservable in use: The attested tier
- Know the code on the user's side: The verified client
Machine-readable source: trust-model.md · Generated 2026-10-27T07:05:42Z · build f301388c · every doc in one fetch: llms-full.txt (HTML)