feat(api): record and reload item deliveries over HTTP - #197
Conversation
A purchaser with an Active in-process session can POST that one published item version was shown and GET the server-ordered ledger to resume. Exact Idempotency-Key replay that matches delivery_ref returns the original event. Items outside the bound release, inactive sessions, and conflicting replay fail closed. Selection, session create, responses, and restart durability stay out of this family. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Stale comment
GET cannot resume administration, and a purchaser following this family will stall after the first accepted delivery.
The domain slice is real: first POST returns 201, exact Idempotency-Key == delivery_ref replay returns 200 without a second row, and unpublished items / paused new deliveries / conflicting replay fail closed with application/problem+json. That is not enough.
Required before this head is a landing vehicle:
- GET must return allowed_item_version_refs, release_content_digest, and session_state, or stop claiming resume.
- 201/200 and every problem detail must name the next call. Catalog the problem type URIs in OpenAPI.
- The TCP accept loop must read Content-Length bytes after the header terminator. A mid-character Content-Length must fail closed, not panic.
- Colliding seeded session_ref values must fail closed. Document capability-URL authority and the absence of tenant isolation.
- Idempotency-Key must use the same normalized_reference predicate as other public IDs.
- POST must require Content-Type application/json.
Keep this draft unmerged. The same-slice successor on cursor/bc-202765b3-6d0e-4a63-9cc8-6a638afe7692-a197 applies those fixes on top of this head. Do not open a third item-delivery HTTP family.
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Draft HTTP record/reload is the right buyer family after durable persist. Keep this slice on #197. Do not open a second item-delivery HTTP PR.
Rebase onto #224 before this can compile against current persist/reload. #224 adds ItemDeliveryError::CorruptHistory. delivery_problem in src/item_delivery_http.rs is not exhaustive for that variant, so this head will fail to build once it picks up the reload domain.
HTTP still trims Idempotency-Key. valid_idempotency_key returns the trimmed spelling, so a padded header can match an exact delivery_ref. After #224, persist/reload reject padded aliases. This transport should fail closed on a padded key instead of aliasing.
In-process only: no PostgreSQL durability (keep #224). No session create (#149). No response HTTP (#195/#221). Do not merge this Draft in parallel with #224. Do not self-approve. Independent last-push review still required after rebase.
Sent by Cursor Automation: Fix Issues
Protected-main #81 requires claim_deadline_at on processing integration_consumption rows. Recovery fixtures that omit the column fail constraint integration_consumption_claim_deadline_shape.


Why
A purchaser can start listing instruments (#165) and creating sessions (#149), but still cannot record that a published item was shown or reload that ledger to resume. That is the next buyer-facing hole after session create.
What
POSTandGET/v1/sessions/{session_ref}/item-deliveriesIdempotency-Keyreplay that matchesdelivery_refopenapi/item-deliveries.yaml)Boundary
No live
fast-mlsirmitem selection or calibration. No session create/start (keep #149). No response, scoring, or result HTTP. No PostgreSQL ledger durability (keep #186/#110 reload persist). Do not mix those onto this head.Verification
cargo test --test item_delivery_http_contractcargo test --test item_delivery_http_listener_contractcargo test --test documentation_architecture_contractNext action after this lands
Record an accepted response event over HTTP against the same Active session, still without inventing a score.