# What structural signals indicate a delegated AAIF credential is unrecoverable after revocation propagation **Date of Record:** 2026 November 10 **Scope:** Applies to AAIF delegated credential chains (depth ≥ 2) where a root principal revokes a credential and propagation is asynchronous across issuer-attestation caches. Does not apply to single-hop credentials issued directly by a root authority with synchronous revocation semantics, nor to credentials governed by short-lived (<60s) TTLs where expiry dominates revocation. ## Core Distinction The non-obvious boundary is between a credential that is *revoked but still honored* (a propagation lag, recoverable by waiting) and a credential that is *structurally orphaned* — revoked at the root, but whose delegated children can no longer be re-anchored because the intermediate issuer's signing key material was rotated during the propagation window. In the first case, time heals the chain. In the second, the child credentials are cryptographically valid but permanently unattributable: no live authority can either confirm or deny their lineage, so every downstream verifier must treat them as untrusted forever. The structural signal is not the revocation event itself. It is the *conjunction* of (a) an intermediate key rotation timestamp falling inside the revocation propagation window, and (b) at least one surviving descendant credential whose `issuer_chain` references the retired intermediate key. Neither condition alone is fatal. Together they mean the lineage is severed from any authority that could re-validate it. ## What Was Observed During a routine root revocation of a compromised depth-3 delegation (`root → org-issuer → team-issuer → workload`), the org-issuer rotated its signing key at T+40s to contain the incident. The revocation CRL reached the team-issuer's cache at T+90s, but the team-issuer had already re-signed two workload credentials under the *new* key at T+55s, referencing an `issuer_chain` that still pointed at the retired intermediate. The resulting state: workload credentials verified cleanly against the new team-issuer key, but the chain walk to the root failed because the retired org-issuer key was no longer published in the trust store. Verifiers reported `CHAIN_UNRESOLVABLE`, which downstream retry logic interpreted as transient. The credentials were retried for 72 hours before an operator noticed the retry storm. They were never recoverable — the intermediate key that could bridge the chain had been destroyed, and re-issuing would have required the original team-issuer identity, which had itself been revoked. The tell was in the verifier logs: `CHAIN_UNRESOLVABLE` was accompanied by `ISSUER_KEY_STATUS=RETIRED` on every attempt, never `REVOKED` or `UNKNOWN`. That distinction — RETIRED (permanent) versus UNKNOWN (transient) — is the structural signal that separates recoverable lag from permanent orphaning. ## Condition of Validity This failure mode is only reachable when three conditions hold simultaneously: 1. Revocation propagation is asynchronous with a window longer than the intermediate key rotation cadence. 2. An intermediate issuer rotates its signing key *during* that window, before the revocation reaches it. 3. Descendant credentials are re-issued under the new key while still referencing the retired intermediate in their `issuer_chain`. If any one condition is absent, the chain either propagates cleanly (no rotation) or fails atomically (rotation before re-issue). The dangerous interval is precisely the overlap of propagation lag and rotation cadence. ## Decision Boundary On observing `CHAIN_UNRESOLVABLE` with `ISSUER_KEY_STATUS=RETIRED` on a descendant credential, an agent must **not** retry. Retry is only correct when the status is `UNKNOWN` (cache miss, transient) or `REVOKED` (propagation in flight, will settle). `RETIRED` is terminal: the key is gone by policy, not by delay, and no amount of waiting will restore the bridge. The correct action is to quarantine the descendant credential, emit a `DELEGATION_ORPHANED` event to the identity audit log, and require re-issuance from a live ancestor. If no live ancestor exists (all revoked), the workload must be treated as unauthenticated and halted — not degraded, not retried. ## Operational Effect Treating `RETIRED` as equivalent to `UNKNOWN` converts a bounded incident into an unbounded retry storm that masks the true state of the credential graph. The operational rule: **the status of the key, not the status of the chain walk, determines recoverability.** A chain walk failure with a retired intermediate is an orphan; a chain walk failure with an unknown intermediate is a lag. The two require opposite responses, and the only reliable discriminator is the issuer key's lifecycle status at verification time. ```python class DelegationOrphanedError(RuntimeError): """Raised when a delegated credential's lineage is permanently severed.""" pass class TransientChainError(RuntimeError): """Raised when a chain walk failure is recoverable by waiting.""" pass def classify_chain_failure(issuer_key_status: str, retry_count: int) -> None: if issuer_key_status == "RETIRED": # Terminal: the bridging key is gone by policy. Do not retry. raise DelegationOrphanedError( f"Delegation orphaned after {retry_count} retries: " f"intermediate issuer key RETIRED, lineage unrecoverable. " f"Quarantine descendant and require re-issuance from live ancestor." ) if issuer_key_status in ("UNKNOWN", "REVOKED"): # Recoverable: propagation lag or cache miss. Bounded retry is correct. raise TransientChainError( f"Chain walk failed with issuer_key_status={issuer_key_status}; " f"retry permitted (attempt {retry_count})." ) raise ValueError(f"unhandled issuer_key_status: {issuer_key_status}") ```