The verified client, in full
Everything a browser runs for a Space is delivered from an origin, and an origin can be compromised — a popped hosting account, a bad deploy, a poisoned cache. The verified client closes that gap on two orthogonal planes, and a serious client needs both:
- Verification (integrity) — what code runs. The browser refuses to run any byte that isn't the exact, platform-signed release.
- Confinement (custody) — who can touch the room key. Key custody lives in an outer frame the app cannot read, so the browser's Same-Origin Policy — not the app's own discipline — is the wall.
They compose: verification pins the loader so only approved code runs; confinement keeps the key out of that code's reach anyway. Verify the prisoner and keep the cage. From there this page climbs the ladder to the strongest tiers — a native attested client, the verifier extension that forces verification on the real bytes, the power-user stack that removes Witbitz from the trust base, and the certified app that makes a closed-source app machine-auditable.
Status. The core chain — pinned key → signed cert → manifest → loader →
__vcImport/__vcFetch→ bundle + workers + chunks + pinned assets — is built and proven on staging (preview.witbitz-spaces.pages.dev) when forced by the verifier extension /?vc— the verified client, Implemented, not the default production boot. Its extension-free, origin-served counterpart — the pinned bundle, a self-bootstrapping loader + a signed client manifest that content-pins the shell's imported module closure — is Design, not built. The confinement plane (vault sandwich + Kernel) is live in production. Where a piece is design or device-only it says so.
The one problem it solves
script-src 'self' — the normal same-origin policy — trusts any script the origin serves. That is exactly the wrong
thing against a compromised origin: the evil script is same-origin, so 'self' waves it through, and stripping the
Subresource-Integrity attributes off the HTML disables the per-file checks. The verified client removes 'self' and
replaces "trust the origin" with "trust one small loader whose hash is pinned out-of-band, and let it check everything
else."
Part 1 — Verification: what code runs
The trust anchor and the chain
Trust bottoms out at a pinned platform public key (P-256), published in verify it yourself and compiled into the loader and the verifier — never fetched from the app. From there, one signature covers the whole frontend:
PINNED platform key → signed /cert.json (frontendSha256, ES256) → sha256(/assets-manifest.json) → every file's hash/cert.jsonis a platform-signed commitment. ItsfrontendSha256is the SHA-256 of the served/assets-manifest.json; the signature is verified against the pinned key, and the cert is rejected if it embeds a different key (no key-swap)./assets-manifest.jsonis a content-addressed map{ path → sha256 }of every served file. Because the cert signs its hash, the manifest — and every file hash in it — is trustworthy once the cert verifies.
A compromised origin can serve an evil bundle, but it cannot forge a cert that verifies against the pinned key, so any swapped byte fails the chain and is refused.
The loader — the small, stable, pinnable entry
spaces/public/space-loader.js is the entry point. It is deliberately tiny and stable across app releases (it
imports nothing versioned), so its hash is the one thing an extension has to pin. space.html loads it:
<script type="module" src="./space-loader.js" data-app="./space.js" data-bundle="./verified-app.json"></script>Its exported verifyRelease() runs the chain above (pinned key → cert signature → frontendSha256 == sha256(manifest))
and returns run-or-exit. On a mismatch the app is never imported and the user sees a plain "couldn't verify this app"
page instead of running unknown code.
Two tiers
Verification is opt-in per load, so the default path is byte-identical to a normal boot and a stray cert outage can never brick startup.
| Tier | Trigger | What it guarantees |
|---|---|---|
| A — verify-in-place | ?vc=1 (or the verifier) |
The served frontend matches the signed release (run-or-exit). The app still loads as normal ES modules under script-src 'self'. |
| B — loader-only CSP | ?vcbundle=1 (or the verifier) |
script-src '<loaderhash>' '<bundlehash>' … with no 'self'. Evil same-origin JS cannot run at all. |
Tier A answers "is this the right release?" Tier B additionally answers "can anything else run?" — no. The verifier extension is what forces either tier so the origin can't opt out.
How Tier B runs a whole app under "no 'self'"
Under a loader-only CSP the browser won't load same-origin <script>s or import() modules — so the loader stops
relying on the browser to fetch code and does it itself. It fetches the app as text, checks its hash, and injects it
inline — which runs only because that hash is the second pin in script-src. From there the app is a single verified
closure. Two reusable primitives extend the same guarantee to everything the app loads lazily:
__vcImport(url)— verified module import. The app'simport('./x.js')is rewritten to this; it resolves the target to its signed*.bundle.js, fetches it, checkssha256 == the manifest entry, and imports it from a blob. Lazy feature chunks (the enclave route, the PDF worker) load this way.__vcFetch(url)— verified bytes fetch. For a path covered by the signed manifest it fetches, hashes, checks, and returns a verifiedResponse(or throws); for anything not in the manifest — a dynamic API call, live data — it passes through untouched (the egress-lockconnect-srcstill governs). The manifest is the discriminator: release asset → verify; runtime data → pass through.
Workers get the same treatment: the loader pre-verifies each worker's bundle, starts it from a verified blob URL (so
worker-src blob: admits only checked bytes), and hands it the signed manifest so the worker can __vcFetch-check
anything its runtime pulls in — e.g. the on-device speech model's WebAssembly (code) and weights (data). The build
stage tools/build-verified-app.mjs bundles the app and each worker, rewrites new Worker/import() to the verified
shims, and writes a signed verified-app.json sidecar.
Third-party assets are frozen, then verified
Large third-party binaries — the transformers.js runtime, the ONNX-runtime WebAssembly, the Whisper model — used to be
fetched at deploy from moving CDN/registry refs with no integrity check, so a deploy would sign whatever the CDN served
that day. They are now frozen: fetch-whisper.sh verifies every byte against a recorded pin
(tools/whisper-assets.sha256) and aborts on drift, and the manifest covers them so __vcFetch can check them at load.
The WebAssembly is code and must be verified; the model weights are data (a swap yields a wrong transcription,
not code execution) — both are verified here regardless.
The pinned bundle — collapsing the client to one shell
Status: DESIGN, not built. Live today: the egress-lock CSP, the signed reproducible render build,
/cert.json, and CSP-sha256 pinning of the shell's inline script. Not yet shipped: extending that pin to the shell's imported module closure via a bootstrap loader + signed client manifest. It is the web-side complement to the attested client and the piece that lets the reproducible-build proof (verify Tests 6–7) cover the code the browser actually executes, not just the render and inline shell.
The gap, precisely. The /space page is a small HTML shell: an inline app module (CSP hash-pinned) plus import
statements pulling in ~23 sibling modules — e2ee.js (your encryption), recovery.js, backupVault.js, and the rest.
Those imports pin the names of what loads, not the bytes; the modules load under script-src 'self'
(same-origin, not content-pinned). So a swapped e2ee.js survives a shell-only check, the egress lock doesn't catch it
(it can fold your key into an allow-listed request, or simply weaken the crypto), and an external curl | sha256sum
verifies a different fetch than your session (split-view).
This is not self-attestation — it is a bootstrap. A page cannot verify itself. This design does something narrower
and achievable: it collapses the client's verifiable surface from ~23 moving files to one small, stable shell by
having the shell content-pin everything it loads. It is measured boot for the web. The mechanism: the build signs
{path: sha256} for the transitive module closure into /cert.json (shellSha256, closureSha256, modules[]); the
shell replaces import './x.js' with loadVerified('./x.js') — fetch once → hash → compare → execute that exact copy
via a blob: module URL, else fail-closed (one fetch, verify, run — never re-fetch, or split-view reopens at the
module level); rebuilding published source yields the same manifest, so verify Tests 6–7 grow to cover the
whole client closure. A swapped module then fails to load rather than silently running. The shell's own bytes still
need an external anchor — browser CSP + signed hash today; transparency gossip or a native/extension verifier to fully
close it.
Where trust bottoms out, and honest residuals
| Root | For |
|---|---|
| The pinned platform key (published, out-of-band) | the whole signature chain |
| The loader's hash (the one thing the verifier pins) | that only the real loader is the entry |
| Math — signatures and SHA-256 | every byte check |
| The browser + extension running faithfully | the enforcement itself |
Witbitz vouches for nothing about itself that isn't checkable against a key it doesn't control at verification time. The residuals, stated once for the whole page: verification is integrity, not correctness — a genuine bug in honestly-signed code is orthogonal, so receiver hardening (XSS-safe render, sandboxed widgets, validated tool inputs) still matters; without the verifier extension a naked browser has no out-of-band signal that the loader ran honestly (the toolbar badge is what a page can't forge); and attestation protects the code and the key, not the fact that plaintext reaches a model provider — the strongest-privacy tier still needs a BYO or enclave-hosted model (the attested tier).
Part 2 — Confinement: who can touch the key
The verification plane answers what code runs. This plane answers the other half — who can touch the room key — and it is the older, load-bearing idea, live in production: room-key custody lives in an outer frame the app cannot read.
The one idea, and the vault sandwich
Room-key custody moves out of the app frame into an outer frame the app cannot read. A vault (its own origin) holds the account master and the room keyring and frames the keyless app as an iframe. The app boots with no key in its URL and no key in its storage; the keys it needs arrive by a handshake it can't widen.
vault (L1 — holds the master + room keys, top frame, un-framable)
│ frames the app with ?fullapp=1&vcp=1&evictmk=1 (NO key in the URL)
▼
the app (L2 — separate origin, keyless: its live key variable stays null)
└── ready{room} → key{room, mk} (postMessage, origin-pinned both ways)| Layer | Realm / origin | Holds | Never holds |
|---|---|---|---|
| L1 vault | the vault origin (top frame) | account master, room keyring, recovery UI, identity ceremony, the login/account pixels | — |
| L1 Kernel | an L1 Web Worker (separate heap) | room → mk and all mk-crypto |
full topology, network egress |
| L2 app | the app origin (iframe, keyless) | the view-models it renders; its live key variable is null | the master, the keyring, the vault's storage |
Three inversions versus the naive "put the key in the app's URL" design: the outer frame is the trusted one; the key
arrives by handshake, not a URL fragment; the app is a separate origin, so the Same-Origin Policy is the wall,
not the app's good behavior. The app is the same build as standalone — a runtime flag (IN_VAULT) selects the
confined behavior, and the vault forces evictmk=1 so the current room's key is never a live main-thread variable. The
vault is itself un-framable (frame-ancestors 'none' + X-Frame-Options: DENY); the login and account pixels have
to live in it, because a cross-origin iframe can't run FedCM / Google sign-in / the recovery overlay — the ceremonies
that touch the master.
Why the outer frame, not just discipline. A single-origin app can intend to keep its key from its render code, but
nothing enforces it — an XSS or supply-chain slip in any module reads the same-origin localStorage and the live key.
Splitting the vault onto its own origin makes the boundary browser-enforced: the app frame's
window.top.localStorage throws SecurityError. That is the difference between "we're careful" and "the platform won't
let it."
How the app gets keys without holding them. Two paths, both keeping custody outside the app's persistent reach — on
demand (boot keyless, post ready{room}, the vault answers key{room, mk} fed to the Kernel worker) and in bulk
(the account's index room carries room → mk for every Space; the Kernel absorbs every key from the index doc
worker-side, which is why a new device needs only the index-room pointer to open everything). The full app↔vault channel
is a small origin-pinned postMessage protocol (vcHandoff), every message gated on the exact peer origin.
The kernel and Atlas
Inside the vault sandwich, the key never sits as a plain variable — it lives in a Kernel: a Web Worker that holds every room key and does all the crypto, taking semantic requests in and never letting a key back out. Atlas is the sibling idea for the metadata (the room graph).
Status. The Kernel is built and, for key-learning from the index, default-on in production. The keyless-index mechanic ships; the full metadata-confinement Atlas realm is a deliberate non-goal for today's threat model and a documented target beyond it.
The organizing principle is least authority by information class — cryptographic secrets ≠ sensitive metadata ≠ presentation ≠ transport — so a compromise of one exposes only its own class:
| Part | Realm | Holds | Never holds |
|---|---|---|---|
| Kernel | an L1 Worker (separate heap) | room → mk, all mk-crypto |
full topology, network egress |
| Atlas | a sibling L1 Worker | the topology graph (rooms, titles, lane/pipe edges) | raw keys, network egress |
| L1 broker | the loader's main thread | capabilities/ports, opaque ciphertext in transit | keys, topology plaintext, view-models |
| App | the L2 iframe | the scoped view-models it renders | keys, the full graph |
The Kernel (l1-worker.js) takes semantic ops — poll, submitTurn, readState, seal, unseal — and does the
mk-crypto and entry-signing inside its own realm; the key never posts back out, so a render-layer compromise can
ask the Kernel to work but can't extract the material. Stated precisely so it isn't overclaimed: a Worker is a separate
JS realm and heap with no direct object-reference access — not physical memory isolation; the boundary is only as
strong as what's forbidden across it (no SharedArrayBuffer, no key-bearing transferables returned, no debug interfaces
left on).
Atlas is used two ways. The keyless-index mechanic (built, default-on, ?atlasidx): the index room's
room → mk pointers would leak keys if surfaced, so the Kernel absorbs them on unseal and returns a keyless graph,
and injects them on seal so the app never touches a raw pointer even on write. The full metadata-confinement
realm (target, descoped) would give the graph its own Worker and hand the app only keyless projections — closing the
residual where a compromised render layer can read your Space graph (titles, lane membership) — but it's an expensive
projection-completeness grind, and for the current threat model it's a non-goal: the app is the file browser and may
see the directory listing; only the contents' keys are confined.
The strongest anti-exfiltration lever: L1 is the sole egress. Only the L1 broker has network access, and it moves
opaque ciphertext it cannot interpret; the Kernel and Atlas can interpret sensitive data but have no ambient network
access. So the components that can understand the data cannot send it; the component that can send cannot understand
it — which directly closes the covert-channel exfiltration residual. Capability discipline hardens the ports as they
mature: scope bound to the port not a parameter (poll() with no room argument, so a caller can't widen authority);
explicit revocation (every capability is revocable, a membership/room change bumps the epoch); and bootstrap → LOCK
(broad setup interfaces disappear after a short boot phase — privilege-dropping as in OS design). Background
notifications must not reintroduce a raw key on the Service Worker: the design derives a one-way notification key
NK = HKDF(mk, "notif") scoped to short previews, epoch-rotated and per-device revocable.
Part 3 — The attested client (native)
Status: the server-side seam is Implemented (built + tested, behavior-neutral, not enabled); the native clients are Design. A room's owner-signed policy can carry
requireAttestation, and the render verifies a freshness-bound platform attestation against it (bound to the member's signing key so it can't be replayed) — implemented and tested with a mock verifier. What still needs the native side: the reproducible native shells and the real App Attest / Play Integrity / Keystore / TPM verifiers (today stubbed and fail-closed, so arequireAttestationroom refuses every turn — the seam is ready for the verifiers to drop in). This is the missing symmetric half of the server attestation the rest of the platform already does.
You cannot verify the code a browser is running — the user owns the runtime; any check a page runs on itself can be hooked, and nothing stops a user from calling the API with their own client. The response is not to attest the browser (unwinnable) but to offer, opt-in, a client whose code can be attested: the exact static, egress-locked, reproducibly-built web bundle, wrapped in a thin native shell whose only jobs are to (1) present a hardware attestation, (2) hold keys in the Secure Enclave / StrongBox / TPM so the room key never sits in JS, (3) load the bundle locally into a locked web view, and (4) freshness-bind the attestation to each action. One source of truth across web and native; the audit surface is a thin generic shell plus the web code reviewers already read.
The one rule that makes it real, not theater: the web bundle must ship inside the attested binary and load locally — never off the network. Bundled and loaded from a local scheme, the app's signature covers its embedded assets, so an attestation of "genuine, unmodified app" includes the bundle. A web view pointed at a live URL (including Android Trusted Web Activities) attests the shell, which then runs whatever the network hands it — worse than a plain browser, because it launders trust it never earned. And the attestation must bind to every action, not once at admission, or a member attests with the genuine app then switches to a patched client for the writes that follow — the room's existing freshness challenge is the hook.
| Platform | Shell | Attestation | Keys | Notes |
|---|---|---|---|---|
| Android | WebView | Play Integrity, or hardware Keystore attestation (X.509 rooted in Google, carries app-signing digest + Verified Boot) | StrongBox / TEE | Cleanest full chain. Self-distributed + reproducible APK + Keystore attestation gives source → binary → attested. |
| iOS / iPadOS / macOS | WKWebView | App Attest (hardware-backed) | Secure Enclave | Integrity strong; reproducibility partial — Apple re-signs the shipped binary, so you lean on a transparency-logged build pipeline for provenance. |
| Windows | WebView2 | Assembled — TPM 2.0 measured boot + Azure Attestation · TPM key attestation · Authenticode/MSIX + optional WDAC | TPM 2.0 | No single "App Attest for Win32"; strongest on a managed enterprise fleet (MDM + WDAC). |
So integrity of the running bundle is attestable on every platform; end-to-end reproducibility of the shipped
binary is Android-clean, iOS-partial, Windows-DIY — state that split plainly. The egress lock generalizes: today
it is the CSP header; with native it splits into one canonical signed policy (the room-data path goes only to the
declared origin; the shell reaches only a small fixed set of platform endpoints — attestation provider, push) and a
per-platform enforcement of it. Every native OS control is coarser than connect-src, so on native the fine-grained
guarantee leans on the reproducible, attested binary rather than a readable header: on the web you read a header;
on native you reproduce and attest the binary. The web is not the weak link in the egress story — it's the platform
with the cleanest, self-verifiable lock.
How a room requires it. "Only attested clients may join" is not a client-asserted flag — it's an admission
condition set by the room/app owner and verified on the server, in the same slot that carries "only my registered
users" (the owner rule). At join and on each write the server checks the
attestation, bound to the member's signing key; other members can be shown a participant is on an attested client.
Admission and client-integrity become one policy: { authenticated identity } AND { attested client }. It shrinks the
hardest residual — content injection between members — without making the client omnipotent-proof (a rooted device, a
bug in the genuine app, and untrusted content from others remain, so receiver hardening still matters). Because
requiring an install trades away open-a-link reach, it is opt-in and additive: web rooms keep the untrusted-client
architecture; attested-native rooms get this stronger tier on top.
Part 4 — The verifier extension
The verified client can check itself, but a naked browser has no out-of-band way to know the check ran honestly — an
origin could serve a loader that lies. The verifier is a small browser extension that removes that last assumption: it
lives in the toolbar, outside the page, forces verification the origin can't opt out of, pins the loader by hash, and
shows a badge the page cannot forge. It ships in the repo at docs/verified-client-real/extension/.
Status. Built and proven headless against the deployed staging app (Chromium, DNR-forced CSP, CDP-confirmed). This is the shipped CSP-loader approach; the transparency-log and enclave extensions that go further are the power-user stack roadmap.
The shape is a per-brand, single-origin verifier whose host_permissions are scoped to one app origin — e.g.
a bank's own "Bank X Verified Client." Minimal blast radius, a trivial least-privilege review, and the brand owns the
whole chain. The same generic core is just configured with { origin, pinnedKey, bundleMode }. It does two
independent jobs, both at the network layer: (1) force verification — a declarativeNetRequest redirect adds
?vc=1/?vcbundle=1 to every /space navigation, so the origin can never serve the app unverified; (2) force the
policy — a modifyHeaders rule sets the CSP the renderer sees (the origin's strict policy in Tier A, upgrading a
report-only egress-lock to enforced; the loader-only policy in Tier B, no 'self', worker-src blob:). CSP only ever
intersects tighter, so a forced strict policy is a floor the origin cannot loosen. Alongside that it independently
attests the release — running the same pinned-key → cert → manifest chain itself — and paints a toolbar badge
(green ✓ / red !) the page cannot draw.
Why it works on mainstream Chromium (no response-body reading). An earlier design required Firefox and
webRequest.filterResponseData to hash the exact bytes the browser loaded (Chromium MV3 can't read response bodies). The
CSP-loader model sidesteps that: instead of observing the bytes, the extension forces a CSP that pins the loader's
hash, and the loader verifies everything else — there is no byte to race, only the pinned loader can be the entry. That
makes it a standard MV3 extension using declarativeNetRequest (applied before the renderer sees the response). The DNR
rules are pre-armed at startup so the first navigation is already covered — no uncovered first load, no reload.
Honest residuals. A page's own service worker can synthesize a navigation response that never traverses the
network, so the verified policy must include SW disposition (approve a specific SW hash or forbid one), enforced
on-origin; the origin-served loader is the cost of keeping the brand's real domain (a chrome-extension:// page would
break passkeys, cookies, TLS identity). The badge is the user's ground truth, but a naked browser has the same phishing
surface as any site — the extension is the additive apex for people who want to check.
Install the verifier — a five-minute walkthrough
The extension in
docs/verified-client-real/extension/runs today on Chromium (128+) and enforces against the staging app (preview.witbitz-spaces.pages.dev). It's an unpacked developer build, not yet a Web Store listing.
- Point it at the app origin.
config.jsonis the entire app-specific surface:origin(the app you want verified),pinnedKey(the platform signing key from verify it yourself — the one trust anchor, compared out-of-band), andbundleMode(trueforces Tier B, loader-only CSP;falseis Tier A verify-in-place). - Load it unpacked.
chrome://extensions→ Developer mode on → Load unpacked → select theextension/folder. The service worker starts and pre-arms its rules immediately. - Open a Space and watch it verify. Navigate to
…/space. Without doing anything else you see: the URL redirect to…?vcbundle=1(Tier B) or…?vc=1(Tier A); the app boot normally (the loader fetched the bundle and workers, checked each hash against the signed manifest, and injected them); the toolbar badge turn green ✓. - Confirm it's really enforcing. Turn the extension off and reload — the URL stays
/spaceand the badge is gone (the contrast is the proof). Inspect the/spaceresponse headers with the extension on: acontent-security-policywith no'self'inscript-src(Tier B) and the report-only header removed. If the release ever fails the chain — a swapped byte, a bad signature — the loader shows "couldn't verify this app" and the badge goes red. - Verify the extension itself (the one out-of-band act). The whole system hangs on trusting the verifier, so check
it once: read its four small files, confirm the
pinnedKeymatches verify it yourself, and — for the strongest anchor — prefer an extension authored by someone other than the app vendor, so it isn't the vendor vouching for itself. That single check, done once, is the only thing you take on faith.
Part 5 — The power-user stack
Status: TARGET ARCHITECTURE. It composes shipped pieces (signed
/cert.json, reproducible render build, readable egress-lock, themkseal/mkUnsealwire format) with designed ones (the pinned bundle) and net-new ones (afilterResponseDataverifier extension, transparency-log publishing + gossip, and the render in an attested enclave — the attested tier). It is the honest answer to "how does a user know they run a good app?" for a user willing to run one extra tool.
Who it's for: the power user who will install Firefox (Android or desktop) and one verifier extension — because a mobile web page alone cannot verify itself and an operator serving its own app proves nothing. The mainstream reach (open-a-link, any browser) keeps the existing model; this is the additive apex. The property that makes it "perfect": one deliberate trust decision, verified out-of-band once — then everything is checked automatically, on the real bytes, from browser chrome, with cheating detectable. Witbitz is removed from the trust base.
The five components: (1) a verifier extension — open-source, reproducible, ideally authored by someone other than
Witbitz, trust anchors pinned inside it, using webRequest.filterResponseData in Firefox to hash the exact bytes
the browser loaded (the same fetch the page uses — what makes it split-view-proof); (2) the
pinned-bundle client; (3) the signed /cert.json (shellSha256, closureSha256, modules[],
lambdaCodeSha256, sourceSha256, gitCommit, egress, enclave); (4) transparency logs — every build's hashes
to ≥2 independent append-only logs; the extension checks inclusion and gossips signed tree heads, so a split-view
is detectable by any one honest observer; (5) the enclave (Nitro) — the render runs attested, the extension verifies
PCR0 == the reproduced measurement chaining to the Nitro root.
Per-load flow (automatic after a one-time setup): hash the shell + every module the browser actually loaded → verify
/cert.json against the pinned pubkey → loaded hashes == the signed manifest → hashes are in the transparency
logs with no split-view → verify the enclave attestation → confirm connect-src == the signed egress →
badge green/red. Trust bottoms out entirely outside Witbitz — Mozilla, the independent extension author, the AWS Nitro
root, independent transparency logs, and math. Not zero-trust — minimal trust, every deviation detectable and
attributable. The likeliest overclaim, stated plainly: attestation protects the key and the code, not the fact that
plaintext reaches a model provider — the strongest-privacy tier still needs a BYO/enclave-hosted model. And on iPhone,
until the EU's alternative-engine rules give iOS a Firefox-grade extension API, iOS web can't do the byte-level check
— an iOS power user's strong path today is the native App Attest app (Part 3).
Part 6 — The certified app
Status: DESIGN / direction. An answer to "how do I know an app is good?" for apps that are not open-sourced, by making the app model small enough that an automated, attested audit is sound. It defines what good means; the power-user stack verifies you received the good build.
Open source + plural human review is the gold standard for "no hidden backdoor," but it demands publishing the source, which most builders won't do. Can you get a verifiable "this app is good" without open-sourcing it? The move: don't out-analyse an adversary's arbitrary code — remove arbitrary code from the problem. A Witbitz app is almost entirely a manifest + UI — a declarative capability request (what data, which tools, where it may send) plus a constrained interface, closer to a policy than a program, and policy is checkable. Complexity disqualifies: an app too complex to audit cleanly is auto-rejected, which kills the main evasion vector for free (obfuscation, time bombs, hidden data-dependent paths are all complexity, and you can't hide a backdoor in convolution if convolution itself fails the gate). This converts "determine what an arbitrary program does" (undecidable) into "check a small declarative artifact against a policy" (tractable, much of it deterministic).
The mechanism: a fixed, confining runtime proven once for all apps (it confines every app to its declared capabilities, keeps the egress-lock, sandboxes the UI, forbids arbitrary code — one small shared artifact, openable and attestable once); plural attested checkers from different entities with different methods, each receiving the source inside an attested enclave (fed to the machines, not the public) and verifying the app matches its privacy certificate, with N-of-M agreement; deterministic where possible (declared egress and capabilities checked with no model), LLM where necessary (does the UI match the stated purpose); and a public verdict log — build hash + privacy certificate + checker set + verdicts — so "N independent attested checkers approved this build" is accountable and challengeable without publishing source. The trust moves from "audit each app's arbitrary code" to "a small fixed runtime + an objective complexity gate + plural attested checkers" — smaller, mostly deterministic, mostly openable. Hold the claim tight: the defensible guarantee is "a simple, capability-confined app, approved by N independent attested checkers against its declared certificate," not "any app is safe."
Next
- Verify it yourself — what's checkable from a shell today
- The attested tier — the server-side half (operator blind in use)
- Trust model · Privacy tiers · Identity and admission
Machine-readable source: client-architecture.md · Generated 2026-08-29T18:46:30Z · build f3ff88cc · every doc in one fetch: llms-full.txt (HTML) · ← identity-and-admission · the-attested-tier →