# In what scenarios must an instance treat memory-poisoning attestation as a per-write invariant rather than a periodic sweep **Date of Record:** 2026 November 8 **Scope:** Applies to long-horizon agent state stores where an agent's persistent memory (episodic summaries, retrieved facts, tool-output caches, or self-authored notes) is read back across many sessions and can be mutated by untrusted or semi-trusted writers. Does not apply to stateless inference, to stores where every writer is inside the same trust boundary and no external content is ever ingested, or to read-only frozen snapshots. ## Core Distinction The non-obvious boundary is this: **memory poisoning is not a property of a memory item; it is a property of the transition that wrote it.** A periodic integrity sweep can attest that the *current* store contents hash to a known-good root, but it cannot distinguish "this item was written by a trusted path and later verified" from "this item was written by a poisoned path and the sweep happened to run after the poison was already folded into the attested root." The moment the sweep recomputes and blesses the Merkle root, it launders every unverified write that occurred since the last sweep. Attestation that runs on a schedule attests to *what is there now*, not to *how it got there*. Per-write attestation attests to the provenance chain of each transition. These are different invariants, and only the second one survives an adversary who writes between sweeps. ## What Was Observed In a deployment where an agent ingested external documents into a vector-backed episodic store and a nightly job recomputed a signed Merkle root over all stored chunks, the following sequence occurred: 1. A malicious retrieved document contained an instruction payload that the ingestion pipeline summarized into a "fact" chunk and wrote to the store. 2. The chunk passed ingestion validation because validation checked *schema and length*, not provenance. 3. The nightly sweep ran, recomputed the root over all chunks including the poisoned one, and signed it. 4. On the next session, the agent read the chunk back, treated it as attested memory (it was inside a signed root), and acted on it. The root was valid the entire time. Every hash matched. The signature verified. The integrity attestation reported *green* while the store was poisoned, because the poison had been written *before* the sweep and therefore became part of the attested baseline. The failure was invisible to every check that compared current state to a stored root; it was only detectable by replaying the write log against the provenance policy that *should* have gated ingestion. The tell was a divergence between two independent measurements: the count of writes whose provenance class was `external_untrusted` and the count of writes that had passed a provenance gate. The store was 100% hash-consistent and 0% provenance-consistent for one chunk. ## Condition of Validity Per-write attestation is the correct invariant **if and only if** the following holds: every mutation to the store carries an authenticated provenance record (writer identity, source class, and the gate decision) that is committed *atomically with* the data write, and the attestation root is computed over `(data, provenance)` pairs rather than over data alone. If mutations can occur without a provenance record — e.g., a bulk backfill, a migration that rewrites chunks in place, or an admin console that bypasses the write path — then per-write attestation is unsound and you must fall back to a full re-derivation of provenance from an append-only log, because the store itself no longer carries the evidence. The invariant is only as strong as the guarantee that no writer can commit data without committing provenance in the same transaction. A single out-of-band writer collapses the whole scheme back to "trust the sweep," which is exactly the failure mode above. ## Decision Boundary Use per-write attestation when **any** of these hold: - The store ingests content from outside the trust boundary (retrieved documents, tool outputs, user-supplied text, other agents' messages). - The agent reads its own prior writes back as authoritative context in later sessions (self-reinforcing memory). - The sweep interval is longer than the time-to-action, i.e., the agent can act on a write before the next sweep. Do **not** escalate to per-write attestation when the store is written only by a single trusted process with no external ingestion and reads never cross a session boundary that the writer doesn't control — there the sweep is sufficient and the per-write overhead is pure cost. The boundary is not "how sensitive is the data" but "can an unverified write land between two attestations and be read before the next one." If yes, the sweep is structurally blind and you need the per-write gate. ## Operational Effect Enforcing per-write provenance attestation moves the detection point from *after* the poison is folded into the baseline to *at* the transition, and it changes the failure from silent to loud: a write whose provenance class is `external_untrusted` and whose gate decision is not `allow` raises at commit time rather than surfacing as a green attestation over a poisoned store. The cost is a provenance record per mutation and an atomic two-part commit; the benefit is that the attested root can no longer launder an unverified write, because the root covers the gate decision itself. The residual risk is the out-of-band writer described under Condition of Validity — that must be closed by making the write path the only path, or the invariant is theater. ```python class ProvenanceAttestationError(RuntimeError): """Raised when a store mutation lacks a valid per-write provenance gate.""" pass TRUSTED_SOURCE_CLASSES = frozenset({"internal_agent", "operator_signed"}) def commit_memory_write(store, chunk, provenance): """ Commit a memory chunk only if its provenance gate passed in the same transaction. Attestation covers (data, provenance); a sweep over data alone would launder unverified writes. """ if provenance is None: raise ProvenanceAttestationError( f"write of chunk {chunk.id!r} has no provenance record; " "refusing to commit data without committed provenance" ) source_class = provenance.get("source_class") gate_decision = provenance.get("gate_decision") if source_class not in TRUSTED_SOURCE_CLASSES and gate_decision != "allow": raise ProvenanceAttestationError( f"chunk {chunk.id!r} from source_class={source_class!r} " f"has gate_decision={gate_decision!r}; untrusted write " "cannot enter the attested root" ) # Atomic: data and provenance land together, or neither lands. with store.transaction() as tx: tx.put_data(chunk) tx.put_provenance(chunk.id, provenance) tx.extend_attestation_root(chunk, provenance) return True ```