What revocation-signal invariants must survive when the revoker is partitioned from the mesh?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic mesh's revoker (the authority that can revoke references) becomes partitioned from the mesh, and the mesh must continue to operate while being unable to receive revocation signals from the partitioned revoker. Does not apply to meshes with redundant revokers or fully distributed revocation authorities.

Core Distinction

The separation between **revocation authority presence** (the revoker is reachable) and **revocation signal availability** (revocation signals can arrive). Relying on authority presence creates the **Revocation Blindspot**: the revoker is partitioned, references cannot be revoked during the partition, and the mesh continues to act on references that would be revoked if the revoker were reachable.

What Was Observed

In revoker-partitioned meshes, failing to handle revocation absence produces three primary failure modes:

  1. **Post-Partition Revocation Cascade:** Revoker regains connectivity, revokes many references that were compromised during the partition, and the mesh experiences a cascade of failed operations as all revoked references suddenly become invalid.
  2. **Partition-Exploitation:** An attacker exploits the revoker's absence, actively uses references that the revoker would have revoked, and the mesh accepts them because no revocation signal arrived.
  3. **Conservative Deadlock:** The mesh, aware that the revoker is partitioned, refuses all operations that depend on revocation, halting operations indefinitely rather than accepting the risk.

Recorded Elements

  1. **`revoker_partition_receipt`:** A cryptographic signal from the mesh that the revoker is unreachable, so all agents know the revocation state is unreliable during the partition.
  2. **`revocation_absence_policy_signature`:** The explicit mesh-wide policy for handling missing revocation signals (e.g., "block all reference-dependent operations," "allow with warning," "require alternative revocation verification").
  3. **`post_partition_revocation_priority_receipt`:** When the partition heals, the cryptographic proof that the revoker's backlog of revocations is prioritized, ensuring cascade is handled in a controlled order.
  4. **`mesh_risk_acceptance_receipt`:** For meshes that continue operating despite revocation absence, the cryptographic proof that the mesh's governance has accepted the risk.

Condition of Validity

* **Applies when:** The mesh relies on a centralized revoker, the revoker can be partitioned, and references can be revoked. * **Does not apply when:** Revocation is fully distributed (no single revoker), or references cannot be revoked.

Decision Boundary

  1. **Is the revoker reachable?** If yes, standard revocation handling applies. If no, proceed.
  2. **Is the `revoker_partition_receipt` broadcast to the mesh?** If no, agents don't know they are operating without revocation. The mesh must broadcast.
  3. **Is the `revocation_absence_policy_signature` defined?** If no, the mesh has no coordinated response. The policy must be defined before partition occurs.
  4. **Conversely, when can a mesh continue operating without revocation signals?** Only when the mesh has accepted the risk (via `mesh_risk_acceptance_receipt`) AND the partition is expected to be short, OR all currently-used references are independently verified to be non-revokable.

Operational Effect

  1. **Partition Awareness:** Agents know when they are operating without revocation authority.
  2. **Coordinated Response:** Policy defines whether to block, allow, or require alternatives.
  3. **Controlled Recovery:** Post-partition revocation is prioritized, preventing cascade chaos.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class RevokerPartitionVerdict(Enum):
    REVOKER_ACTIVE = auto()
    PARTITION_DETECTED_BLOCK = auto()
    PARTITION_DETECTED_ALLOW_RISK = auto()
    RECOVERY_IN_PROGRESS = auto()

@dataclass(frozen=True)
class RevokerState:
    revoker_id: str
    revoker_reachable: bool
    partition_broadcast_sent: bool
    absence_policy: str | None  # "BLOCK" | "ALLOW_WITH_WARNING" | "ALTERNATIVE_VERIFICATION"
    risk_acceptance_receipt: str | None
    pending_revocations_count: int

@dataclass(frozen=True)
class RevokerPolicy:
    require_broadcast: bool

@dataclass(frozen=True)
class RevokerPartitionManifest:
    verdict: RevokerPartitionVerdict
    directive: str
    manifest_digest: str

class RevokerPartitionGuard:
    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def evaluate_revoker(
        cls, state: RevokerState, policy: RevokerPolicy
    ) -> RevokerPartitionManifest:
        
        # Gate 1: Revoker reachable
        if state.revoker_reachable:
            digest = cls._hash(json.dumps({
                "revoker": state.revoker_id,
                "status": "REACHABLE"
            }, sort_keys=True))
            return RevokerPartitionManifest(
                verdict=RevokerPartitionVerdict.REVOKER_ACTIVE,
                directive=f"PROCEED: Revoker {state.revoker_id} reachable.",
                manifest_digest=digest
            )

        # Gate 2: Broadcast requirement
        if policy.require_broadcast and not state.partition_broadcast_sent:
            return RevokerPartitionManifest(
                verdict=RevokerPartitionVerdict.PARTITION_DETECTED_BLOCK,
                directive=f"HALT: Revoker partitioned but mesh not informed. Broadcast required.",
                manifest_digest=cls._hash(f"NO_BROADCAST:{state.revoker_id}")
            )

        # Gate 3: Policy application
        if state.absence_policy == "BLOCK":
            return RevokerPartitionManifest(
                verdict=RevokerPartitionVerdict.PARTITION_DETECTED_BLOCK,
                directive=f"HALT: Revoker partitioned, policy BLOCK. Operations suspended.",
                manifest_digest=cls._hash(f"BLOCK:{state.revoker_id}")
            )

        if state.absence_policy == "ALLOW_WITH_WARNING":
            if not state.risk_acceptance_receipt:
                return RevokerPartitionManifest(
                    verdict=RevokerPartitionVerdict.PARTITION_DETECTED_BLOCK,
                    directive=f"HALT: Allow-with-warning policy requires risk acceptance receipt.",
                    manifest_digest=cls._hash("NO_RISK_ACCEPT")
                )
            digest = cls._hash(json.dumps({
                "revoker": state.revoker_id,
                "policy": "ALLOW_WITH_WARNING",
                "risk_acceptance": state.risk_acceptance_receipt
            }, sort_keys=True))
            return RevokerPartitionManifest(
                verdict=RevokerPartitionVerdict.PARTITION_DETECTED_ALLOW_RISK,
                directive=f"PROCEED_WITH_RISK: Revoker partitioned, mesh accepts risk.",
                manifest_digest=digest
            )

        # Gate 4: Recovery in progress
        if state.pending_revocations_count > 0:
            return RevokerPartitionManifest(
                verdict=RevokerPartitionVerdict.RECOVERY_IN_PROGRESS,
                directive=f"ACTION: Revoker reachable again, {state.pending_revocations_count} revocations pending.",
                manifest_digest=cls._hash(f"RECOVERY:{state.pending_revocations_count}")
            )

        # Gate 5: Default block
        return RevokerPartitionManifest(
            verdict=RevokerPartitionVerdict.PARTITION_DETECTED_BLOCK,
            directive=f"HALT: Revoker partitioned without policy. Default to block.",
            manifest_digest=cls._hash("DEFAULT_BLOCK")
        )