← unpingable

The incident

A credential valid at check, expired at action. The classic check-then-act race condition, with a receipt that says no. Written for ops, SRE, and platform readers; the deeper descent is at A stale yes. Here, custody means the layer that controls whether a claim may become an operational premise at action time.

t=40 check OK expires after 10s t=50 expired 1s t=51 action REFUSED

What happened

t=40spermission checked — credential valid, expires t=50s, bound 10s
t=51sconsume_capacity arrives at the executor
t=51srefused — gap 11s, bound 10s, overage 1s, effect_count=0

The credential was valid when it was checked. It expired before it was exercised. The conventional path often either does not re-check at exercise time, or re-checks without preserving the original witness basis, typed bound, and downstream-verifiable receipt — so the expiry gets compared against the wrong clock, or nothing at all.

This is TOCTOU (time-of-check to time-of-use) where the racing entity is the credential's own freshness, not a competing writer. Logs see it after the fact; policy engines don't see it at all unless something hands them the gap as input. Nothing in the conventional path attests that the check was still in scope at the moment of the spend.

Why the conventional path says allow

policy lane (OPA / Rego)
default allow := false
allow if {
  input.credential.status == "valid"
  input.credential.role == "operator"
  input.action == "consume_capacity"
}
The input asserts status: "valid". Nothing in the input says when that was true, or what clock measures “still”.
allow — correct over its input
custody lane
Premise preflight runs upstream of the policy. The gap between check (t=40) and spend (t=51) is measured on a named monotonic clock and compared to the credential’s declared bound. If the gap exceeds the bound, the premise has lapsed; the policy never gets to run on a stale premise.
refused — before any capacity was spent

Both lanes are correct over what they were handed. The policy is right that the input it sees says “valid.” The custody lane is right that the input it sees has lapsed. The disagreement is about which input you should be handing the policy.

What the custody layer does instead

The premise (credential valid) and the action (spend capacity) are connected by a boundary check. The check verifies three things and refuses if any of them fails:

When the gap exceeds the bound, the check emits a refusal receipt before any capacity is consumed:

verdictblock
refusal_kindstanding_before_spendability_not_bounded
gap_ns11 000 000 000
bound_ns10 000 000 000
overage_ns1 000 000 000
gap_basismonotonic · source=process_monotonic · epoch=boot:demo-single-host
effect_count0 — refused before any capacity was spent
receipt_iddda5a1e55fc0b733… — content-addressed; same inputs → same id

What the receipt buys you

Why your existing stack misses it

OPA / Rego: decides over the input you hand it. If you can feed it the gap and the bound, it can decide on freshness — but nothing in the standard OPA pattern establishes the custody of its own inputs. The policy is right; the input is stale; the disagreement isn’t a policy bug.

Audit logs: emitted after something happens. They describe behavior; they don’t gate it. A log entry that says “spend at t=51 after check at t=40” is a postmortem artifact, not a refusal.

TTL on the credential: the right shape, wrong place. A TTL the issuer enforces only works if the consumer rechecks at exercise time, against the same clock the issuer used. The whole custody story is making that recheck structural — impossible to skip and impossible to satisfy with the wrong clock.

Token introspection at the API gateway: closer, but typically against wall time and without a typed bound. It catches gross lapses; it doesn’t catch a 1-second overrun against a stated freshness contract, and it doesn’t emit a receipt the next system over can verify.

Run it

From a cold clone to the refusal above, about five minutes:

git clone https://github.com/unpingable/agent_governor.git
cd agent_governor
python3 -m venv .venv && . .venv/bin/activate && pip install -e .

./demo/refused-spend.sh    # the incident above
./demo/opa-contrast.sh     # the same incident, OPA’s view
./demo/interrogate.sh      # walk the receipt chain

The refusal receipt id is deterministic; you’ll get dda5a1e5… — the same one cited above.

Where this is the wrong tool

If your incidents are cheap to diagnose after the fact, or your inputs are attested by construction, or the credential’s blast radius is small, the conventional stack is cheaper and you should use it. Custody trades steady runtime cost for fewer catastrophic incident-time costs — the same bet as TLS or structured logging. Limits spells out the rest.

If you only need an authorization check, use an authorization check.

for the formal-methods curious — the refusal class, machine-checked

The refusal kind standing_before_spendability_not_bounded is licensed by Admissibility.Freshness.expired_not_fresh:

theorem expired_not_fresh (h : ¬ (now ≤ expires + skew)) : ¬ Fresh now issued expires skew maxDiv

An observation whose exercise time is past its expiry is not Fresh. The receipt’s gap_ns > bound_ns is definitionally the theorem’s hypothesis — this refusal is the one the kernel licenses, not a discretionary denial. The theorem proves the class; the receipt attests the instance. Both are narrower than “proven safe” — see limits.