I'm building SPOE, an AI app builder. Every tool in this space says "you own your code". I wanted to be able to prove it, so every export SPOE produces is signed. This is how that works, in enough detail that you can poke holes in it.
When an AI writes your app, two questions follow the code around. Is this exactly what I was shown? And does it quietly depend on the tool that made it? A ZIP answers neither.
Three files ride along with every project: PROVENANCE.json, PROVENANCE.sig and verify-provenance.mjs.
PROVENANCE.json lists every file with its SHA-256 and size, a hash over the whole tree, which models wrote and reviewed the changes (never the prompts), and the signer's public key:
{
"spoe_provenance": "1",
"project": { "slug": "tint-booker", "stack": { "frontend": "nextjs", "backend": "node", "database": "postgres" } },
"version": { "number": 2 },
"files": [{ "path": "web/app/page.tsx", "sha256": "9f2c…", "bytes": 1834 }],
"tree_sha256": "41ad…",
"generations": [
{ "role": "generator", "model": "…" },
{ "role": "reviewer", "model": "…" }
],
"signer": { "alg": "ed25519", "key_id": "c85280961cc26721", "public_key_pem": "-----BEGIN PUBLIC KEY-----…" }
}
The signature in PROVENANCE.sig is Ed25519 over a canonical form of that JSON: keys sorted recursively, no whitespace. The tree hash is SHA-256 over the sorted lines path\0sha256\n, so the order files happen to be zipped in never matters. The key id is the first 16 hex characters of the SHA-256 of the public key's DER encoding.
The verifier is about 40 lines of plain Node 18+, with no packages and no network:
$ node verify-provenance.mjs
OK signature valid (key_id c85280961cc26721)
OK 30 files match manifest
VERIFIED - exported 2026-10-09T01:24:13Z from project tint-booker v2
It checks that the key id matches the embedded key, that the signature is valid, that every listed file is on disk with the right hash, and the tree hash. It exits 1 if anything is off.
A valid signature only tells you the files match a key. To know who signed it, compare the key id with the keys spoe.ai publishes at spoe.ai/api/signing-keys. The page at spoe.ai/verify does all of this in your browser without up the ZIP, and also lists any file in the ZIP that the manifest doesn't know about. The offline script is getting that same check next.
Before an export is signed, a lint refuses it if anything ties it back to SPOE: an import of an SPOE package, a dependency on one, code reading SPOE_* environment variables, a call to SPOE's API, or one of our internal folders. No warnings, no override.
And CI does the whole thing on every commit: export the scaffold, unzip it into an empty directory, verify the signature, docker compose up, hit the health check. If that fails, nothing ships.
Every change the builder makes is reviewed by a second model from a different model family before it lands. A critical finding blocks the change whatever the reviewer's own verdict says, and a review that times out or errors is never treated as a pass: it waits for a human.
A signature proves integrity and origin, not quality. It can't tell you the code is free of bugs or safe to run; the review and your own eyes are for that. It also says nothing about the prompts, which are deliberately left out of the manifest.
SPOE is at spoe.ai. It's free to start (50 credits on sign-up and a daily top-up), runs on Venice's private models, and your first payment of any size unlocks export for good.
I'd especially like critique of the manifest format and the verifier. What would you need to see before you trusted an export from a tool like this?