Skip to main content

Case Study

ThingStore: Supply-Chain Security for an App Store, Built Solo

What it takes to safely run other people’s AI-generated code: signing, gates, sandboxes, brokers, and a revocation feed.

In ProgressJun 2026 - PresentSolo Developer

Updated Jul 11, 2026

Currently BuildingEd25519 Publisher Signing5-Layer Publish GateFail-Closed by Default

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.

1

Manifest schema validation

Every distributable unit is one JSON manifest, projected through a kind registry mirrored in Rust and TypeScript with drift checks.

2

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.

3

Capability-ceiling lint

Requested permissions are checked against a per-kind sandbox ceiling. A data pack cannot ask for what a subprocess gets.

4

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.

5

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.

Tech Stack

Backend

Cloudflare Workers (registry)Supabase PostgresWebCrypto Ed25519Rust (ed25519-dalek verify)Rust install pipeline (zip-slip safe)

Infrastructure

R2 (content-addressed bundles)Electron session partitioningHTTP CONNECT egress broker (Rust)macOS Seatbelt / sandbox-exec

Frontend

React + TypeScript store surfaces

AI

LLM risk-review gate layer

Tooling

Vitest (edge handlers)

Want to discuss the architecture?

Get in Touch
ThingStore: Supply-Chain Security for an App Store, Built Solo | Jeffrey Michael Johnson