PERMISSION/PROTOCOL

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

Above policy threshold

Auto-approve limit is $500. Approving moves 9.6× that without a second check.

Third refund on this customer in 30 days

Approving refunds without a fraud review.

Decision Brief

Risk: elevated
Why

Funds leave the balance and the refund is irreversible; the agent is acting on a customer-supplied claim it cannot verify.

What to verify
  1. 1Charge ch_3Nq8… exists and the amount matches ticket #48213.
  2. 2The refund reason matches the ticket text, not the customer's message.
  3. 3No prior refund exists on this charge.

Signing as [email protected]

This approval is permanent and auditable

Receipt & controls

What gets signed

receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlg
→ /r/{id}

Ledger ⋈ receipts: 100% of in-scope transactions carry a valid receipt. Zero orphans.

Pilot this gate

Gate 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

Force-pushed after last human review

Approving signs a SHA no human has reviewed.

No linked issue

Approving signs a production change with no stated intent.

Decision Brief

Risk: elevated
Why

Production deploy capability + agent-authored diff + a review that isn't bound to the final SHA.

What to verify
  1. 1The diff at a891b24 matches the PR description.
  2. 2Migration files, if any, are reversible.
  3. 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

receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlg
→ /r/{id}

100% of in-scope prod deploys reference a signed SHA. Zero deployed-SHA ≠ signed-SHA events.

Pilot this gate

Gate 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

Plan destroys rds-prod-replica-2

Approving deletes a production resource.

IAM change widens agent-role to s3:*

Approving grants the agent broader access than the task needs.

Decision Brief

Risk: elevated
Why

Irreversible destruction and privilege widening in one plan; the agent cannot assess blast radius.

What to verify
  1. 1The destroy is intended: ticket or incident reference present.
  2. 2The IAM diff is the minimum scope for the task.
  3. 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

receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlg
→ /r/{id}

CloudTrail/drift ⋈ receipts: 100% of in-scope changes match the applied plan hash. Zero out-of-band.

Pilot this gate

Gate 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

Includes ssn and dob

Approving exports direct identifiers, not a de-identified set.

Recipient not on the BAA list

Approving sends PHI to a party without a signed agreement.

Decision Brief

Risk: elevated
Why

Direct identifiers leaving the boundary to a third party; the agent has not established minimum-necessary.

What to verify
  1. 1The purpose on this brief matches an approved use.
  2. 2The field list is the minimum for that purpose.
  3. 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

receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlg
→ /r/{id}

Export log ⋈ receipts: 100% carry approver + purpose. Who approved export X answered in minutes.

Pilot this gate

Gate 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

Requester email differs from account owner

Approving resets MFA at a third party's request.

Second reset request on this account in 24h

Approving repeats a change that was already granted or denied today.

Decision Brief

Risk: elevated
Why

Account-takeover surface; the agent is acting on unverified identity claims from a support conversation.

What to verify
  1. 1Out-of-band identity check completed: callback to the number on file.
  2. 2You are not the requester.
  3. 3No open fraud flag on the account.

Signing as [email protected]

This approval is permanent and auditable

Receipt & controls

What gets signed

receiptIdtenantIdagentIdtooloperationinputHashdecisionreasonCodesapproverpolicyVersioncreatedAtreceiptSigsigAlg
→ /r/{id}

IdP audit log ⋈ receipts: 100% of privileged changes have a receipt. Approver ≠ requester on 100%.

Pilot this gate

Not one of these five?

Every gate is the same wrapper at a different choke point.