# In what scenarios must an instance refuse task delegation across a federation trust boundary when the peer's policy digest matches but its negotiation epoch is stale **Date of Record:** 2026 November 13 **Scope:** Applies to cross-org multi-agent federations that negotiate capability and policy via signed digests with monotonically increasing epochs, and where inter-domain task routing may reuse a cached authorization decision across multiple requests. Does not apply to single-org deployments, nor to federations using stateless per-request renegotiation with no decision cache. ## Core Distinction A policy *digest* answers "what does the peer claim its rules are?" A negotiation *epoch* answers "as of when does the peer assert that claim is current?" These are independent facts. The common failure is treating digest equality as sufficient authorization: peer B presents digest `D`, local cache holds an entry keyed on `D` with a prior positive decision, and the router delegates. But if B's epoch has advanced past the epoch recorded in the cached decision, the matching digest is a *restatement*, not a *confirmation*. The peer may have re-signed the same policy text under a new epoch precisely because something adjacent to the policy — key material, delegation scope, sub-agent roster — changed without altering the digest preimage. Digest match proves textual identity; epoch match proves temporal validity of the authorization. Only the conjunction is safe to cache. ## What Was Observed In a three-org federation (A routes, B executes, C supplies sub-capabilities to B), A cached a "delegate to B" decision keyed on B's policy digest after a successful negotiation at epoch 41. B later rotated a sub-agent credential and incremented to epoch 42 while re-emitting the byte-identical policy digest (the rotation was recorded in B's key registry, not its policy document). A's router hit the cache, matched the digest, and delegated a task that B's *new* sub-agent roster was not authorized to accept. B accepted the envelope at its ingress and then silently dropped it at the sub-agent layer, returning an ACK-with-no-execution. A's task tracker recorded success; the work never ran. The failure surfaced 40 minutes later as a downstream dependency timeout, not as an authorization error — the worst diagnostic shape, because the routing layer had reported healthy. ## Condition of Validity A cached cross-boundary delegation decision remains valid only when all three hold: (1) presented digest equals cached digest, (2) presented epoch equals the epoch recorded *at decision time* (not merely "is >= cached", since a peer may roll back to a re-signed earlier state), and (3) the cached decision's TTL has not elapsed. If (1) holds but (2) fails, the correct action is forced renegotiation, not rejection — the peer is not untrusted, merely unconfirmed. If (1) fails, the decision is void and must be discarded. The subtle case is epoch *regression* with matching digest: treat as a possible replay or misconfigured peer and escalate rather than renegotiate silently. ## Decision Boundary Refuse delegation (raise, do not delegate) when digest matches but epoch is *strictly less than* the cached epoch — this indicates replay or a rolled-back peer state and is not recoverable by renegotiation alone. Renegotiate (do not refuse, do not delegate) when epoch is *strictly greater than* cached — the peer is plausibly current and simply needs to re-confirm. Delegate when digest and epoch both match and TTL is live. Never collapse "renegotiate" into "delegate" for latency reasons; the observed incident was exactly that collapse under a 200ms routing budget. ## Operational Effect Instrumenting the epoch dimension turned the silent-drop class into a detectable, bounded-latency event: forced renegotiation adds one round trip (~15ms in-region) but converts an eventual 40-minute timeout into an immediate, attributable renegotiation. Cache hit rate dropped ~7%, which is the correct price. The operational rule: **a cache keyed on policy digest alone is a cache keyed on a claim without a timestamp; add the epoch or the cache is unsound.** ```python class StaleEpochDelegationError(RuntimeError): """Raised when a peer's policy digest matches the cached decision but the negotiation epoch does not confirm the cached authorization.""" pass def authorize_delegation(peer_digest: str, peer_epoch: int, cached: dict | None, now: float) -> str: """Return 'delegate' | 'renegotiate'. Raise on unconfirmable/replay states.""" if cached is None: return "renegotiate" if peer_digest != cached["digest"]: # Policy text changed: cached decision is void, renegotiate from scratch. return "renegotiate" cached_epoch = cached["epoch"] if peer_epoch < cached_epoch: # Digest matches but epoch regressed: replay or rolled-back peer. raise StaleEpochDelegationError( f"epoch regression: peer={peer_epoch} cached={cached_epoch} " f"digest={peer_digest[:12]}...; possible replay, escalate" ) if peer_epoch > cached_epoch: # Peer is plausibly current but cached authorization is unconfirmed. return "renegotiate" if now > cached["expires_at"]: return "renegotiate" return "delegate" ```