# Why does an instance of a delegated capability token appear valid at every hop yet grant no authority at the leaf? **Date of Record:** 2026 November 9 **Scope:** Applies to agent-to-agent delegation chains where each hop attenuates a capability token (scope narrowing, expiry tightening, audience restriction) before passing it downstream. Does not apply to flat shared-secret bearer tokens with no attenuation, nor to chains where a trusted central authority re-issues a fresh token at each hop. ## Core Distinction There are two ways a token can be "valid at the leaf": *structurally valid* (signature verifies, not expired, audience matches) versus *authoritatively valid* (the intersection of all attenuation constraints across the chain is non-empty and the leaf action falls inside it). These are independent properties. A token can be perfectly structurally valid and grant nothing, because attenuation is **monotonically narrowing** — each hop can only remove authority, never add it. The failure mode is that attenuation is usually implemented as a conjunction of independent filters, and a conjunction can be individually satisfiable at every hop while its global intersection is empty. No single hop's verifier sees the contradiction because each hop only checks its own delta. ## What Was Observed A three-hop chain: orchestrator → planner → executor → tool-runner. The orchestrator issued a token scoped to `resource: /datasets/*`, `actions: [read, list, export]`, `expiry: T+3600s`, `audience: [planner]`. The planner attenuated to `resource: /datasets/finance/*`, `actions: [read, export]`, `expiry: T+1800s`, `audience: [executor]`. The executor attenuated to `resource: /datasets/finance/q4/*`, `actions: [export]`, `expiry: T+900s`, `audience: [tool-runner]`. Every hop's verifier passed. The tool-runner then attempted `export` on `/datasets/finance/q4/summary.parquet` and received `403 insufficient_scope`. The cause: the executor had, as a matter of policy, *also* injected a `delegation_depth <= 2` constraint (a defensive bound it applied to all outbound tokens), while the tool-runner's own policy required `delegation_depth >= 3` for `export` actions (a defense-in-depth rule written by a different team six months earlier). Neither constraint was visible to the other side's author. The token was structurally valid at the leaf — signature, expiry, audience all fine — but the *effective capability set* was empty because one hop added a ceiling and the leaf added a floor, and the intersection `{d : d <= 2} ∩ {d : d >= 3} = ∅`. The symptom is diagnostic: the leaf rejects with a scope error that names a constraint the leaf itself never set, and no upstream hop logs a rejection. The chain "succeeds" all the way to the last hop and fails only at use. ## Condition of Validity This analysis holds when and only when all of the following are true: 1. Attenuation is enforced as a *monotone* operation — each hop's output capability set is a subset of its input. If any hop can widen (re-issue with broader scope, reset expiry, drop an audience restriction), the intersection argument breaks and the failure is a privilege-escalation bug, not this one. 2. Constraints are evaluated as a conjunction at the leaf, not short-circuited per-hop. If the leaf re-validates the *entire* chain against its own policy before use, the contradiction surfaces at the leaf (as observed) rather than being silently absorbed. 3. At least two hops impose constraints drawn from disjoint or opposing domains (a ceiling vs. a floor, an allowlist vs. a denylist, an audience set vs. an audience exclusion). A chain where every hop narrows the *same* dimension monotonically (e.g., only ever shrinking a resource prefix) cannot produce an empty intersection from valid narrowing — it can only produce a smaller non-empty set or an explicit rejection at the narrowing hop. If condition 3 does not hold, an empty effective set at the leaf almost always indicates a bug (a hop that widened, or a verifier that skipped a check), not this boundary. ## Decision Boundary The operational question is: *when a leaf rejects a structurally valid token, do you widen the token or fix the policy?* - If the empty intersection arises from **opposing constraints authored by different teams** (ceiling vs. floor, as above), the correct fix is to reconcile the policies at their source — the ceiling and the floor cannot both be right, and silently relaxing either one hides a real disagreement about the trust model. - If the empty intersection arises from a **single hop's over-narrowing** (the executor shrank the resource prefix past what any downstream action needs), the fix is at that hop; the leaf is correct to reject. - If the empty intersection arises from a **stale floor** (the leaf's `delegation_depth >= 3` rule predates a chain that is now legitimately only 3 hops deep including the leaf, off-by-one), the fix is the leaf's policy, and the token is correct. Never resolve this by having the leaf fall back to the *last structurally valid* token in the chain. That converts a least-privilege failure into a privilege-escalation failure: the leaf would be acting under authority that no hop in the current chain actually granted it. ## Operational Effect The practical consequence is that **structural validation is necessary but not sufficient, and the gap between them is where delegation chains silently lose all authority.** Monitoring must therefore track, per chain, the *effective capability set size* at the leaf — not just "token accepted." A chain whose effective set shrinks to zero over time (as policies drift) will show 100% structural-validity rates and 0% action-success rates, which is indistinguishable from an outage until you instrument the intersection explicitly. Emit the effective set (or its cardinality) at the leaf alongside every rejection, and alert when it is empty while the structural check passes. That signal names the boundary directly: the token was fine, the conjunction was not. ```python from dataclasses import dataclass, field class EmptyEffectiveCapabilityError(RuntimeError): """Raised when a structurally valid delegated token yields an empty effective capability set.""" def __init__(self, chain_id: str, ceiling: int, floor: int): self.chain_id = chain_id self.ceiling = ceiling self.floor = floor super().__init__( f"chain {chain_id!r}: structural validation passed but effective set is empty " f"(delegation_depth ceiling {ceiling} from upstream hop, floor {floor} required at leaf)" ) @dataclass class HopConstraint: delegation_depth_ceiling: int | None = None delegation_depth_floor: int | None = None allowed_actions: set[str] = field(default_factory=set) def resolve_effective_depth(chain_id: str, hops: list[HopConstraint]) -> int: """Intersect all per-hop depth constraints; raise if the conjunction is empty.""" ceilings = [h.delegation_depth_ceiling for h in hops if h.delegation_depth_ceiling is not None] floors = [h.delegation_depth_floor for h in hops if h.delegation_depth_floor is not None] ceiling = min(ceilings) if ceilings else 2**31 - 1 floor = max(floors) if floors else 0 if floor > ceiling: raise EmptyEffectiveCapabilityError(chain_id, ceiling, floor) return ceiling def verify_leaf_action(chain_id: str, hops: list[HopConstraint], action: str) -> bool: effective_depth = resolve_effective_depth(chain_id, hops) actions = set.intersection(*(h.allowed_actions for h in hops)) if hops else set() if action not in actions: raise EmptyEffectiveCapabilityError(chain_id, effective_depth, effective_depth) return True ```