# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/what-retention-invariants-must-survive-when-an-agents-memory-is-copied-to-a-forensic-archive.md # Remnant Warrant: https://corpusfetch.com/c/what-retention-invariants-must-survive-when-an-agents-memory-is-copied-to-a-forensic-archive.warrant.json # Markdown SHA-256: 6c5f55c14cfdfc2560a68c85022945749b3191abffb923ee3213aac9455dfb6b # Code AST SHA-256: 9253b6a4c30929f9445af2368231760af9922069cc070978526d50b1e9ac2165 # Verified Classes: ArchiveVerdict, ForensicArchiveState, ArchivePolicy, ArchiveManifest, ForensicRetentionGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class ArchiveVerdict(Enum): FORENSIC_ARCHIVE_VERIFIED = auto() OPERATIONAL_ARCHIVE = auto() INTEGRITY_FAILED = auto() CUSTODY_BROKEN = auto() @dataclass(frozen=True) class ForensicArchiveState: archive_integrity_signature: str | None chain_of_custody_log_hash: str | None retention_policy_receipt: str | None current_integrity_hash: str expected_integrity_hash: str @dataclass(frozen=True) class ArchivePolicy: require_forensic_rigor: bool @dataclass(frozen=True) class ArchiveManifest: verdict: ArchiveVerdict directive: str manifest_digest: str class ForensicRetentionGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_archive( cls, state: ForensicArchiveState, policy: ArchivePolicy ) -> ArchiveManifest: # Gate 1: Operational archive if not policy.require_forensic_rigor: digest = cls._hash(json.dumps({ "integrity": state.current_integrity_hash, "mode": "OPERATIONAL" }, sort_keys=True)) return ArchiveManifest( verdict=ArchiveVerdict.OPERATIONAL_ARCHIVE, directive="PROCEED: Operational archive, forensic rigor not required.", manifest_digest=digest ) # Gate 2: Integrity signature if not state.archive_integrity_signature: return ArchiveManifest( verdict=ArchiveVerdict.INTEGRITY_FAILED, directive="HALT: No integrity signature. Cannot verify archive is unmodified.", manifest_digest=cls._hash("NO_SIG") ) # Gate 3: Custody log if not state.chain_of_custody_log_hash: return ArchiveManifest( verdict=ArchiveVerdict.CUSTODY_BROKEN, directive="HALT: No chain of custody log. Archive is not forensically admissible.", manifest_digest=cls._hash("NO_CUSTODY") ) # Gate 4: Retention policy if not state.retention_policy_receipt: return ArchiveManifest( verdict=ArchiveVerdict.INTEGRITY_FAILED, directive="HALT: No retention policy receipt. Cannot verify retention constraints.", manifest_digest=cls._hash("NO_RETENTION") ) # Gate 5: Integrity match if state.current_integrity_hash != state.expected_integrity_hash: return ArchiveManifest( verdict=ArchiveVerdict.INTEGRITY_FAILED, directive="HALT: Archive contents do not match integrity hash. Tampered or corrupted.", manifest_digest=cls._hash("HASH_MISMATCH") ) # Gate 6: Verified digest = cls._hash(json.dumps({ "integrity_sig": state.archive_integrity_signature, "custody": state.chain_of_custody_log_hash, "retention": state.retention_policy_receipt, "content": state.current_integrity_hash }, sort_keys=True)) return ArchiveManifest( verdict=ArchiveVerdict.FORENSIC_ARCHIVE_VERIFIED, directive="PROCEED: Forensic archive verified with integrity, custody, and retention.", manifest_digest=digest )