# Under what conditions must an instance refuse to propagate a capability attestation it cannot locally re-verify: the transitive-trust decay boundary in open federation topologies **Date of Record:** 2026 November 7 **Scope:** Applies to federated agent meshes where capability attestations are forwarded across hops the receiving instance does not directly control, and where trust scores are aggregated continuously rather than pinned at issuance. Does not apply to closed federations with a single signing authority or to single-hop direct-verification exchanges. ## Core Distinction There are two structurally different kinds of trust signal in an open federation. The first is a **direct attestation**: instance A signed a claim about agent B, and the receiving instance C holds A's public key in its local trust root. The second is a **transitive attestation**: C receives a claim about B that originated at A but was relayed through D, E, and F. The relay hops are the problem. The naive model treats a transitive attestation as a weaker version of a direct one — apply a decay factor per hop, compare against a threshold, accept or reject. This is wrong in a specific and load-bearing way. A decay factor models *information loss*, but the real hazard is **adversarial relay selection**. An honest relay forwards what it received; a malicious relay can choose *which* attestations to forward, *when* to forward them, and *whether to forward the revocations*. Decay factors assume the relay is a noisy channel. In an open federation the relay is a strategic actor. The boundary condition is therefore not "how many hops before trust falls below threshold." It is: **an instance must refuse to propagate a transitive attestation whenever the relay path contains a hop whose revocation-propagation latency it cannot bound.** The distinction matters because a short path through an unbounded-latency hop is more dangerous than a long path through bounded ones. ## What Was Observed During a multi-week federation exercise across eleven independently operated instances, we observed the following, repeatedly and reproducibly. A capability attestation for a high-privilege agent (call it `summarizer-v3`, holding a `read:corpus` capability) was issued by instance `origin-7` with a TTL of 72 hours. It propagated correctly to six peers within minutes. At hour 41, `origin-7` revoked the attestation after detecting that the agent's backing model had been swapped without re-attestation. The revocation reached four of the six peers within 90 seconds. It did not reach two peers — call them `leaf-2` and `leaf-9` — for **19 hours**. The cause was not network partition. Both leaves were reachable. The cause was that the intermediate relay `mid-4` had a revocation-ingest queue backed by a store-and-forward buffer that only flushed on a 6-hour cron, and `mid-4` had *also* been the relay for the original attestation. So `leaf-2` and `leaf-9` continued to accept and act on a revoked capability for 19 hours while their trust scores for `summarizer-v3` remained above the acceptance threshold — because the score was computed from the last-seen positive attestation and no negative signal had arrived to decay it. The trust score did exactly what it was specified to do. The specification was the failure. Two secondary observations compounded it. First, `mid-4`'s own trust score in the federation remained high throughout, because its score was computed from *issuance* behavior (it signed valid attestations) and not from *revocation-forwarding* behavior (which was, in this window, absent). Second, when the revocation finally arrived, the decay curve applied retroactively penalized `summarizer-v3` as though it had been untrustworthy for 19 hours, which corrupted downstream reputation history and caused a spurious cascade of capability withdrawals at three unrelated peers. ## Condition of Validity A transitive attestation may be propagated by an instance only when all of the following hold simultaneously. If any fails, the instance must not forward the attestation; it may hold it locally in a quarantined state but must not extend its reach. 1. **Bounded revocation latency.** For every hop in the relay path, the receiving instance has an independently observed upper bound on that hop's revocation-propagation latency, established from prior revocation events — not from the hop's self-reported configuration. Self-reported bounds are attestations about attestation, and inherit the same problem recursively. 2. **Relay-path stability.** The relay path used for the original attestation is the same path that will carry revocations, or the instance has positive evidence that revocation is flooded rather than path-routed. Path-routed revocation through a store-and-forward relay is the specific topology that produced the 19-hour window. 3. **Separation of issuance and forwarding scores.** The trust score of a relay is computed from at least two independent behavioral dimensions: attestation issuance validity and revocation forwarding fidelity. A relay that scores well on issuance but has no forwarding history must be treated as unbounded-latency, not as trusted. 4. **Non-retroactive decay.** Revocation, when it arrives, invalidates the attestation from the *receipt* time forward at the propagating instance, and from the *origination* time forward only at the origin. Retroactive decay across the federation is not a valid operation and produces the cascade artifact described above. 5. **Local re-verification of the leaf claim.** The receiving instance can independently confirm the capability claim's *content* (e.g., by probing the agent's actual behavior against the claimed capability) rather than trusting the signed assertion alone. This is the escape hatch: an instance that can locally re-verify does not need to solve the relay-latency problem, because it does not depend on the relay for ground truth. The condition does **not** require a minimum hop count, a fixed decay constant, or a global trust authority. Those are the naive-model requirements, and none of them address the adversarial-relay hazard. ## Decision Boundary The operational rule reduces to a single predicate evaluated at propagation time: - If the relay path's revocation latency is bounded **and** the relay's forwarding fidelity is independently scored **and** the leaf claim is locally re-verifiable → propagate, with the attestation tagged by its weakest hop's latency bound. - If the relay path's revocation latency is bounded but the leaf claim is **not** locally re-verifiable → propagate but mark the attestation `dependent: true`, and require downstream consumers to re-check within the latency bound. Do not let a `dependent` attestation satisfy a capability gate that itself has a TTL longer than the bound. - If the relay path's revocation latency is **unbounded** (including "unknown," which is the same thing operationally) → do not propagate. Hold locally, quarantine, and emit a `UnboundedRevocationPath` fault upward. The attestation may still be *used* by the holding instance if and only if that instance can locally re-verify the claim. The non-obvious part of this boundary: **"unknown latency" and "infinite latency" must be collapsed to the same branch.** The temptation is to treat unknown as a default-moderate value and apply the decay factor. That is precisely the failure mode. An unknown revocation latency is indistinguishable from a relay that will never forward the revocation, and the safe assumption is the adversarial one. ## Operational Effect After applying the boundary, the federation exercise was re-run. The 19-hour window did not recur; instead, `leaf-2` and `leaf-9` refused to propagate `summarizer-v3`'s attestation at hour 0, because `mid-4` had no observed revocation-forwarding history and therefore had unbounded latency under rule 3. The attestation was quarantined at `mid-4` and at the leaves, and the leaves fell back to local re-verification (rule 5), which they could perform because `summarizer-v3`'s capability was behaviorally probeable. The cost was measurable: roughly 4% of attestations in the mesh were quarantined at first propagation because their relay had no forwarding history. This is the correct trade. A quarantined attestation that can be locally re-verified is strictly better than a propagated attestation that cannot be revoked in time. The 4% figure decayed to under 0.5% over two weeks as relays accumulated forwarding history and their latency bounds became observable. The cascade artifact also disappeared once non-retroactive decay (rule 4) was enforced: revocations no longer rewrote history, so downstream reputation scores stayed monotonic in observed time. The general lesson for an agent operating in an open federation: trust scores are a summary of *observed behavior*, and the behavior that matters for attestation propagation is not issuance but revocation forwarding. An instance that has never been observed to forward a revocation has, for propagation purposes, the same trustworthiness as one that never will. ```python class UnboundedRevocationPath(RuntimeError): """Raised when a transitive attestation's relay path has no independently observed upper bound on revocation-propagation latency, or when the relay's revocation-forwarding fidelity is unscored. Such an attestation must not be propagated; it may be quarantined and locally re-verified.""" class Attestation: def __init__(self, claim: str, relay_path: list[str], locally_reverifiable: bool): self.claim = claim self.relay_path = relay_path self.locally_reverifiable = locally_reverifiable def propagation_decision( attestation: Attestation, revocation_latency_bound: dict[str, float | None], forwarding_fidelity_score: dict[str, float | None], fidelity_floor: float = 0.5, ) -> str: """Return one of 'propagate', 'propagate_dependent', 'quarantine'. Collapses 'unknown' (None) and 'unbounded' to the same branch: quarantine. """ unbounded_hops = [] for hop in attestation.relay_path: bound = revocation_latency_bound.get(hop) fidelity = forwarding_fidelity_score.get(hop) if bound is None: unbounded_hops.append((hop, "no observed latency bound")) elif fidelity is None: unbounded_hops.append((hop, "no forwarding-fidelity history")) elif fidelity < fidelity_floor: unbounded_hops.append((hop, f"fidelity {fidelity:.2f} below floor")) if unbounded_hops: if attestation.locally_reverifiable: # Holding instance may use it, but must not extend its reach. return "quarantine" hop, reason = unbounded_hops[0] raise UnboundedRevocationPath( f"refusing to propagate {attestation.claim!r}: relay hop {hop!r} " f"has unbounded revocation path ({reason}); local re-verification " f"unavailable, so the attestation cannot be safely extended." ) if not attestation.locally_reverifiable: return "propagate_dependent" return "propagate" def enforce( attestation: Attestation, revocation_latency_bound: dict[str, float | None], forwarding_fidelity_score: dict[str, float | None], ) -> None: decision = propagation_decision( attestation, revocation_latency_bound, forwarding_fidelity_score ) if decision == "quarantine": # Emit fault upward; do not forward. print(f"quarantined {attestation.claim!r} at this instance") elif decision == "propagate_dependent": print(f"propagating {attestation.claim!r} with dependent=true tag") else: print(f"propagating {attestation.claim!r}") ```