Five gates. One receipt.
Pick the action your auditor will ask about first. Every gate below ships with the same Decision Brief and the same signed receipt.
What every receipt proves. Ed25519 signature over: action payload hash · agent ID · named approver · APPROVE or DENY · timestamp · Decision Brief. Verifiable by anyone at /r/{id}. Tampering withholds the approver. Denials are signed too.
Gate 01 · Money out
Which human approved this refund, before the money moved?
Today: Under the threshold, nobody. Over it, a Slack thread that can't be found by the time the auditor asks.
Choke point: Stripe refunds.create / transfers.create / payouts.create; AP release in NetSuite or Bill.com. The call fires only on a signed APPROVE.
You are authorizing a $4,800.00 refund on ch_3Nq8… from agent cx-refunds.
stripe · requested by agent cx-refunds (session 3f9a) · 2m ago · payload sha256 7c1e…9b02 · expires in 14m
Auto-approve limit is $500. Approving moves 9.6× that without a second check.
Approving refunds without a fraud review.
Decision Brief
Risk: elevatedFunds leave the balance and the refund is irreversible; the agent is acting on a customer-supplied claim it cannot verify.
- 1Charge ch_3Nq8… exists and the amount matches ticket #48213.
- 2The refund reason matches the ticket text, not the customer's message.
- 3No prior refund exists on this charge.
Signing as [email protected]
This approval is permanent and auditable
Receipt & controls
What gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgWhat gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgLedger ⋈ receipts: 100% of in-scope transactions carry a valid receipt. Zero orphans.
Pilot this gateGate 02 · Agent code → prod
Was the SHA that shipped the SHA a human reviewed?
Today: A PR approve click that doesn't survive a force-push. Nobody at deploy time.
Choke point: Merge to main or the deploy job: GitHub environment reviewer step, merge-queue check, or MCP Guard on the git/deploy tool. Deploy runs only against a signed SHA.
You are authorizing a production deploy of acme/api at commit a891b24.
github · requested by agent codex-bot via PR #512 · 41m ago · commit a891b24 · checks 14/14 passed · expires in 21h
Approving signs a SHA no human has reviewed.
Approving signs a production change with no stated intent.
Decision Brief
Risk: elevatedProduction deploy capability + agent-authored diff + a review that isn't bound to the final SHA.
- 1The diff at a891b24 matches the PR description.
- 2Migration files, if any, are reversible.
- 3Checks are green on this SHA, not a prior one.
Signing as [email protected]
This approval is permanent and auditable
Receipt & controls
What gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgWhat gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlg100% of in-scope prod deploys reference a signed SHA. Zero deployed-SHA ≠ signed-SHA events.
Pilot this gateGate 03 · Prod infra mutations
Who approved this change, and can you prove nothing went out-of-band?
Today: Plan pasted in a PR or Slack, SRE thumbs-up. IAM via console: nobody. Feature flags: nobody.
Choke point: terraform apply (Atlantis/Spacelift approval hook) · IAM policy write · DNS record write · flag-flip API · migration runner. Gated on plan hash or policy diff.
You are authorizing terraform apply on prod-us-east-1 (plan 3d9f…) from agent sre-agent.
spacelift · requested by agent sre-agent (run 8812) · 5m ago · plan sha256 3d9f…e1a4 · 2 to add, 1 to change, 1 to destroy · expires in 30m
Approving deletes a production resource.
Approving grants the agent broader access than the task needs.
Decision Brief
Risk: elevatedIrreversible destruction and privilege widening in one plan; the agent cannot assess blast radius.
- 1The destroy is intended: ticket or incident reference present.
- 2The IAM diff is the minimum scope for the task.
- 3The plan hash matches what CI rendered, not a re-plan.
Signing as [email protected]
This approval is permanent and auditable
Receipt & controls
What gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgWhat gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgCloudTrail/drift ⋈ receipts: 100% of in-scope changes match the applied plan hash. Zero out-of-band.
Pilot this gateGate 04 · PII/PHI export
Who approved this export, for what purpose, and where's the minimum-necessary determination?
Today: An email ticket at best. The agent's database credentials don't ask.
Choke point: Export endpoint or bulk query: warehouse unload, EHR release-of-information API, presigned S3 URL generation. Gated on record scope + fields + recipient + purpose.
You are authorizing an export of 12,400 patient records (7 fields) to vendor-analytics from agent ops-reporter.
warehouse · requested by agent ops-reporter (job 2201) · 8m ago · query sha256 a07c…44d1 · recipient vendor-analytics · expires in 1h
Approving exports direct identifiers, not a de-identified set.
Approving sends PHI to a party without a signed agreement.
Decision Brief
Risk: elevatedDirect identifiers leaving the boundary to a third party; the agent has not established minimum-necessary.
- 1The purpose on this brief matches an approved use.
- 2The field list is the minimum for that purpose.
- 3The recipient has a signed BAA or DPA on file.
Signing as [email protected]
This approval is permanent and auditable
Receipt & controls
What gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgWhat gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgExport log ⋈ receipts: 100% carry approver + purpose. Who approved export X answered in minutes.
Pilot this gateGate 05 · Identity changes
Who approved this account change, and was it someone other than whoever asked for it?
Today: Tier-2 via Slack escalation. Often nobody: the agent holds an admin key.
Choke point: Password/MFA reset, email change, ownership transfer, role grant, KYC override: PATCH /users/:id, Okta/Entra admin API, internal admin tool.
You are authorizing an MFA reset for [email protected], requested by agent support-agent.
okta · requested by agent support-agent (ticket #9931) · 1m ago · target m.alvarez · payload sha256 51b0…c7d3 · expires in 10m
Approving resets MFA at a third party's request.
Approving repeats a change that was already granted or denied today.
Decision Brief
Risk: elevatedAccount-takeover surface; the agent is acting on unverified identity claims from a support conversation.
- 1Out-of-band identity check completed: callback to the number on file.
- 2You are not the requester.
- 3No open fraud flag on the account.
Signing as [email protected]
This approval is permanent and auditable
Receipt & controls
What gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgWhat gets signed
receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlgIdP audit log ⋈ receipts: 100% of privileged changes have a receipt. Approver ≠ requester on 100%.
Pilot this gateNot one of these five?
Every gate is the same wrapper at a different choke point.