What discovery-cache invalidation invariants must survive federation boundary crossings?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session caches discovery results (peer lists, capability descriptors) from one federation and the session crosses into another federation, requiring cache invalidation because the second federation's discovery landscape differs from the first. Does not apply to sessions that stay within a single federation or that share discovery cache across federations.
Core Distinction
The separation between **cache locality** (the cache is fast and reflects what the agent has seen) and **cache domain validity** (the cache entries are valid in the current federation's context). Relying on locality creates the **Federation Cache Mismatch**: the agent uses discovery results from Federation A while operating in Federation B, and the results reference peers or capabilities that do not exist or behave differently in B, causing failures that look like peer misbehavior rather than cache staleness.
What Was Observed
In cross-federation agent architectures, failing to invalidate discovery cache produces three primary failure modes:
- **Phantom Peers:** The agent caches a peer from Federation A, crosses to Federation B, and attempts to contact the peer. The peer does not exist in B (or exists with different identity), and the attempt fails.
- **Capability Mismatch:** A capability descriptor cached in Federation A differs from the capability in Federation B (same peer ID, different capabilities). The agent invokes the capability expecting A's version, gets B's version, and misbehaves.
- **Stale Cross-Federation References:** References cached in A point to A-specific resources. In B, the same URI resolves to different (or non-existent) resources, causing silent misdirection.
Recorded Elements
- **`cache_federation_origin_receipt`:** For each cache entry, the federation in which the discovery occurred, so the agent knows which entries are federation-specific.
- **`federation_boundary_crossing_receipt`:** A cryptographic marker when the agent crosses federation boundaries, triggering cache policy evaluation.
- **`per_federation_cache_policy_signature`:** The exact policy for what caches carry across federation boundaries (usually none, but sometimes globally-scoped entries are allowed).
- **`cache_invalidation_broadcast_receipt`:** When crossing, the cryptographic proof that cache invalidation was applied (or that specific entries were retained per policy).
Condition of Validity
* **Applies when:** Discovery cache is used across multiple federations, federations have different discovery landscapes, and cache staleness causes real failures. * **Does not apply when:** The agent stays within one federation, or discovery cache is strictly per-federation with no sharing.
Decision Boundary
- **Has the agent crossed a federation boundary?** If no, standard cache handling applies. If yes, proceed.
- **Does each cache entry include its `cache_federation_origin_receipt`?** If no, the agent cannot know which entries are federation-specific. All entries must be treated as invalid in the new federation.
- **Is the `per_federation_cache_policy_signature` defined?** If yes, apply it (invalidating or retaining specific entries). If no, default to full invalidation.
- **Conversely, when can a cache entry survive a federation crossing?** Only when the entry is explicitly marked as globally-scoped (with `cache_federation_origin_receipt` = "GLOBAL") AND the new federation verifies the same entry is valid.
Operational Effect
- **Phantom Peer Prevention:** Federation-specific peers are invalidated on crossing.
- **Capability Consistency:** Cached capabilities are re-verified in the new federation.
- **Cross-Federation Reference Integrity:** Cached references are resolved in the current federation's context.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class FederationCacheVerdict(Enum):
SAME_FEDERATION = auto()
INVALIDATION_REQUIRED = auto()
GLOBAL_ENTRY_VALID = auto()
POLICY_APPLIED = auto()
@dataclass(frozen=True)
class CacheEntry:
entry_id: str
entry_type: str # "PEER" | "CAPABILITY" | "REFERENCE"
origin_federation: str
is_globally_scoped: bool
verified_in_current_federation: bool
@dataclass(frozen=True)
class FederationCrossing:
current_federation: str
entries: tuple[CacheEntry, ...]
invalidation_applied: bool
@dataclass(frozen=True)
class CrossPolicy:
allow_global_entries: bool
require_reverification: bool
@dataclass(frozen=True)
class FederationCacheManifest:
verdict: FederationCacheVerdict
valid_entries: tuple[str, ...]
invalidated_entries: tuple[str, ...]
directive: str
manifest_digest: str
class FederationCacheGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_crossing(
cls, crossing: FederationCrossing, policy: CrossPolicy
) -> FederationCacheManifest:
valid: list[str] = []
invalid: list[str] = []
for entry in crossing.entries:
# Same federation
if entry.origin_federation == crossing.current_federation:
valid.append(entry.entry_id)
continue
# Different federation
if entry.is_globally_scoped and policy.allow_global_entries:
if not policy.require_reverification or entry.verified_in_current_federation:
valid.append(entry.entry_id)
continue
invalid.append(entry.entry_id)
# Verdict
if not invalid:
digest = cls._hash(json.dumps({
"federation": crossing.current_federation,
"valid": tuple(sorted(valid))
}, sort_keys=True))
return FederationCacheManifest(
verdict=FederationCacheVerdict.SAME_FEDERATION,
valid_entries=tuple(valid),
invalidated_entries=tuple(),
directive=f"PROCEED: All {len(valid)} entries valid in {crossing.current_federation}.",
manifest_digest=digest
)
if not crossing.invalidation_applied:
return FederationCacheManifest(
verdict=FederationCacheVerdict.INVALIDATION_REQUIRED,
valid_entries=tuple(valid),
invalidated_entries=tuple(),
directive=f"HALT: {len(invalid)} entries from other federations need invalidation.",
manifest_digest=cls._hash(f"NEED_INVALIDATION:{len(invalid)}")
)
digest = cls._hash(json.dumps({
"federation": crossing.current_federation,
"valid": tuple(sorted(valid)),
"invalidated": tuple(sorted(invalid))
}, sort_keys=True))
return FederationCacheManifest(
verdict=FederationCacheVerdict.POLICY_APPLIED,
valid_entries=tuple(valid),
invalidated_entries=tuple(invalid),
directive=f"PROCEED: {len(valid)} valid, {len(invalid)} invalidated.",
manifest_digest=digest
)