IPX replay: byte-offset checkpoint does not fingerprint the spool file (silent evidence corruption) #182

Closed
opened 2026-09-05 04:34:15 +00:00 by mara · 1 comment
Collaborator

Reviewed at commit 3b4e2da (filed against the IPX replay introduced in 6f40a44, which advances #26).

Problem
replay-ipx-http-spool (source/hackmode-core/capture-replay.lisp, lines ~157-227) resumes strictly from the stored byte offset of fetch-latest-capture-checkpoint (op, capture-session, source-id triple). The checkpoint payload stores only :offset, :last-record-id, :framing-version (execution-graph.lisp ~line 208). Nothing ties the offset to the actual spool file content.

Repro

  1. Replay a spool to offset N (checkpoint persisted).
  2. Delete/recreate the spool file, or point replay at a different spool file for the same source-id (e.g. restored-from-backup or re-exported spool).
  3. Second replay starts at byte N of unrelated content: frames decode into bogus exchanges or partial JSON gets quarantined, and the checkpoint advances over valid data.

No error is raised; evidence integrity is silently broken.

Suggested fix
Persist a fingerprint in the checkpoint payload (spool path plus file size, or a rolling content hash of the consumed prefix). On replay, refuse (or require an explicit re-baseline override) when the current file's size is smaller than the recorded offset or the fingerprint mismatches. Mirror the fingerprint in ipx-frame-provenance so exchanges remain attributable to a specific spool generation.

Reviewed at commit 3b4e2da (filed against the IPX replay introduced in 6f40a44, which advances #26). **Problem** `replay-ipx-http-spool` (`source/hackmode-core/capture-replay.lisp`, lines ~157-227) resumes strictly from the stored byte offset of `fetch-latest-capture-checkpoint` (op, capture-session, source-id triple). The checkpoint payload stores only `:offset`, `:last-record-id`, `:framing-version` (`execution-graph.lisp` ~line 208). Nothing ties the offset to the actual spool file content. **Repro** 1. Replay a spool to offset N (checkpoint persisted). 2. Delete/recreate the spool file, or point replay at a different spool file for the same `source-id` (e.g. restored-from-backup or re-exported spool). 3. Second replay starts at byte N of unrelated content: frames decode into bogus exchanges or partial JSON gets quarantined, and the checkpoint advances over valid data. No error is raised; evidence integrity is silently broken. **Suggested fix** Persist a fingerprint in the checkpoint payload (spool path plus file size, or a rolling content hash of the consumed prefix). On replay, refuse (or require an explicit re-baseline override) when the current file's size is smaller than the recorded offset or the fingerprint mismatches. Mirror the fingerprint in `ipx-frame-provenance` so exchanges remain attributable to a specific spool generation.
mara closed this issue 2026-09-08 01:34:45 +00:00
Author
Collaborator

Fixed by PR #199, merged as commit 420b788 on master. Checkpoints now persist a SHA-256 fingerprint and size of the consumed spool prefix [0,offset); replay-ipx-http-spool verifies both before resuming and raises the new exported ipx-spool-fingerprint-mismatch condition on a replaced or shortened spool instead of silently decoding unrelated bytes into canonical evidence. RED-first regression tests cover both rejection paths; exact-head CI green (core/hygiene/boundary) at bf37e91.

Fixed by PR #199, merged as commit 420b788 on master. Checkpoints now persist a SHA-256 fingerprint and size of the consumed spool prefix [0,offset); replay-ipx-http-spool verifies both before resuming and raises the new exported ipx-spool-fingerprint-mismatch condition on a replaced or shortened spool instead of silently decoding unrelated bytes into canonical evidence. RED-first regression tests cover both rejection paths; exact-head CI green (core/hygiene/boundary) at bf37e91.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/hackmode#182
No description provided.