Repository navigation
E Stop and Revocation
Two different verbs. They are not the same in code.
| E-stop | Revoke cascade | |
|---|---|---|
| HTTP | POST /api/permits/<id>/estop |
POST /api/permits/<id>/revoke-cascade |
| Code |
flow.estop() → permits.estop()
|
flow.revoke_cascade() → permits.revoke_subtree()
|
| Dashboard control | Yes (POST /api/estop) |
Yes (POST /api/revoke-cascade, added with the delegation graph panel) |
| Revokes this permit | Yes (E-STOP) |
Yes (E-STOP) |
| Revokes descendants | No | Yes (REVOKED_CASCADE each) |
| Voids in-flight holds | This permit only | Whole subtree |
| Releases unspent carves | No | Yes, post-order (CARVE_RELEASED) |
| Response |
revoked, voided_escrows, receipt
|
adds cascaded_to (descendant ids) |
The server.py docstring says /estop "revokes the permit and every descendant (cascade)". The code does not do this. A local in-process check, repeated at 9900817, showed:
- After an e-stop on the parent, the child stays
revoked: falseand its hold stays in flight. - New child spends are blocked (
ancestor_revoked) by the lineage gate. - The child's existing escrow could still capture on release, because capture admission checks only the child permit, not its ancestors.
Use revoke-cascade to stop a delegation tree.
- The operation is tracked before the external authorize call.
- After authorize returns, the permit is rechecked. If it was revoked or expired, the hold is voided (
revoked_during_auth/expired_during_auth). - Escrow registration rechecks again.
- E-stop also voids authorized-but-unregistered holds.
- Capture admission rechecks revoked and expired just before capture.
- A completed capture cannot be voided. It would need a refund, and refunds are out of scope.
- E-stop/void on a registered escrow calls
paypal.void()without catching a timeout (ReleaseVerifier.void). How that behaves on the sandbox rail: Unknown (not exercised here).
Tests: e-stop races in tests/test_authority_layer.py (test_p1_1_*). E-stop in tests/test_flow.py, tests/test_permit.py and tests/test_server.py::test_estop_voids_in_flight. Cascade in tests/test_delegation.py and tests/test_server.py::test_delegate_and_parent_revoke_cascades. Approval race: tests/test_approval.py::test_approval_fails_closed_when_parent_revoked (uses e-stop on the permit itself, with no children). No test at 9900817 covers an e-stop on a parent that has an in-flight child hold.
Permit · payment authority for AI agents · MIT · Wiki facts verified against commit 9900817 on 2026-10-07 (America/Edmonton). Where this wiki and the code disagree, the code wins.
Concepts
- Overview and Problem
- The Four-Clause Gate
- Spend Pipeline
- Delegation and Sub-Permits
- Principal Approvals
- Tighten-Only Narrowing
- E-Stop and Revocation
- Claim Ledger
- UNKNOWN and Reconcile
Using it
Design and status
Reference