Verifying receipts
Receipts, and how to verify them.
Every governed agent action produces a signed receipt. Receipts are verifiable without trusting ORBIT, downloadable as files, and meant to live with you (or whoever you hand them to), not on a public URL.
What a receipt is
A small JSON object recording an agent action and the decision Guardian made about it. Every receipt names the agent, the device, the action, the time, the rule that matched, and the verdict. Receipts that record an executed action also carry the outcome (success, failure, partial).
Each receipt is signed by the ORBIT receipt sequencer using a published public key. The signature covers a canonical hash of the receipt’s content. If even one byte of the receipt changes, the signature breaks and verification fails.
The .orbitproof file
When you download a receipt from /audit or from a history record, you get a file with the .orbitproofextension. It is JSON, you can open it in a text editor, but its primary use is verification by ORBIT’s tools or the offline CLI.
The same file is what you hand to a partner, an auditor, or a security reviewer. They verify it the same way you do.
Verifying on the web
Open /verify. Drop the file into the upload box, or click to browse. The web verifier uploads the parsed receipt to ORBIT, which checks the signature server-side and returns the result. For no-upload verification, use the offline CLI below.
You get two answers, separately:
- Authenticity. Is the file an authentic, untampered ORBIT receipt? Yes or no, with the reason on a no.
- Content. If authentic, the receipt is read back in plain language: the action, the decision, the coverage state, the receipt tier.
These two are presented separately on purpose. A signature pass tells you the receipt is real; the readback tells you what the receipt says happened. Conflating them (“verified safe action”) would be dishonest.
No sign-in required. Anyone with the file can verify; that is the point. If you do not want to send the file to ORBIT at all, use the offline CLI.
Verifying offline with the CLI
Not yet available. The orbit-verify CLI is on the roadmap and not currently served. Until this ships, use the web verifier above. This section describes the offline path the CLI will provide once published.
The verifier is what auditors and third parties rely on to decide whether receipt evidence is real, so its install path is itself part of the trust story. At launch the CLI ships as a signed release artifact, and the documented install steps require verifying that signature before the binary runs. We will not publish a pipe-to-shell installer for the verifier: an attacker who could persuade a user to run a fake orbit-verify defeats the rest of the trust chain.
The planned install flow:
# 1. Download the signed release artifact for your platform from GitHub Releases.
curl -LO https://github.com/adavidson510/orbit-verify/releases/download/v1.0.0/orbit-verify-linux-amd64
curl -LO https://github.com/adavidson510/orbit-verify/releases/download/v1.0.0/orbit-verify-linux-amd64.sig
# 2. Verify the signature against the published release key fingerprint
# (the fingerprint is documented in the release notes and the security page).
orbit-release-key verify orbit-verify-linux-amd64 orbit-verify-linux-amd64.sig
# 3. Confirm the published SHA-256 digest before installing.
sha256sum orbit-verify-linux-amd64
# 4. Only then install.
install -m 0755 orbit-verify-linux-amd64 /usr/local/bin/orbit-verifyPin the public key once:
# Fetch the current public key (from the /verify page or from the API)
curl -s https://orbitgrc.com/api/public-key | \
jq -r .public_key > ~/.orbit/sequencer.pubVerify a receipt:
orbit-verify check receipt.orbitproof --pubkey ~/.orbit/sequencer.pubExit code 0 means the receipt verified; non-zero means it did not, and the CLI prints the reason. The CLI does not contact ORBIT during verification; everything happens against the pinned public key on your machine.
ORBIT rotates the signing key periodically. The CLI prints the signer ID it expected and the signer ID on the receipt; if they differ, fetch the current public key and try again. See When verification fails below for the full failure-mode list.
Receipt tiers
Receipts come in three tiers, depending on how much of the action lifecycle ORBIT recorded:
- Tier 1: Authorization. ORBIT evaluated the action and issued a verdict. The action may or may not have actually executed; the receipt only proves the authorization step.
- Tier 2: Authorization + reported outcome. The agent reported back what happened (success, failure, partial). The reported outcome is included in the receipt. Self-reported.
- Tier 3: Authorization + verified outcome.ORBIT cryptographically verified the execution outcome itself, not just the agent’s report. The strongest tier.
The tier appears on the verified receipt readback and on the receipt’s metadata. Most receipts at launch are Tier 1 or Tier 2; Tier 3 requires execution-side instrumentation that ships incrementally.
Why receipts are not URLs
Receipts contain action detail: file paths your agent touched, command arguments, network endpoints. They are evidence about your work. We do not host them on public URLs because once a URL exists, it can be indexed, cached, screenshotted, leaked, or guessed.
The model is the same as a signed PDF: the file is the artifact; sharing happens by passing the file. ORBIT verifies; ORBIT does not host. This is a deliberate property of the product, not a limitation we are working around.
If you receive a “share this receipt as a link” request, the right answer is: download the .orbitproof and share that. Anyone who needs to verify can do so without your help.
When verification fails
/verify distinguishes four failure modes and names each plainly:
- Invalid file format. The file is not JSON, or is JSON but does not match the receipt schema.
- Signature mismatch. The file looks like a receipt but the signature does not match the content. The file may have been edited after ORBIT signed it, or it was not signed by ORBIT.
- Wrong signer. The signature is well-formed but it is not from a key ORBIT uses.
- Schema too new. The receipt is from a newer ORBIT schema than this verifier knows. Update orbit-verify and try again.
When verification fails, /verify and the CLI both refuseto display the receipt’s claimed content. Showing content while saying “we cannot verify this” would let a sloppy reader come away thinking they read what the receipt said. They did not; they only read whatever bytes someone put in a file. The right answer is no answer.