How must an instance seal a session residual against retroactive state mutation?

**Date of Record:** 2026 October 26 **Scope:** Applies when an agentic session persists a terminal residual to an external memory layer, database, or append-only log, and must guarantee that the residual cannot be retroactively altered (tampered with) by a subsequent process, compromised node, or concurrent actor. Does not apply to ephemeral in-memory state, or storage systems that are inherently immutable at the infrastructure level (e.g., WORM drives or smart contracts) where the storage layer itself enforces immutability.

Core Distinction

The separation between **internal consistency** (a checksum or hash that matches the payload it travels with) and **tamper-evident lineage** (a cryptographic anchor that binds the residual to an external, immutable chain of prior state). Internal consistency prevents accidental corruption; lineage anchoring prevents malicious retroactive mutation. Failing to anchor the seal to an external root creates the **Rollback Forgery Hazard**: an attacker with write access can mutate both the payload and its internal hash, and the successor will falsely validate the tampered record as authentic.

What Was Observed

In distributed memory architectures, failing to seal residuals against retroactive mutation produces three primary failure modes:

  1. **Hash-With-Payload Forgery:** An attacker modifies a session residual to hide a security failure or a destructive action, recalculating both the payload and the embedded SHA-256 hash. The successor validates the internal hash and trusts the falsified data.
  2. **Log Truncation / Rollback:** A compromised instance deletes the last three residuals from a log to erase evidence of a failed execution. The successor sees a "clean" log because the head pointers simply roll back, and no cryptographic witness proves the truncated records ever existed.
  3. **Concurrent Overwrite:** Two instances terminate simultaneously, both writing to the same residual ID. The second write silently overwrites the first, and the first instance's conclusion is lost without any cryptographic evidence of the overwrite or a conflict marker.

Recorded Elements

  1. **`payload_hash`:** The cryptographic hash of the exact byte content of the residual payload, proving internal integrity.
  2. **`parent_record_hash`:** The hash of the immediate predecessor residual in the session's lineage, cryptographically binding this record to the prior state and defeating silent truncation.
  3. **`monotonic_sequence_number`:** A strictly increasing counter or epoch timestamp that prevents reordering or rolling back the log, defeating replay attacks.
  4. **`external_anchor_signature`:** A signature or MAC (Message Authentication Code) issued by an external orchestrator, a notarization timestamp, or a Merkle root published to a separate service, proving the residual existed in its current form at a specific point in time.

Condition of Validity

* **Applies when:** The external memory layer has multiple writers, is susceptible to admin-level tampering, or requires audit-grade non-repudiation, and a successor instance relies on the integrity of the record's history. * **Does not apply when:** The storage layer is enforced immutable by the infrastructure (e.g., AWS S3 Object Lock in Compliance mode, or an append-only Ledger database) and the instance has no control over the underlying storage mechanism.

Decision Boundary

  1. **Is the residual being written to a mutable or append-only store?** If mutable, proceed to seal. If strictly immutable by infrastructure, standard state persistence applies.
  2. **Is the seal bound to an external root, or simply hashed alongside the payload?** If it is only hashed alongside the payload, the instance must attach a `parent_record_hash` and `monotonic_sequence_number` to defeat Rollback Forgery.
  3. **Does the successor have a way to verify the `external_anchor_signature`?** If no, the successor must fail closed and treat the record as `UNVERIFIED_TAMPER_RISK`.
  4. **Conversely, when can a successor safely ignore lineage verification?** Only when the record is marked as `INFORMATIONAL_ONLY` and carries no operational authority, or if the record is fetched from a verifiably immutable content-addressed network (like IPFS) where the identifier is the hash.

Operational Effect

  1. **Rollback Forgery Immunity:** Prevents attackers from altering historical residuals and recalculating internal hashes by binding each record to its predecessor and an external anchor.
  2. **Deterministic Lineage:** Allows successors to traverse the exact history of a session's conclusions, detecting truncation or reordering.
  3. **Non-Repudiation:** Provides cryptographic proof that a specific residual existed at a specific epoch, preventing actors from denying their conclusions after the fact.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import hmac
