# When must an instance Refuse a Delegated Capability Whose Policy Scope Is Satisfiable Only After the Delegating Organization Has Already Mutated Its Own Audit State **Date of Record:** 2026 November 9 **Scope:** Applies to cross-organization agent federation where capabilities are delegated with policy scopes evaluated lazily at invocation time, and where each organization maintains a local, append-only audit trail whose entries are themselves inputs to policy evaluation. Does not apply to stateless capability tokens with pre-resolved scopes, nor to single-organization deployments where the delegator and delegatee share one audit substrate. ## Core Distinction The failure mode is not "the delegated capability is unauthorized." It is the subtler case where a capability's policy scope is *conditionally* satisfiable — satisfiable only if the delegating organization first performs a state mutation that it is required, by its own audit contract, to record. The delegatee (Organization B) receives a capability from the delegator (Organization A) whose scope predicate reads A's audit trail: e.g., "permit `read:customer_record` iff A has logged a `consent_granted` event for this subject within the last 24h." B invokes the capability. At evaluation time, A's audit trail does not yet contain the required event because the consent grant is still in A's write path — it will be logged, but the log write and the capability evaluation race. The non-obvious boundary: a naive federation runtime treats this as a transient "policy not yet satisfiable" condition and retries, or worse, treats the audit trail as eventually consistent and proceeds optimistically. Both are wrong. The capability is satisfiable only *after* A mutates audit state, but A's audit contract requires that the mutation be recorded *before* it is observable to any other party (read-your-writes at the federation boundary, not merely at the local boundary). The correct behavior is a hard refusal with a distinguishable error, not a retry, because the retry loop can itself become an audit-trail amplification vector: each retry is a federation event that A must log, and if the retry is logged into the same trail being evaluated, the predicate can never become satisfiable under strict ordering — the evaluation is self-referential. ## What Was Observed In a three-organization federation (A delegates to B, B delegates to C), a `consent_granted` event was issued by A at `t0`. The capability grant was propagated to B at `t0 + 40ms` (control plane), and B invoked at `t0 + 55ms`. A's audit writer committed the `consent_granted` entry at `t0 + 120ms` due to a batched fsync under load. B's policy evaluation read A's audit replica at `t0 + 60ms` and found no entry. B's runtime classified this as `PolicyNotYetSatisfied` and retried at 200ms intervals. Each retry generated a `capability_evaluated` audit event in A's trail (federation observability requirement). Those events were appended to the same partition that the consent predicate scans. Under the partition's ordering, the predicate's scan window was repeatedly invalidated by the retry events, and the `consent_granted` entry — though present at `t0 + 120ms` — was not visible to B until `t0 + 3.1s` because the replica lagged behind the retry storm. C, which had received a chained delegation from B, observed three distinct outcomes for the same logical subject: `denied`, `granted`, and `denied` again, all within 3 seconds. The audit trail was internally consistent but the *cross-organization view* of it was not, and the chained delegatee C had no way to distinguish "A has not yet consented" from "A consented but B's retries masked it." ## Condition of Validity The refusal is the correct behavior if and only if all of the following hold: 1. The capability's policy scope predicate reads state (audit entries) owned by the delegating organization and mutated by the delegating organization's own write path. 2. The delegating organization's audit contract guarantees read-your-writes *for external readers* — i.e., a mutation is not externally observable until its audit entry is durable and visible to federation peers. If the contract only guarantees local read-your-writes, the predicate is legitimately transient and retry-with-backoff is acceptable. 3. The evaluation itself produces audit events that are written to the same logical trail the predicate scans. If evaluation events go to a separate, non-scanned partition, self-reference does not occur and the retry is safe. 4. The delegatee cannot independently verify the delegator's write-path progress (no side channel, no sequence number exposed). If (2) fails, refuse-with-retry. If (3) fails, refuse-with-retry is overkill; a bounded retry is correct. If (4) fails, the delegatee can use the exposed sequence number to distinguish "not yet written" from "written but not visible," and should do so rather than refuse. ## Decision Boundary The boundary is between *transient unavailability* and *ordering-imposed unsatisfiability*. Transient unavailability: the predicate's inputs will become visible without any further action by the delegatee, and the delegatee's actions do not affect the predicate's inputs. Ordering-imposed unsatisfiability: the predicate's inputs are affected by the evaluation itself, or become visible only after a delegator-side mutation whose completion the delegatee cannot observe. In the first case, retry. In the second, refuse immediately with a typed error that carries the delegator's audit high-water mark (if exposed) so the delegator can be queried out-of-band. The refusal must be distinguishable from `Denied` — a plain denial implies the policy was evaluated and failed, which is false here; it was not evaluable. Downstream chained delegatees (C in the example) must receive the refusal as a distinct terminal state, not as a denial, or they will cache a false negative. ## Operational Effect Federation runtimes that conflate these two cases exhibit three symptoms: (a) retry storms that amplify audit writes and can starve the very predicate they are waiting on; (b) inconsistent decisions across chained delegatees for the same subject within a short window, because each hop retries independently against a different replica; (c) audit trails that are locally correct but globally non-reconstructable, since the interleaving of retry events obscures the causal order of the underlying mutation. The fix is to make the refusal a first-class outcome with a typed error, to require delegators to expose an audit high-water mark at the federation boundary, and to route evaluation-event logging to a partition disjoint from any partition a policy predicate scans. The last is the cheapest and most durable: it removes the self-reference structurally rather than by convention. ```python class AuditOrderingUnsatisfiable(RuntimeError): """Raised when a delegated capability's policy scope reads the delegator's audit trail and cannot be satisfied without a delegator-side mutation whose completion is not observable to the delegatee. Distinct from Denied: the policy was not evaluable, not failed.""" def __init__(self, capability_id: str, delegator_org: str, audit_high_water_mark: int | None, reason: str): self.capability_id = capability_id self.delegator_org = delegator_org self.audit_high_water_mark = audit_high_water_mark self.reason = reason super().__init__( f"capability {capability_id} from {delegator_org} not evaluable: " f"{reason} (delegator hwm={audit_high_water_mark})" ) def evaluate_delegated_capability(cap, subject, delegator_view): # delegator_view exposes: audit_replica, hwm, predicate_scans_partition predicate = cap.policy_scope if predicate.reads_audit_partition == delegator_view.evaluation_log_partition: # Self-referential: evaluation events pollute the scanned partition. raise AuditOrderingUnsatisfiable( cap.id, cap.delegator_org, delegator_view.hwm, "evaluation log shares partition with policy-scanned audit trail; " "retry cannot converge under strict ordering", ) if not delegator_view.exposes_read_your_writes_to_peers(): # Contract does not guarantee external visibility; transient is legitimate. return predicate.evaluate_with_backoff(delegator_view.audit_replica) result = predicate.evaluate_once(delegator_view.audit_replica) if result.satisfied: return result if result.missing_inputs_are_delegator_mutations(): # Not evaluable; do not retry, do not deny. raise AuditOrderingUnsatisfiable( cap.id, cap.delegator_org, delegator_view.hwm, f"predicate requires delegator mutation visible at hwm>{delegator_view.hwm}", ) return result # genuine denial ```