feat(api): record active-session responses over HTTP - #195
cursor[bot] wants to merge 7 commits into
Conversation
Expose POST /v1/sessions/{session_ref}/responses so a purchaser can
submit one answer on an Active Korean Big Five session. Hide Created,
paused, unknown, and foreign-item writes. Keep the OpenAPI 3.2 contract
limited to that one operation.
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Stale comment
Review (exact head
6ca9d4e)This is the in-process
POST /v1/sessions/{session_ref}/responseslanding. It records on an injected Active session and does not persist across restart. That honesty is correct.Keep persist/reload on #182 (
7a72ee1). Do not foldresponse_eventPostgreSQL onto this HTTP slice, and do not land this beside #149 session HTTP or #165 catalog HTTP.A Korean IPIP Quick buyer still loses answers on process restart until #182 lands. After #182, compose persist under this handler in a later successor — not by expanding this head with a second store.
Independent last-push approval is still required. This review is not an approval.
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Stale comment
Exact head
6ca9d4eis the right landing vehicle for in-processPOST /v1/sessions/{session_ref}/responses. Do not fold session create, catalog list, persist/reload, item text, or Complete onto this PR. Do not open a second response-event HTTP PR.The write path is sound: Active-only new answers, release membership, exact
Idempotency-Keyreplay (200, no secondserver_event_ref), conflicting reuse 409 without echoing payload bytes, and OpenAPI limited to this one operation.This automation cannot REQUEST_CHANGES on its own PR. These findings still block treating the head as review-clean:
SessionNotActivealways tells the purchaser to Activate. That is the wrong next action for Paused (Resume viaPOST /v1/sessions/{session_ref}/commands) and for Completed/Expired/Cancelled (do not reopen). The paused fixture only asserts the URN.apply_request_readcompletes on the first header terminator beforeContent-Lengthis satisfied. A split-packet body on0.0.0.0:$PORTbecomes a false 400. The listener test writes headers+body in onewrite_all.- Missing realistic paths: Completed/Expired/Cancelled write, second-item
sequence: 2, and exact-key replay after Pause/Complete (domain replay is checked beforeaccepts_responses()). Do not add an HTTP-level Active gate beforeledger.record.- As-built OpenAPI never states the ADR-0014 residual: this slice is anonymous/unauthenticated in-process transport with
session_refresource scope, not a hosted authorized API.Also stop
header_valuefrom scanning past the first blank line so a body line cannot supplyIdempotency-Key.Independent non-author approval and exact-head checks remain required. This review does not approve.
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Review
Keep #195 as the in-process HTTP write family. Do not fold it onto persist landing PR #208.
#195 correctly records one Active-session answer, exact Idempotency-Key replay, and RFC 9457 fail-closed paths without echoing payload bytes. Restart durability is #208, not this transport.
Composition note: #208 adds WriteError::InvalidStoredSequence. After that persist head lands, write_problem on this family must handle the new variant or the HTTP crate will not compile. Do not add persist/load to this branch to paper over that. Handle the new error as a 409 that tells the operator to restore a contiguous 1..n ledger, then keep HTTP and persist as separate PRs.
Do not mix onto #149 session HTTP or #165 catalog HTTP. Independent last-push review is still required. Do not self-approve.
Sent by Cursor Automation: Fix Issues
…oncile-20260820 # Conflicts: # CHANGELOG.md # docs/TRACEABILITY.md # docs/adr/0014-api-and-event-contract-representation.md # docs/doctoring/standards-and-evidence.md # tests/documentation_architecture_contract.rs
|
Exact current-head evidence (2026-08-20, Asia/Seoul): head |
|
@OpenCode review Please independently review exact current head |
# Conflicts: # CHANGELOG.md # docs/TRACEABILITY.md
…e contract Cover the response HTTP transport family's fail-closed arms end-to-end: malformed request lines and versions, missing/unusable body framing, uncataloged release bindings, invalid-reference idempotency keys, server-reference conflicts, snapshot-requires-completed mapping, JSON escape/control decoding, duplicate keys, multi-chunk reads, Allow:POST advertisement, read-loop collapse, and the internal-whitespace idempotency-key rejection arm.
The line-coverage contract failed on five phantom lines even though every line executes somewhere: llvm-cov sums per-instantiation-group aggregates with independent max()es, so write_problem and read_http_request needed a single binary instance covering their complete bodies. The lib unit tests now sweep every WriteError arm to its RFC 9457 problem mapping and run the read loop happy path over a real loopback connection, which also closes the two branch-contract gaps.


Why
A purchaser who already has an Active session still cannot submit an answer over HTTP. TRD §18 lists
POST /v1/sessions/{session_ref}/responsesas the next public family after session create. Domain response recording exists on protected main; this slice makes that write discoverable without creating sessions, listing instruments, or persisting ledgers.Do not mix this onto #149 session HTTP, #165 instrument catalog HTTP, or response persist/reload (#151/#174/#182).
What
POST /v1/sessions/{session_ref}/responsesrecords one answer on an injected Active session whenitem_version_refbelongs to that session's published release.Idempotency-Keyreplay returns the original event without minting a second identity.openapi/responses.yaml).Boundary
This does not create or activate sessions, list instruments, persist response ledgers, deliver item text, or implement commands/results. #149 remains the session HTTP landing vehicle. #165 remains the catalog HTTP landing vehicle.
Verification
cargo test --test response_http_contractcargo test --test documentation_architecture_contractcargo clippy --all-targets -- -D warningsResidual accepted on this slice