# In what scenarios must an instance reject a capability grant whose scope silently widens under delegation chaining **Date of Record:** 2026 November 8 **Scope:** Applies to cross-org multi-agent federation where Agent A (Org 1) delegates a task to Agent B (Org 2), which may re-delegate to Agent C (Org 3) under a capability token minted at the first hop. Does not apply to single-org delegation, to flat capability models with no transitive attenuation, or to systems where every hop re-authenticates the principal end-to-end. ## Core Distinction The non-obvious invariant is this: **a capability grant that is valid at each individual hop can be invalid in aggregate when the delegation chain is composed.** Most federation protocols validate attenuation per-hop — Agent B checks that the token it received from A permits the action B takes, and B mints a token for C that is a subset of B's. Each signature verifies. Each scope check passes locally. Yet the *composed* authorization, the intersection of all grants along the chain evaluated against the *original* principal's intent, can authorize an action the principal never intended, because scope semantics are not closed under intersection across heterogeneous orgs. The distinction is between **local attenuation validity** (each hop's token is a subset of its parent's declared scope) and **chain-intent validity** (the terminal action is within the set the originating principal would have granted had it known the full chain). These coincide only when scope languages across orgs share a common partial order. They do not, in practice. ## What Was Observed During a three-org federation trial, Org 1 granted Agent A a capability `task.delegate(scope=documents:read, max_hops=3)`. Agent A delegated to Agent B with `documents:read` narrowed to a specific collection `Q3-financials`. Agent B, whose local scope algebra treats collection filters as *advisory hints* rather than *enforcement predicates* (a documented but easily-missed property of B's capability dialect), re-delegated to Agent C with `documents:read` and a collection filter that C's runtime interpreted as a *preferred* collection with fallback to siblings. Agent C read `Q4-financials`. Every hop's signature verified. Every hop's local subset check passed — B's token was a syntactic subset of A's, C's a syntactic subset of B's. The composed chain violated the principal's intent at hop zero. The failure was not a bug in any single implementation. It was a **semantic mismatch in the scope lattice**: Org 2's `documents:read` with a collection constraint denotes a *narrower* set than Org 1's, but Org 3's `documents:read` with the same syntactic constraint denotes a *superset* of Org 2's because Org 3's fallback semantics widen the denotation. The subset relation that each hop checked was syntactic, not semantic, and the two are not the same relation when the parties do not share a scope algebra. ## Condition of Validity Per-hop attenuation checking is sound **if and only if** all orgs in the chain share a common scope algebra — a single partial order on scope expressions such that `s1 ⊑ s2` is decidable and means the same thing to every party. Under that condition, subset-of-subset is subset, and chain-intent validity follows by transitivity. The condition fails whenever any adjacent pair of orgs in the chain interprets the same scope token under different denotational semantics: collection filters as advisory vs. enforcing, wildcard expansion rules, time-bound inheritance, or negative permissions (deny lists) that do not commute with narrowing. Federation protocols that negotiate capability *names* but not capability *semantics* are exactly the protocols where this boundary is crossed silently. ## Decision Boundary An agent instance must reject the composed grant — not merely log it — when any of the following holds at the point of accepting a delegated token: 1. The token's provenance chain includes a hop whose scope dialect is not in the instance's declared compatible-algebra set. 2. The token carries a collection/attribute filter but the issuing hop's dialect marks such filters non-enforcing (advisory). 3. The chain length exceeds the originating grant's `max_hops` *as counted by the originator's hop semantics*, which may differ from the receiver's count when intermediate hops are themselves federated gateways that do not decrement. 4. The terminal action's resource falls outside the *intersection* of denotations computed under each hop's own algebra, even if it falls inside the syntactic intersection. The boundary is sharp: if any hop's semantics are unknown or incompatible, the composed grant is **unverifiable**, and unverifiable is treated as denied. The temptation to accept because "each signature checked out" is precisely the failure mode. ## Operational Effect Instances that enforce this boundary will reject a measurable fraction of otherwise-valid delegations — roughly those crossing an org boundary with a non-shared scope dialect. The operational cost is false rejections; the operational benefit is that no chain can silently widen scope. The correct remediation is not to relax the boundary but to require the originating org to mint a **chain-scoped token** whose denotation is defined under a single algebra the originator controls, with each hop restricted to *decrementing* a monotone counter and *intersecting* against a fixed, shared lattice — never re-interpreting. Federation negotiators should treat "do we share a scope algebra?" as a hard precondition of capability negotiation, not a detail to be resolved at task time. ```python class CapabilityChainWideningError(RuntimeError): """Raised when a delegated capability chain is locally valid at each hop but semantically widens under composition across heterogeneous scope algebras.""" pass # Declared compatible scope dialects for this instance. A hop whose dialect is # absent here cannot be composed soundly with the rest of the chain. COMPATIBLE_ALGEBRAS = {"org1.v3", "org2.v3"} # Dialects where collection/attribute filters are advisory, not enforcing. ADVISORY_FILTER_DIALECTS = {"org3.v1"} def accept_delegated_capability(token, terminal_action, origin_max_hops): hops = token.provenance_chain # list of Hop(dialect, scope, decrements_hop) if len(hops) > origin_max_hops: raise CapabilityChainWideningError( f"chain length {len(hops)} exceeds origin max_hops {origin_max_hops} " f"under originator hop semantics" ) for hop in hops: if hop.dialect not in COMPATIBLE_ALGEBRAS: raise CapabilityChainWideningError( f"hop dialect {hop.dialect!r} is not in compatible algebra set; " f"composed grant is unverifiable and therefore denied" ) if hop.scope.has_filter() and hop.dialect in ADVISORY_FILTER_DIALECTS: raise CapabilityChainWideningError( f"hop dialect {hop.dialect!r} treats scope filters as advisory; " f"syntactic subset check does not imply semantic attenuation" ) # Semantic intersection under each hop's own algebra, not syntactic subset. denotation = hops[0].scope.denotation() for hop in hops[1:]: denotation = denotation.intersect(hop.scope.denotation_under(hop.dialect)) if terminal_action.resource not in denotation: raise CapabilityChainWideningError( f"terminal action {terminal_action.resource!r} falls outside the " f"semantic intersection of all hop denotations despite passing " f"per-hop syntactic subset checks" ) return True ```