The problem with an app store for AI-built apps
GBuild's ThingMaker lets a conversation become a working app. The moment those apps can be shared, a harder problem arrives: you are now distributing untrusted third-party code, written partly by models, to other people's machines. That is a supply-chain security problem, and most marketplaces solve it with human review and hope.
ThingStore is the attempt to solve it with architecture instead: a registry that gates before publish, a client that verifies before install, a runtime that confines during execution, and a revocation feed that works after the fact — even offline.
5
automated gate layers
Ed25519
publisher signing
SHA-256
content-hash verify chain
Offline
revocation still holds
Nothing runs unverified
The client refuses first and asks questions never.
On approval, the registry Worker signs the bundle's SHA-256 content hash with the GBuild publisher key using WebCrypto Ed25519. The Rust client (ed25519-dalek) refuses to install unless the signature verifies and the downloaded bytes hash to the signed value — and the two implementations are held together by cross-language falsification tests, so a quiet drift between the signer and the verifier fails the build instead of shipping.
Install itself is a four-gate, fail-closed pipeline: publisher signature, content-hash byte verify, zip-slip-safe extraction, and a post-extract manifest cross-check with rollback. A forged Builtin source claim gets clamped to Marketplace trust. Bundles are capped at 100 MB so an untrusted archive cannot exhaust the machine.
Five layers before anything publishes
Submission runs a server-side review pipeline. Pass every layer and the Thing auto-publishes; trip one and it auto-rejects with the failing layer and a human-readable reason. An additional egress-scrutiny gate triages the author-declared network allowlist — the same list the sandbox and CSP will read verbatim at runtime — and states its own limits in its source, because a static gate is triage, not a guarantee.
Manifest schema validation
Every distributable unit is one JSON manifest, projected through a kind registry mirrored in Rust and TypeScript with drift checks.
Secret / PII scan
20 token patterns server-side, 22 client-side (the absolute-path pattern is Rust-only), with no-echo-of-matched-value discipline. The client refuses to even build a bundle that trips one.
Capability-ceiling lint
Requested permissions are checked against a per-kind sandbox ceiling. A data pack cannot ask for what a subprocess gets.
Static CSP analysis
Embedded code and HTML are scanned against the same content-security rules the runtime will enforce, before publish rather than after install.
LLM risk review
A model reads what the static layers cannot: intent. Auto-publish on all-pass, auto-reject with the failing layer and a fix-it reason.
Behind the gate sits a human review queue with fail-closed reviewer authorization (a Supabase-uid allowlist — no shared secret ever reaches the renderer), an audit trail on every decision, and a rollout halt switch (AUTO_PUBLISH_DISABLED) for the day the automation is wrong.
Confinement is the runtime, not a wrapper
Publishing gates catch what a scanner can see. The runtime assumes the gates missed something.
Electron session partition
Every installed Thing runs in its own session partition with deny-by-default permission and device handlers, a manifest-derived CSP, and origin-pinned navigation confinement. A missed registration means an empty allowlist, not an open one.
Loopback egress broker
The only network path is an HTTP CONNECT proxy on 127.0.0.1 that enforces the manifest allowlist, resolves DNS inside the broker (the Thing never gets UDP:53), and rejects any host resolving to loopback, private, or link-local space. DNS rebinding and SSRF are designed against, not patched after.
Seatbelt subprocess jail
Third-party subprocesses launch through one door: a generated sandbox-exec SBPL profile. If no profile can be produced, the spawn is refused. Fail closed is the default posture, not a feature.
Revocation completes the loop: a reviewer flips a published Thing to revoked, the client persists a local revoked-set it consults on every enable, and refreshes hourly from the Worker feed. Pulling the network cable does not un-revoke anything.
The gaps are documented, on purpose
A security system that hides its own limits is lying about them.
ThingStore ships with a live inventory of its own holes, written down rather than discovered by someone else: a confirmed macOS Seatbelt defect (Seatbelt cannot host-scope remote tcp, so hostname allowlists produce an uncompilable profile), a missing orchestrator-glue end-to-end test on the install path, and dispatch arms for some data kinds that are still no-ops. Paid Things and the creator revenue share are explicitly deferred behind an off-by-default flag — every published Thing is free until the payment rail earns its way in.
The egress broker's current design carries findings from a red-team pass folded back into the implementation. That loop — probe it, document it, fix it, keep the writeup — is the actual product discipline here.
Where it's headed
The registry Worker, signing chain, install pipeline, session confinement, review queue, creator profiles, remix lineage, and revocation feed are built and testable today; the store ships inside GBuild's private builds. What remains before a public marketplace is the same list the inventory names: closing the Seatbelt host-scoping defect, the end-to-end orchestrator test, and turning on payments only when the trust rails have held.
ThingStore is one subsystem of GBuild. Read the GBuild case study
Trust is not a review badge. It is a chain of checks that still holds when nobody is watching.