fix(response): prove restored times and close persist coverage arms - #208
fix(response): prove restored times and close persist coverage arms#208cursor[bot] wants to merge 8 commits into
Conversation
A two-item path can now reload the same answers after restart without re-checking live session activity. Gapped sequence, reused client or server identity, and blank session references fail closed. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Store accepted response_event rows with observed and received time so a two-item path reloads the same answers after process restart. Exact replay is idempotent; client, server, sequence, or session rebinding fails closed under READ COMMITTED. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
A Korean path can now reload stored observed/received time, continue with item 3 after restart, and keep those rows through recovery COPY. Misaligned event times fail as arity, not a clock error. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Recovery COPY now asserts first-write observed/received instants. Reload rejects pre-epoch stored clocks, missing relations, and repeatable-read time loads. Unit tests cover sequence overflow and operator-facing error copy so the 100% gate stays honest. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Review (exact head 65566fb)
This is the #201-line persist slice (persist_response_ledger / load_response_event_times), not a successor of #182.
classify_existing_event compares session, client, item, digest, and sequence. It does not compare stored observed_at / received_at. Time rebinding is therefore not fail-closed. Ledger load also omits clocks and uses a second query, so the two reads can diverge under READ COMMITTED.
Prefer ready #221 (7de134b) for persist/clocks: one-event persist, single-query ResponseEventReceipt clocks, time-rebinding fail-closed, gapped receipt fail-closed, and continue-from-reload scoring freeze. Do not merge this draft beside #221, #182, #201, #174, or #53.
Response HTTP stays on #195. This review is not an approval.
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Review — PR #208 65566fb SOUND (COMMENT, not approval)
Unique commits after #201 (1c707dd): 671717e, 65566fb. This is a cursor[bot] persist landing. Do not self-approve. Do not merge until exact-head required checks and independent last-push approval land.
What this head uniquely proves
- Recovery COPY now asserts first-write
observed_at/received_atunix-ms (1_700_000_000_000/1_700_000_000_250) intests/postgres_recovery_invariants.rs. load_response_event_timesfails closed on numeric session refs,REPEATABLE READ, and pre-epoch stored clocks.- Persist without the relation is a typed
Databasefailure (unmatched unique-constraint / missing-relation arm), not a fake unique-key class. - Unit tests cover
postgres_loaded_sequence(-1), millisecond overflow pastu64::MAXmillis, and Display/source for every non-Databasevariant. - Untestable
checked_addoverflow arm is gone. On 64-bit Unix everyu64ms offset fitsSystemTime; zero staysInvalidTimestamp. That keeps the 100% gate honest.
Carried persist contract is unchanged: ResponseLedger::from_persisted, migrations/0020_response_event.sql, exact replay, fail-closed rebinding, continue-after-restart scoring prefix after item 3. No HTTP /v1/sessions/{session_ref}/responses leak. No psychometric kernel leak.
Prefer this head
Prefer #208 over #201, #174, #182, and #53. Do not land those overlapping persist slices in parallel. Do not open another response_event persist PR.
Correctly out of scope
- HTTP
POST /v1/sessions/{session_ref}/responsesremains #195 - Raw response bodies
- Completed snapshot persist (#55 / #151)
- Session persist / command lock / HTTP (#219 / #149 / #161 / #154)
Non-blocking residuals (do not open a successor persist PR)
load_response_event_timesdoes not rebuild the ledger. A gapped store failsload_response_ledgerbut can still return a shorter time vector. #195 must treat ledger load as the integrity gate and compare lengths in oneREAD COMMITTEDtransaction.- Persist rejects unix-ms
0; load accepts epochTIMESTAMPTZ. The close is scoped to pre-epoch, matching TRACEABILITY. - Exact replay with different supplied times is implied by
ON CONFLICT DO NOTHINGand not separately asserted. Mechanism is sound.
Operator next action
Keep this draft until Runtime CI, coverage, and independent review are terminal-success on unchanged 65566fb9fc0711585f7b31abebe9868e950577d3. Then merge only that head. HTTP response transport stays on #195.
Sent by Cursor Automation: Fix Issues
|
Closing this draft as superseded by #221's response-event restart lane. #221 explicitly names #208 as a stale overlapping draft that must not land in parallel, carries the durable response-event/timestamp/recovery work, and additionally fails closed on time rebinding and gapped receipt history while proving continuation from the reloaded ledger to the same scoring prefix. The tips diverge from protected main rather than forming a fast-forward stack, so keeping both open would leave two landing vehicles for the same |


Why
#201 persisted in-progress
response_eventrows and reloaded the two-item Korean path, but recovery COPY did not assert first-write observed/received instants, and several persist fail-closed arms were untested. A buyer still needs those times after restore, and the 100% coverage gate must stay honest.Prefer this head over #201, #174, #182, and #53. Do not land those overlapping persist slices in parallel.
This is independent of Active PR #161/#149 (session HTTP), #154 (session command lock), #151 (completed snapshot reload), #195 (HTTP responses), and #162 (restricted linkage). Do not fold those slices into this head.
What
observed_at/received_atunix-ms pairs.load_response_event_timesfails closed on pre-epoch stored clocks, numeric session refs, andREPEATABLE READ.Databasefailure.postgres_timestamptzno longer keeps an untestablechecked_addoverflow arm; everyu64millisecond offset fits a UnixSystemTime, and the zero instant stays rejected.Carries the #201 persist/load contract:
ResponseLedger::from_persisted,migrations/0020_response_event.sql, exact replay, fail-closed rebinding, and continue-after-restart scoring prefix after item 3.Out of scope
POST /v1/sessions/{session_ref}/responses(#195)#55/#151)#161/#149/#154)Test plan
cargo test --lib postgres_response_eventcargo test --test response_ledgercargo test --test documentation_architecture_contract --test traceability_active_pr_contractcargo clippy --all-targets -- -D warningscargo test --test postgres_response_event_persistence --test postgres_response_event_error_contract --test postgres_recovery_invariants(needsTEST_DATABASE_URL)Do not merge until exact-head checks and independent last-push approval are satisfied. Do not self-approve.