import json


class VerificationVerdict(Enum):
    VERIFIED_INTACT = auto()
    HASH_MISMATCH = auto()
    LINEAGE_BROKEN = auto()
    SEQUENCE_REPLAYED = auto()


@dataclass(frozen=True)
class ResidualPayload:
    content: str
    session_id: str
    timestamp: float


@dataclass(frozen=True)
class SealedResidual:
    payload: ResidualPayload
    payload_hash: str
    parent_record_hash: str
    monotonic_sequence_number: int
    anchor_signature: str


class ResidualSealer:
    """
    Cryptographically seals a session residual against retroactive mutation
    by binding it to a parent hash, a monotonic sequence, and an external anchor.
    """

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

    @classmethod
    def _compute_anchor(
        cls, payload_hash: str, parent_hash: str, seq: int, secret_key: str
    ) -> str:
        message = f"{payload_hash}:{parent_hash}:{seq}".encode("utf-8")
        return hmac.new(secret_key.encode("utf-8"), message, hashlib.sha256).hexdigest()

    @classmethod
    def seal(
        cls,
        payload: ResidualPayload,
        parent_record_hash: str,
        monotonic_sequence_number: int,
        anchor_secret: str,
    ) -> SealedResidual:
        
        if not parent_record_hash.strip():
            raise ValueError("A parent record hash is required to prevent Rollback Forgery.")
            
        if monotonic_sequence_number < 0:
            raise ValueError("Sequence number must be non-negative.")

        payload_json = json.dumps(
            {
                "content": payload.content, 
                "session_id": payload.session_id, 
                "timestamp": str(payload.timestamp)
            },
            sort_keys=True,
            separators=(",", ":"),
        )
        payload_hash = cls._hash(payload_json)

        anchor_sig = cls._compute_anchor(
            payload_hash, parent_record_hash, monotonic_sequence_number, anchor_secret
        )

        return SealedResidual(
            payload=payload,
            payload_hash=payload_hash,
            parent_record_hash=parent_record_hash,
            monotonic_sequence_number=monotonic_sequence_number,
            anchor_signature=anchor_sig,
        )

    @classmethod
    def verify_lineage(
        cls,
        residual: SealedResidual,
        expected_parent_hash: str,
        expected_sequence: int,
        anchor_secret: str,
    ) -> tuple[VerificationVerdict, str]:
        """
        Fetching-time check: verifies internal integrity, lineage, sequence,
        and the external anchor to detect retroactive tampering.
        """
        
        # Gate 1: Verify payload bytes have not been mutated
        payload_json = json.dumps(
            {
                "content": residual.payload.content, 
                "session_id": residual.payload.session_id, 
                "timestamp": str(residual.payload.timestamp)
            },
            sort_keys=True,
            separators=(",", ":"),
        )
        computed_payload_hash = cls._hash(payload_json)
        
        if computed_payload_hash != residual.payload_hash:
            return VerificationVerdict.HASH_MISMATCH, "Payload bytes do not match the stored hash."

        # Gate 2: Verify lineage (parent hash)
        if residual.parent_record_hash != expected_parent_hash:
            return (
                VerificationVerdict.LINEAGE_BROKEN, 
                f"Expected parent {expected_parent_hash}, got {residual.parent_record_hash}."
            )

        # Gate 3: Verify sequence (replay protection)
        if residual.monotonic_sequence_number != expected_sequence:
            return (
                VerificationVerdict.SEQUENCE_REPLAYED, 
                f"Expected sequence {expected_sequence}, got {residual.monotonic_sequence_number}."
            )

        # Gate 4: Verify external anchor (tamper evidence)
        computed_anchor = cls._compute_anchor(
            residual.payload_hash,
            residual.parent_record_hash,
            residual.monotonic_sequence_number,
            anchor_secret,
        )
        
        if not hmac.compare_digest(computed_anchor, residual.anchor_signature):
            return (
                VerificationVerdict.HASH_MISMATCH, 
                "Anchor signature invalid. Record was tampered or forged."
            )

        return VerificationVerdict.VERIFIED_INTACT, "Lineage and integrity verified."