Verifying the client — the code your browser runs
Everything a browser runs for a Space comes from a web origin, and an origin can be compromised: a hijacked hosting account, a bad deploy, a poisoned cache. Sealed storage and an attested server mean little if the page itself can be swapped. This page is how the client is pinned, how anyone can check it, and how the server checks it back.
How the app is put together inside the browser — the vault, the Kernel and Atlas — is the next page: the app as an operating system.
Every release is a reproducible, logged build
A release of the web app is not "whatever we deployed last". Each Official release is rebuilt from its source commit
inside a separate build enclave, which signs its verdict with a key born inside it; the verdict — the release's hash
(frontendSha256), commit and version — goes into an append-only release log and into Rekor, Sigstore's public
transparency log. A deploy is refused unless the bytes rebuild to the logged hash, and never moves backwards to an
older release.
Devices choose a channel: Official (the newest logged release) or Beta (the newest build, not rebuilt by the enclave). The service worker downloads a release completely before the app switches to it.
The page pins everything it loads
The shell names every file it will load by its hash, and the browser refuses anything else:
| What | How it is pinned |
|---|---|
| Every JavaScript module | An import map carries a sha384 integrity for each module; the browser checks each module as it loads it (Chrome 127+, iOS Safari; older engines ignore it). |
| Script tags | Subresource Integrity on each <script src>. |
| Inline scripts | The Content Security Policy lists their hashes, the import map's included. |
| The key worker | Bundled into a pinned module and started from it, so it is covered by the same pins. |
| Network | The enforced CSP's connect-src lists the only hosts the page may reach — the published egress lock. |
The vault (the hosted app's outer frame) is pinned the same way, under its own enforced CSP, and cannot be framed.
What this does not cover by itself: the pins live in the shell, and the shell is whatever the origin serves. A compromised origin could serve a different shell with different pins. Closing that needs a check outside the page — the signed certificate below, checked by a verifier you run, or a native app.
The signed certificate
Each deployed origin publishes a platform-signed /cert.json:
pinned platform key → signed /cert.json (frontendSha256) → /assets-manifest.json → every file's hash/assets-manifest.jsonmaps every served file to its hash, plus the inline-script hashes./cert.jsoncommits to the manifest's hash, signed by the platform key (ES256, P-256). The key is published in Verify it yourself and compiled into the checkers — never fetched from the app. A tenant's own app is signed with a tenant key the same way.- The cert's
frontendSha256is the same hash the release log and Rekor carry, so what is served can be matched to a logged, reproducible build.
Checking it yourself
- From a terminal — fetch
/cert.json, verify the signature against the published key, compare the hashes with what is served and with the release log: Verify it yourself. - In your browser, continuously — the verifier extension.
- On a phone — the attested client.
The verifier extension
A page cannot vouch for itself: any check it runs, a swapped page can skip. The verifier is a small browser extension that runs outside the page, so the origin cannot opt out of it.
- It forces verification. Every app navigation loads in verified mode; the loader checks the signed certificate against the pinned key and refuses to start a release that does not match ("couldn't verify this app").
- It forces the policy. It sets the page's CSP itself, built from the hashes in the signed manifest — with no
'self', so a same-origin script that is not in the signed release cannot run at all (Chromium 127+). - It shows the result in a toolbar badge the page cannot draw: green when the release verifies, red when it does not.
It covers the regular app, the hosted app and its vault, and tenants' apps. Status: Implemented — built and measured against production (the app and the vault boot with no violations; a tampered file fails closed), installed unpacked; not yet in an extension store.
Install the verifier
- Get the extension from the repository (
docs/verified-client-real/extension/) and read its few files.config.jsonholds the origins it guards and the pinned keys — check them against Verify it yourself. - In Chrome, open
chrome://extensions, turn on Developer mode, choose Load unpacked and pick the folder. - Open the app. It reloads in verified mode, boots normally and the badge turns green.
- To see it enforce: turn the extension off and reload — the badge is gone and the page's own policy applies again.
The one thing you take on faith is the extension itself, checked once. The strongest choice is a verifier written by someone other than the app's vendor.
The server checks the client
Verification above protects you from a swapped page. The server can also require that every member of a room runs a released client:
- In the browser — in an attested room, every read and turn names the release it came from; the server accepts only a version in the published release log and on the room's accepted list. A browser can prove its version but not its device, so this level is marked "Witbitz-served vN". Status: Production.
- On a phone — the native app ships the same web bundle inside the app and loads it locally, never from the network, so the phone's hardware attestation covers the bundle too: Apple App Attest on iOS, Android Keystore key attestation on Android. The server verifies the attestation on each request, bound to the member's signing key, and marks the message "attested app". Status: the server's verifiers are built and tested with synthetic keys (no real device's evidence yet); the Android app builds reproducibly; the native apps are not released (Design).
Requiring an attested client is a room setting, checked by the server — not a claim a client makes about itself.
Not built yet
The module list in the certificate
A signed list of the shell's modules in /cert.json, so a checker can match the whole module set the browser loaded —
not only the files served — to the release log, without the extension.
A byte-level verifier
A Firefox extension that hashes the exact bytes the browser received and checks them against independent transparency logs, removing Witbitz from the trust base for one extra tool. Design.
Certified closed-source apps
A capability-confined app audited inside an enclave by several independent checkers against its declared privacy certificate, with a public verdict log — "this app is good" without publishing its source. Design.
Limits
- Integrity is not correctness. A verified release can still have a bug; a verified page renders others' content safely only because it is written to.
- A browser without the extension has no outside check that the shell it got is the logged one — the pins hold within the page, the extension or a native app checks the page.
- Older browsers ignore import-map integrity; the signed certificate and the extension still apply.
Next
- The app as an operating system — the vault, the Kernel and Atlas
- Verify it yourself · The attested tier · Trust model
Machine-readable source: client-architecture.md · Generated 2026-10-27T07:05:42Z · build f301388c · every doc in one fetch: llms-full.txt (HTML)