# Privacy tiers — the canonical configuration, and how modes trade down This is the **spine** for the privacy story. Every other doc describes a *feature*; this one describes the **maximally-private configuration once**, then defines each real-world mode as a **delta** from it — what it *gains* and, precisely, what it *leaks and to whom*. Read this first; the feature docs hang off it. > **Honesty rule (read before quoting anything here).** This page describes the **ceiling** — the maximal configuration, including mechanisms that are still **Design**. **What is actually in production today is in the [Status](./status.md) table and what you can check yourself is in [Verify it yourself](./verify.md).** Every mechanism below carries its own maturity (**Production / Implemented / Design**) so the ideal is never mistaken for the real. --- ## 1. The always-on foundation (every Space, live, not optional) These are not a "tier" — they are the floor beneath every Space, live and checkable today: - **Admission gate** — a gated Space refuses reads *and* writes without an allow-listed identity, even with the room key. - **Egress lock** — the browser-visible app can reach only a published allowlist (`connect-src`); everything else is refused by the browser. - **Content-blind storage** — the store holds only ciphertext sealed to the room key; there is no operator recovery recipient. - **Signed, reproducible build** — each origin — the deployed render **and** the mk-holding vault/kernel — publishes a `/cert.json` + assets-manifest binding its exact deployed bytes to published source, which rebuilds to that hash. *(Store origin + a CI rebuild-and-compare job still to come.)* This is the keystone: it is what makes the claims above *checkable* rather than asserted. - **Key confinement (vault sandwich)** — room keys live in the L1 vault + Kernel worker; the app frame is keyless, enforced by Same-Origin Policy, not app discipline. See [Client architecture](./client-architecture.md). Everything in §2 layers *on top* of this foundation. --- ## 2. The canonical maximum — the "Maximum" tier The highest trust level is the foundation **plus all seven** of the mechanisms below, each of which closes **one specific leak against one specific party**. They are **orthogonal** — independently switchable, each shutting a different door — so the "levels" in §5 are *bundles* of these, not a single ladder. ``` Foundation (always on) + Server attestation → operator/cloud can't read plaintext in use + Client attestation → the running client is provably the genuine build + Client verification → the locks are provably enforced in YOUR browser + OHTTP → the server can't see WHO (your IP) is connecting + Client shaping → a network observer can't read sizes / timing / patterns + No notification → no push provider learns THAT / WHEN you got a message + Confidential model → the model that answers the turn can't read it either = Maximum ``` > **The platform ships this; apps configure it.** The "Maximum" above is the platform's **supported capability**, not an aspiration — everything except the roadmap items (client attestation and client shaping) is shipped and available to every Space. A *mode* (§5) is a **bundle** of these mechanisms; a lower mode simply omits some. *Which mode the first-party Spaces app ships at is a separate, app-level concern — see [The Spaces app: default configuration](./spaces-app-defaults.md).* --- ## 3. What the platform ships today Mechanism-level view — the platform's status for each. (What the *first-party Spaces app* enables by default is a separate concern: [The Spaces app: default configuration](./spaces-app-defaults.md). Full product map: [Status](./status.md). Client-side checks: [Verify it yourself](./verify.md).) | Mechanism | Platform maturity | |---|---| | Admission gate | **Production** (structural — every Space) | | Egress lock | **Production** (structural — every Space) | | Content-blind storage | **Production** (structural — every Space) | | Signed + reproducible build | **Production** (structural — every Space) | | Key confinement (vault sandwich) | **Production** (structural — every Space) | | **Server attestation** (Nitro enclave) | **Production** — the app builder enables the enclave per room | | **Client verification** (verifier extension / CSP-loader) | **Implemented** — the self-run tool + the Windows verifier extension are built and proven on staging, not the prod default; the mobile companion is **Design** | | **Client attestation** (hardware-rooted binary/device proof) | **Design** — iOS App Attest / Android Keystore / Windows TPM verifiers are stubbed + fail-closed; native shells not shipped. (Client *verification* above is *software* release-attestation — a separate, more-mature thing.) | | **OHTTP** (network-metadata) | **Production** — oblivious transport (RFC 9458) is LIVE: the app routes room ops by postMessage to a pinned open-source **L1.5** frame that verifies a **client-attestable relay** (GCP Confidential Space, `relay.witbitz.chat`) and encapsulates to the gateway. Sticky opt-in (`?ohttp=1`); every room data op goes through the relay. ([verify](./verify.md)) | | **Client shaping** (traffic-analysis) | **Design** | | **No notification** | Push is **Production** (off unless a user enables it — a configuration choice) | | **Confidential model** (attested inference) | **Production** — the confidential tier routes its model call through an attested no-log gateway into confidential-compute inference on an open-weights model, verified transitively from the render enclave's measurement ([the attested tier](./the-attested-tier.md#the-confidential-model-closing-the-last-reader-shipped)). | Everything above is **Production** today except **client attestation and client shaping**, which are **Design** — the gap between what ships and the full ceiling. (OHTTP is **Production**, off by default behind the "Hide my IP" toggle.) --- ## 4. The seven mechanism axes (orthogonal) Each axis: the leak it closes, the party it closes it against, and its **platform state**. | Axis | Closes this leak | Against whom | Platform state | |---|---|---|---| | **Server attestation** | plaintext readable *during the render instant* | the operator + the cloud (AWS) | **Production** (the app builder enables the enclave per room) | | **Client attestation** (hardware) | a participant's client is a **tampered/forged build** masquerading as the genuine app — a modified client that leaks, or a bot impersonating one | **whoever runs a forged/tampered client** in your room (checked by the room's `requireAttestation` gate — hardware proof via App Attest / Keystore / TPM) | **Design** — App Attest / Keystore / Windows-TPM verifiers stubbed, fail-closed | | **Client verification** | the JS actually running in your browser might not be the audited, egress-locked build — a **leaky client** could exfiltrate `mk`/plaintext | **whoever serves your client — the app builder itself**, the operator, a CDN, or a network injector — a leaky or swapped build, **on purpose or by mistake** (verifying the client is what makes the *double blind* — even the app's own owner can't read your content — hold) | **Implemented** — self-run tool + Windows extension proven on staging; mobile companion **Design** | | **OHTTP** | your IP / the fact you're connecting | the server + the network path | **Production** — a single attested relay (Confidential Space, verified client-side via the pinned L1.5 frame, RFC 9458) sees your IP but only ciphertext; the gateway decrypts the op but sees the relay's IP. LIVE for **all app→AWS traffic**: room data ops *and* the enclave attest/wake path (previously a direct-to-gateway probe) now both ride the relay when the toggle is on — fail-closed, so a relay hiccup never silently falls back to a direct IP-revealing POST. The relay is measured code that provably does not log the source address — verifiable, not a promise. Residual: the browser still reveals your IP to **Cloudflare** when it loads the app's own bytes and calls same-origin edge functions (`/space-config`, tiles, `/api/appshare`, `/api/link`) — Cloudflare already serves the app, so this is no *new* party, and AWS never sees you (CF proxies onward from its own IP). Hiding your IP from Cloudflare/Apple/Google (app-load, push, Google sign-in) is outside any web page's control — only a device-level VPN or Tor closes it, which composes cleanly with OHTTP. | | **Client shaping** | message sizes, timing, access patterns | a passive network observer | **Design** | | **No notification** | *that*/*when* you received a message (content-free tickle + timing) | the push provider (Apple/Google/push service) | **Production** | | **Confidential model** | the turn's plaintext, read by the model that answers | the model vendor / host | **Production** — the confidential tier's measured image routes only to an attested no-log gateway (Intel-TDX-verified in-image, fail-closed) into confidential-compute inference (Intel TDX + NVIDIA GPU, gateway-verified); trades frontier for open-weights ([the attested tier](./the-attested-tier.md)) | > **Note — client verification** comes in three forms: the self-run **tool** (on-demand; [Verify it yourself §8](./verify.md)), the Windows/desktop **extension** (continuous — pins the release + forces the CSP; **Implemented**), and a mobile **native companion** (**Design**). "Client-verify on" in §5 means the extension/companion (continuous) or a tool run (on-demand). This is *software* release-attestation — distinct from **client attestation** above, which proves the *binary/device* is genuine via hardware. See: [The attested tier](./the-attested-tier.md), [The attested client](./client-architecture.md#the-attested-client), [The power-user stack](./client-architecture.md#the-power-user-stack), [The verifier](./client-architecture.md#the-verifier-extension), [Away notification](./status.md). --- ## 5. Named modes = bundles of axes Modes are named **bundles** of the §4 mechanisms — the platform supports the Maximum; a lower mode simply omits some. Names encode the **trade**, not a number. (Which mode the first-party Spaces app ships at is documented separately: [The Spaces app: default configuration](./spaces-app-defaults.md).) `●` on, `○` off, `◐` Design (not built yet). | Mode | Server-attest | Client-attest | Client-verify | OHTTP | Shaping | Confidential model | Notifications | In production today? | |---|:--:|:--:|:--:|:--:|:--:|:--:|:--:|---| | **Maximum** (full platform support, §2) | ● | ◐ | ● | ● | ◐ | ● | off | Partly — client shaping / hardware client-attest are **Design** (OHTTP is Production; on in this mode, opt-in in the app) | | **Attested** (strongest shippable) | ● | ○ | ● | ○ | ○ | ○ | off | **Yes** | | **Verified** | ○ | ○ | ● | ○ | ○ | ○ | off | **Yes** | | **Baseline** (foundation only) | ○ | ○ | ○ | ○ | ○ | ○ | off | **Yes** | | **Connected** (convenience) | ○ | ○ | ○ | ○ | ○ | ○ | on | **Yes** | > Governance overlays (regulator access, full audit trail, owner rule) are **orthogonal** to these privacy modes — a compliance opening is a *named-recipient* disclosure, not a privacy-mode step-down. Keep them on a separate axis; see [Delegated authority](./trust-model.md#delegated-authority), [The owner rule](./identity-and-admission.md#the-owner-rule). Air-gapped / on-prem deployments compose *on top* of any mode — see [Air-gap](./deployment-options.md#air-gap-zero-egress), [On-prem](./deployment-options.md#your-boundary). --- ## 6. Feature × mode matrix Cells: **✓** available and privacy-neutral · **✓·leak(party)** available but discloses something specific · **✗** unavailable at this mode. Only rows that actually *trade* are shown — every other feature (posting turns, membership, recovery, offline export) is mode-invariant and simply **✓**. | Feature | Maximum | Attested | Verified | Baseline | Connected | |---|:--:|:--:|:--:|:--:|:--:| | Async chat, private lanes, documents, widgets, artifacts | ✓ | ✓ | ✓ | ✓ | ✓ | | Local connectors (on-device: folder / Obsidian / local MCP) | ✓ | ✓ | ✓ | ✓ | ✓ | | Away notifications (push) | ✗ | ✗ | ✓·leak(push provider: that/when) | ✓·leak(push provider) | ✓·leak(push provider) | | Web search / flights / places (egress tools) | ✗ | ✓·leak(the named API) | ✓·leak(the named API) | ✓·leak(the named API) | ✓·leak(the named API) | | Cloud connectors (Google Drive/Docs, etc.) | ✗ | ✗ | ✓·leak(the cloud: content synced) | ✓·leak(the cloud) | ✓·leak(the cloud) | | Live call / voice | ✗ | ✗ | ✓·leak(media path) | ✓·leak(media path) | ✓·leak(media path) | | External model answers the turn | ✓·attested route † | ✓·leak(model vendor) † | ✓·leak(model vendor) † | ✓·leak(model vendor) † | ✓·leak(model vendor) † | † **The model residual.** If an *external* model answers, the model vendor receives plaintext to compute — attestation covers the render, not the vendor. The **Confidential model** axis (§3–§4) closes this and is **Production on the confidential (attested) tier**: the render enclave's measured image routes the turn only to an attested no-log gateway into confidential-compute inference on an open-weights model, each link verifying the next (verification is transitive from the render measurement; the weights themselves are vouched by the attested stack, not measured — see [the attested tier](./the-attested-tier.md#the-confidential-model-closing-the-last-reader-shipped)). Modes that use a frontier model still leak the turn to that vendor — that is the frontier-vs-confidential trade, chosen per room. See [The double blind](./trust-model.md#the-double-blind). --- ## 7. Opting out — what each step gains and what it leaks Each step **omits one platform-supported protection** — an explicit, named trade. Read top-to-bottom as "relax one thing, gain one thing, leak one named thing to one named party." - **Maximum → Attested.** *Gain:* the egress tools (web search / flights / places) — real external capability. *Leak:* each tool call's content to that named API; and OHTTP/shaping being off means the network path sees your IP, sizes, and timing. *Party:* the specific tool API + a network observer. - **Attested → Verified.** *Gain:* runs on any deployment (no enclave required), lower cost. *Leak:* the operator + AWS can read plaintext *during the render instant* (server attestation off). *Party:* the operator + cloud. Client integrity is still verified. - **Verified → Baseline.** *Gain:* no verifier step, frictionless. *Leak:* you're back to trusting the server's *declaration* that the locks hold, rather than confirming them; cloud connectors become available (content to the cloud). *Party:* yourself (trust restored) + any cloud you connect. - **Baseline → Connected.** *Gain:* away notifications (and convenience integrations). *Leak:* the push provider learns *that* and *when* you received a message (content-free, but the tickle + timing). *Party:* Apple/Google/the push service. --- ## 8. Residual limits (the honest floor, at every mode) No mode removes these; state them plainly so the tiers never over-reach: - **Model vendor (frontier rooms only)** — a room that chooses a frontier model hands that vendor the turn's plaintext (§6 †). The **Confidential model** axis (§3–§4) that removes this is **Production**: on the confidential tier the LLM runs as confidential-compute inference (Intel TDX + NVIDIA confidential GPU) behind an attested no-log gateway the render enclave verifies in its measured image, trading a frontier model for an open-weights one ([the attested tier](./the-attested-tier.md)). The residual stands only where the frontier trade is chosen. - **The endpoint / analog hole** — plaintext must exist on a device for a human to use it; a compromised endpoint (keylogger, screenshot, a connector the client doesn't know about) is outside every software guarantee. Managed devices / air-gap raise this bar; software alone cannot. See [Air-gap](./deployment-options.md#air-gap-zero-egress). - **Metadata — IP hidden, shape not yet.** Your IP is hidden by **OHTTP** ("Hide my IP", Production) — no party sees both your IP and your rooms. Message sizes, timing, and access patterns remain visible to the network path until **client shaping** ships. - **Revocation offline** — attestation/verification chains verify offline against pinned roots; revocation freshness needs connectivity. - **Availability is not privacy** — the operator can refuse *service*; content-blindness is a claim about *reading*, not about guaranteeing access forever. --- ## How this reorganizes the doc set This page is the **entry point** for privacy claims. The existing docs slot under it: - **Maturity detail →** [Status](./status.md) · **Client-side proofs →** [Verify it yourself](./verify.md) · **First-party app config →** [The Spaces app: default configuration](./spaces-app-defaults.md) - **Mechanism deep-dives →** [The attested tier](./the-attested-tier.md), [The attested client](./client-architecture.md#the-attested-client), [The verifier](./client-architecture.md#the-verifier-extension), [The double blind](./trust-model.md#the-double-blind), [The power-user stack](./client-architecture.md#the-power-user-stack) - **Deployment overlays →** [Air-gap](./deployment-options.md#air-gap-zero-egress), [On-prem](./deployment-options.md#your-boundary), [Deployment options](./deployment-options.md) - **Feature docs** each state their **mode row from §6** at the top, instead of describing privacy ad-hoc. *Update rule:* when a mechanism changes state, update **§3** and [Status](./status.md) together; when a feature's disclosure changes, update its **§6 row**.