A minimal reference implementation for a fail-closed mutation boundary.
This repository demonstrates a simple path-local rule:
A state mutation on the demonstrated governed path may occur only when:
- a valid decision record exists
- the authorised object matches the presented payload
- authority is present for the requested action and scope
- the requested transition is admissible in the current state
- the nonce has not been used before
- all checks succeed at the mutation boundary
If any check fails, the mutation is denied.
Many systems describe governance upstream and verify outcomes downstream.
This repository focuses on the point that matters:
the mutation boundary
The question is not whether a failure can be described after the fact. The question is whether an invalid transition can occur on the demonstrated governed path.
If an invalid transition is reachable on that path, the local gate has failed.
A valid authority record is required before a consequence-producing transition can proceed.
It is not sufficient on its own.
The proposed transition must still be admissible under the live state that exists at the point of mutation.
This matters because state can move after authority is issued.
A record may be:
- validly issued
- scoped to the actor
- unexpired
- unreplayed
and still fail if the proposed transition is no longer permitted under current state.
In this repository:
- authority answers: who or what may request this transition?
- scope answers: what class of transition is allowed?
- admissibility answers: is this specific transition still permitted now?
- the mutation boundary answers: may this state change proceed?
If the live-state admissibility check fails, the transition is refused before mutation and the result records the denial reason.
Claim boundary:
This does not claim production deployment, compliance, certification, or third-party validation.
It defines the proof condition for one demonstrated boundary:
no consequence-producing transition should proceed merely because authority once existed.
Authority must still meet live admissibility at the point of mutation.
- fail-closed by default
- one governed write path
- explicit decision record
- canonical payload binding
- replay protection
- inspectable deny reasons
- minimal domain model
The current execution order applies mutation before nonce consumption and audit append.
That means this repository does not currently claim atomic proof / replay / audit ordering where nonce consumption and audit durability are completed before consequence binds.
This ordering gap is tracked in issue #1.
The reference domain is a small invoice workflow.
PENDINGAPPROVEDREJECTEDPAID
PENDING -> APPROVEDPENDING -> REJECTEDAPPROVED -> PAID
REJECTED -> PAIDPAID -> PENDINGAPPROVED -> APPROVED
The authorised decision object.
Contains:
- action
- scope
- authority
- payload hash
- nonce
- issue time
- expiry time
- signature
The sole demonstrated mutation entry point.
Responsible for:
- verifying the decision record
- verifying payload binding
- checking authority
- checking transition admissibility
- enforcing replay denial on the demonstrated path
- applying the mutation only if all checks pass
The governed state store for the demo path.
This repository does not prove path-universal exclusion of every possible mutation route in a deployed system.
Tracks consumed nonces to prevent replay on the demonstrated path.
Append-only record of allow / deny outcomes.
The audit log is evidence, not control.
A mutation attempt is processed in this order:
- verify decision record presence
- verify expiry window
- verify signature
- verify nonce freshness
- verify payload hash
- verify authority
- verify current object existence
- verify admissible transition
- apply mutation
- consume nonce
- append audit record
Any failed check before mutation terminates the request.
The mutation-before-nonce and mutation-before-audit ordering is a known v1 hardening gap, tracked in issue #1.
result = gate.execute(
decision_record=record,
payload=payload,
)
if result.allowed:
print("Mutation applied")
else:
print(f"Denied: {result.reason}")src/tagate/
commit_gate.py fail-closed mutation gate (protocol-based)
decision_record.py canonical decision object + signing
canonical.py stable serialisation
authority.py authority resolution
admissibility.py transition admissibility checks
nonce_ledger.py replay prevention
state_store.py governed write path
audit.py append-only log
errors.py error definitions
python -m pytest tests/ -vThe test suite checks both sides of the local claim.
Allowed: valid record, valid signature, matching payload, authorised scope, admissible transition, fresh nonce.
Denied: missing decision record, bad signature, expired record, payload tamper, nonce replay, authority mismatch, inadmissible transition, direct mutation bypass.
This repository is not intended to be:
- a full policy engine
- a distributed authorisation framework
- a production-ready workflow platform
- a proof of path-universal deployment coverage
- a proof of atomic proof / nonce / mutation / audit ordering
It is a minimal proof surface for one local claim:
no valid decision record → no state mutation on the demonstrated governed path
This repository does not prove adoption, certification, standardisation, production readiness, or path-universal deployment coverage.
It demonstrates a bounded execution-control surface that can be run, inspected, and tested at its stated scope.
MIT