How it works · for engineers
Signed orders in. Origin receipts out.
Rootz Receipts adds two extensions to OpenShell's published extension points, keeps an append-only record of each sandbox session, and hands every result an origin receipt that verifies offline. No fork of OpenShell, and no changes to your agents.
The flow
Eight steps from an officer's signature to a stranger's check.
Each step names the component that does it. Only two of them run inside OpenShell, and neither holds a signing key.
- Officer
Signs an order
The policy, in OpenShell's own YAML, plus the prover's verdict, the target sandbox and a validity window.
- Interceptor
Gates the install
OpenShell's gateway asks before committing. No valid order, no install.
- Session log
Writes genesis
Leaf 0: the order and the policy hash in force, which must match what was signed.
- Middleware
Checks each action
Live controls are compared with the authorized ones before every request. Drift is denied.
- Middleware
Commits the bytes
Request and response bodies are recorded by length and SHA-256.
- Session log
Seals checkpoints
A signed tree head over every leaf so far, consistent with the one before.
- Rootz Receipts
Issues the receipt
The exchange, its inclusion proof, the checkpoint, the orders, the controls and the authority evidence.
- Anyone
Verifies offline
The free verifier prints five lines. No account, no network, no console access.
Authorize
Orders and the interceptor
No policy reaches a sandbox unless it arrives as a signed order. Installing a policy is the first order.
What an order is
An order is an authorized instruction, signed by an officer. In the first version there are two: install a policy and change a policy. Day one, an order is a signed, content-addressed file: canonical bytes, with its digest as its name, stored wherever you keep files. It carries:
- the digest of the policy document, written in OpenShell's own policy YAML, so there is nothing new to learn;
- the boundary it must stay inside (the widest policy the company permits for this class of sandbox) and the verdict of OpenShell's policy prover against that boundary, so the officer signs the policy and the proof that it stays inside;
- the change type: install, narrow or widen;
- the target gateway and sandbox, a validity window (orders expire, because authority goes stale) and a nonce against replay.
Where it is enforced
A gateway interceptor registered on OpenShell's published interceptor extension point (RFC 0010, the validate phase) checks the order before OpenShell commits the change. It covers sandbox creation, configuration updates, credential-provider attach and rotate, and policy-advisor approvals, so every path that changes what a sandbox may do passes the same gate. A missing, expired, altered or under-authorized order is refused with a named reason, and the refusal is written to the record.
Change is another order
Narrowing may be signed by a lesser authority. Widening needs the officer, and must carry a contained verdict from the prover; not_contained, unsupported and inconclusive are refused. Each accepted change is a leaf in the session log, so a receipt's Process line can say which order installed the policy in force at that instant.
Moment 1: an unsigned policy is refused · Moment 2: a widening change is refused
Run
Middleware and byte commitments
Agents run unchanged. Supervisor middleware sees every network request and response, checks the controls first, and commits the exact bytes. It does not see local file writes or process output; that is a later phase.
The middleware registers on OpenShell's supervisor middleware extension point (RFC 0009), using the request hook before credentials are attached and the response hook before the answer is returned. It is fail-closed by default. Model calls are ordinary egress from the sandbox, so the middleware sees the prompt going out and the answer coming back.
Before each request: the controls manifest
A controls manifest is the state of the controls at an instant: the policy hash, version and revision OpenShell reports, the order that installed it, the image digest, the digests of executables observed, and the platform evidence, labelled measured (a hardware root such as a TPM or confidential VM attested it) or declared (the platform reported it). Any change to any field is a new manifest. If the live manifest differs from the session's current one, the request is denied until a signed order accepts the change.
Every request and response: a commitment
The middleware records each request and each response as a leaf: method, host, path, the decision and its reason code, and a body commitment, { bytes, sha256 } over the raw bytes. Digests are written as sha256: plus base64url. Change one byte of an answer after it leaves, and the commitment no longer matches.
The middleware and the interceptor hold no signing keys. They propose leaves; the session signs checkpoints. A bug in the ingest path can therefore never become a forged signature.
Record
Session log and checkpoints
One append-only log per sandbox session. Absence is a row: refusals and drift are written, not dropped.
| Leaf | Written by | Records |
|---|---|---|
| genesis | interceptor | The order, the controls manifest and OpenShell's policy hash, which must equal the hash the officer signed |
| policy change | interceptor | The order that changed the policy, and the new manifest |
| request | middleware | Request id, manifest, method, host, path, body commitment, allow or deny, reason code |
| response | middleware | Request id, status, body commitment |
| refusal | interceptor or middleware | What was refused, and the named reason |
The log is a Merkle tree built to RFC 9162, with domain-separated leaf and node hashing. Leaves are not signed one by one. Periodically, and when the sandbox is deleted, the session seals a checkpoint: a signed tree head stating the log's size and root at that moment. Consecutive checkpoints must be provably consistent, so nothing earlier can be rewritten without the break showing.
The checkpoint records how its signing key is bound to the platform: none, a TPM-bound key, or a key generated inside a confidential VM and named in its attestation report. The record is only as strong as where that key lives, and the receipt says which.
Verify
What an origin receipt contains
The portable bundle that leaves with each result. It is not signed as a whole; every part inside it is either signed or proven.
| Part | What it is |
|---|---|
| Subject | The request leaf and its response leaf: the exchange the receipt covers |
| Inclusion | Inclusion proofs for both leaves against the checkpoint |
| Checkpoint | The signed tree head the proofs are checked against |
| Orders | The genesis order and every change up to the subject |
| Controls manifest | The controls in force for the exchange, including the effective policy hash |
| Authority | Evidence that the order's signer was authorized at the instant of signing: the hops from the company's registered root, with validity windows |
| Materials | The other requests in the session that the answer followed (what was fetched), each with its inclusion proof. Fetched, not entailed |
| Keys | The public keys needed to check it |
The report
Five lines, four statuses, no overall boolean.
The verifier reads a receipt and prints five lines, always in this order. Each has exactly one of four statuses, with the checks and reasons behind it.
| Line | The question it answers |
|---|---|
| Authorized by | Which officer, of which company, under which order, and was that authority valid at that instant? |
| Specification | What exactly was the agent asked, byte for byte, and was it allowed under the controls in force? |
| Materials | What did the agent fetch before it answered? If nothing, the receipt says the answer rested on nothing. |
| Process | Which signed order installed the policy in force, which controls were in place, and what was measured versus only declared? |
| Integrity | Is this exchange in the signed session record, complete and unaltered? |
- verified
Checked, and it holds.
- asserted
Present, but not independently checked here, for example when verifying offline. The reason is stated.
- unavailable
Could not be evaluated, with the reason. Never shown as failed.
- failed
Checked, and it does not hold. The named check and reason are shown.
Asserted is never shown as verified, and unavailable is never shown as failed. A weak claim is not a fake claim; an undisclosed one is. Each line's depth (L0 to L3) is computed from the evidence when the receipt is read, never stored or asserted by the issuer.
Anyone, anywhere
Offline verification
The verifier needs no account, no Rootz service and no access to the operator's systems.
The verifier is a free tool for the browser and the command line. Its core has no third-party dependencies, and it never imports the parts of the system that produce receipts, so it cannot be coupled to them.
- Signatures, digests, byte commitments and inclusion proofs are checked locally and are verified or failed.
- Facts that need a read of the company's public authority chain are reported asserted when offline, with the reason. With a network read, they can be verified as of the instant the order was signed.
- The report states when it was verified and where that time came from.
$ ask-orders verify summary.receipt.json --offline
Authorized by asserted not-evaluable-offline · signatures checked; company chain not read
Specification verified
Materials verified 3 sources fetched and committed
Process asserted platform-evidence-declared
Integrity verified checkpoint 42 · signature valid
Illustrative output. The command-line tool ships with the pilot.
Data, not agent
Not that the agent was contained, but that the data came from a specific, measured container.
A finding from our own lab, explained in plain language.
OpenShell's claim is about the agent: it ran inside a policy container. That is a runtime property, and it is reported in the operator's console. It is the right claim for the operator.
The recipient of a result needs a different claim, about the data: this output came from an agent in a specific container, under specific policies, controls and measurements, and the proof travels with the result. "Specific" turns out to matter.
What we measured, on OpenShell v0.1.2
We created two sandboxes from the same policy file, one with a credential provider attached and one without. OpenShell's stored policy revision hash was identical for both. But the provider had quietly added read-write network access to an external API. Only the effective (admission) policy hash, the hash of the policy actually applied, showed the difference.
Stored policy revision hash
- before
- sha256:rev7…Q2c8
- after
- sha256:rev7…Q2c8 (same)
Effective (admission) policy hash
- before
- sha256:eff3…k9Lm
- after
- sha256:eff4…Zt0w (differs)
Hash values shown are illustrative; the behaviour is what we measured.
What that means
Anyone relying on the stored hash to describe the policy in force would have described the wrong policy. This is not a flaw in containment: the sandbox enforced what it was given. It is a gap in what travels: OpenShell reports both hashes, in different places. The origin receipt binds to the effective hash, so a recipient sees the policy that actually applied. And because a provider attach is one of the changes the interceptor gates, Rootz Receipts refuses it without an order; had the change arrived any other way, the middleware would deny the next request on drift.
Keep the chain alive
When an output becomes the next input, the receipt goes with it.
The chain is the record of the reasoning that reached a conclusion.
People rarely check origin; they want the output. Agents can be built to check, and to carry the receipt forward. When agent B uses agent A's result, B's origin receipt names A's receipt by digest under Materials. The verifier checks B, follows the link, and checks A.
- Intact link: the named receipt is supplied and its digest matches. Materials is verified.
- Altered link: a receipt is supplied but is not the one named. Materials is failed, with the reason.
- Missing link: a receipt is named but not supplied. Materials is unavailable, with the reason.
The chain is tamper-evident, and breaks are visible. It answers "how did we get here?", points the conversation at the step that matters, and gives later decisions a record of what went right and what went wrong.
Status: today's design records what an agent fetched within its session. Receipts that name upstream receipts are the next step of that design, and the demo moment illustrates how it will read.
Install
Into OpenShell's published extension points. No fork. No agent changes.
Keep everything you have. Rootz Receipts adds the origin receipt your customer can check.
Order interceptor
Registered on the gateway interceptor extension point (RFC 0010). Refuses sandbox, configuration, provider and policy-advisor changes that do not arrive as a valid order. Writes genesis and policy-change leaves.
Controls and commitments middleware
Registered on the supervisor middleware extension point (RFC 0009). Checks the controls manifest before each request, commits request and response bytes, denies on drift.
- Operators keep using OpenShell's usual commands to create sandboxes and set policies; the interceptor checks the order behind each one.
- Agents, models and tools are unchanged.
- Recipients install nothing; the verifier runs in a browser.
- Keys and clocks are injected: hardware keys for officers, a TPM-bound or confidential-VM key for checkpoints, your HSM where you have one.
- Receipts and logs live in your store, content-addressed. Exporting them is always free.
A workstation running OpenShell
For the developer or analyst whose agent works at their desk.
Process line: declared, or TPM-bound where the machine has one
Your OpenShell or Kubernetes
The two extensions in your environment, keys in your HSM or a hardware enclave.
Process line: whatever your platform can prove
Rootz Receipts Cloud
Managed OpenShell with Rootz Receipts inside a confidential VM Rootz cannot read into. Your officers still sign every order.
Process line: confidential-VM report, signed by the chip vendor
Deployment options in the design. The pilot runs on your OpenShell; the managed option follows. The receipt is the same wherever the agent runs; only the Process line changes, to state what the platform could actually prove.
Built on your authority
The root is your company, not a vendor.
Every order traces back to a key your company registered and controls, checked as of the instant the order was signed. Here is Rootz Corp's own chain, live on Ethereum since 2024, which anyone can check today.
- Legal registration
Rootz Corp., Delaware file 3246351. SEC EDGAR CIK 0002143583. The company key is a registered trade name.
- Company key
0xD36AAf65a91bB7dc69942cF6B6d1dBa4Ef171664
A 2-of-3 multisig on Ethereum, acting in public since 2024. - Officer key
A hardware wallet, authorized by the company in an on-chain transaction, with an expiry. Receipts check that authority as of the instant each order was signed; revocation never rewrites the past.
- Orders
Signed by the officer. Each names the policy, the boundary it must stay inside, the sandbox, and its validity window.
Is this blockchain? Not required to use it. The root of authority is your company's registered key; a public chain is one optional way to anchor it.
Want to see it on your own OpenShell?
Design partners get the pilot first: one workflow, one policy, one counterparty, 30 days.