# Vault — the cross-origin isolation demo (for LLMs and bots)

> Machine-readable explainer. Human page: **https://witbitz.chat/vault** (redirects to the live demo on the Spaces
> origin, https://witbitz-spaces.pages.dev/vault-demo). Canonical raw markdown: **https://witbitz.chat/vault.md**.

## What it is, in one line
A live demo of an **app that builds and hosts an end-to-end-encrypted room it cannot read** — the browser's same-origin
policy keeps the app out, and an **external verifier** proves it. Trust comes from the verifier, **not the hostname**.

## The threat it answers
A **malicious app builder** (the "ghost participant" backdoor): the developer who writes and hosts a Witbitz-powered app
could silently append a secret recipient to the room, or otherwise move the key/plaintext out — E2EE only ever protected
transport, never a malicious endpoint. You cannot solve that "in the client" if the builder writes the client, and you
cannot *detect* your way out (a reviewer/LLM is a heuristic the adversary optimizes against). The answer is to enforce by
**mechanism**: make the security-critical code verifiable and NOT the builder's, and lock egress.

## The corrected model (important — not "the app runs inside Witbitz")
The app-owner (say a hotel) **hosts everything — the vault, the room, and their own app — on their own domains.** Nobody
runs "inside Witbitz"; the user stays on the app-owner's brand and domain. Witbitz supplies the **code**, not the hosting.
- The **only structural requirement is two distinct origins**: the vault + room on one (e.g. `vault.hotel.com`), the
  untrusted app on another (e.g. `app.hotel.com`) — *both the app-owner's*. That two-hostname split is what lets the
  browser's cross-origin isolation keep the app out. It is a technicality, not "give up your domain."
- **Trust comes from VERIFICATION, not from being a Witbitz origin.** A verifier confirms the top page is the honest
  vault bytes, the room matches the reproducible build, the egress-lock is enforced, and no rogue worker is registered.
  A hotel-hosted-but-verified vault gives un-spoofable consent just as well — a tampered vault simply fails the check.

## The three layers
1. **Top frame — the vault.** Verified Witbitz code. The un-spoofable surface: consent, the roster + safety number, the
   lock trust mark. The untrusted app can neither cover nor fake it.
2. **Middle — the untrusted app** ("Grand Hotel", the builder). A *different origin*. It frames and positions the room
   and brands it (via sanitized tokens the vault applies) — but the browser makes reading the room a `SecurityError`.
3. **Inner — the room.** The E2EE Space, same origin as the vault (so they share a direct same-origin channel — no
   postMessage needed), egress-locked so it can only reach content-blind Witbitz.

## The flow (what a visitor sees, and what happens)
1. **Open the page.** It frames the real `vault › app › room` stack: a purple "Grand Hotel" app hosting a live Witbitz
   room, with the vault's trust bar above it.
2. **The untrusted app self-reports.** The middle app tries to reach the vault's API (`window.parent.vaultAPI`) and to
   read the room's DOM — both come back `BLOCKED · SecurityError`. This is shown live, but labeled **illustrative, not
   authoritative**: a malicious app would claim "blocked" too, which is exactly why the real check is external.
3. **Leak from the page — and watch it fail.** A button fires a `fetch()` to an outside host from the demo page itself;
   the page's own `connect-src` (it runs under the same enforced egress-lock CSP as the room) **blocks** it. You can also
   read the page's live enforced CSP right there.
4. **The verifier is the anchor.** An external program (`node tools/vault-verifier.mjs`) drives a real browser and reads
   ground truth the page can't forge, confirming: three distinct origins; the app can't reach the vault API; the app
   can't read the room; the room's egress-lock is enforced; no rogue Service Worker.

An on-page scoreboard fills in as each is shown: **Isolated · No-drive · No-read · Egress-locked · Verified.**

## How it works (architecture)
- **Same-origin policy IS the access control.** The vault and room share an origin, so they talk by direct
  `window`-access; the middle app is cross-origin, so any attempt to reach the vault's API or read the room throws a
  `SecurityError`. No trust in the app's good behavior is required — the browser enforces it.
- **Egress-lock.** Every layer on the Spaces origin ships a strict `Content-Security-Policy` with a tight `connect-src`
  (only content-blind Witbitz). Out-of-band leaks are blocked structurally — including from the demo page itself, which
  is how "this app can only talk to Witbitz" becomes a checkable fact rather than a promise.
- **Verified, not trusted (why external).** A page can lie about itself, and a rogue **Service Worker** can sit *below*
  the page and below a passive network proxy — serving tampered bytes from its own cache and synthesizing its own
  headers, so load-time / `curl` / proxy checks are blind to it. The anchor is therefore an **external** verifier that
  drives a real browser over the debugging protocol and reads the actual loaded bytes, the browser-owned SW registry
  (un-forgeable), and the enforced CSP. On desktop it's a small program you run; on mobile it's a **native, attested
  wrapper** (a bundled-local app with hardware attestation, no live-URL WebView).

## Why this is different from "an iframe sandbox"
Sandboxing usually protects the *host* from the *guest*. Here the point is the opposite and stronger: the party who
**builds and hosts** the whole thing is structurally prevented from reading the room inside it, and that containment is
**verifiable by anyone** from outside the app-owner's control — hosting is theirs, the verifier is not.

## URLs
- `https://witbitz.chat/vault` — the live demo (redirects to https://witbitz-spaces.pages.dev/vault-demo).
- This explainer, canonical: `https://witbitz.chat/vault.md`.
- The raw three-layer stack: `https://witbitz-spaces.pages.dev/vault?app=https%3A%2F%2Fwitbitz-vault-demoapp.pages.dev%2F`.
- How verification works (developer docs): `https://witbitz.chat/docs/verify.md` (see Test 8 — the CDP verifier).
- Related demo: `https://witbitz.chat/lumen.md` (the egress-lock, from the hosting angle).
