commerce: refund lifecycle as a flow-on-sx flow (20 tests) — Phase 5 backlog complete
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 39s

refund.sx — refund as a second flow-on-sx flow (request -> approve -> settle)
with two suspension points (approval = human/policy decision, settle =
provider). refund-begin! records :refund-requested and suspends at approval;
refund-approve! advances to settle; refund-settle! records :refunded
(idempotent) and completes; refund-reject! records :refund-rejected and cancels.
Only :refunded moves the books. Reuses order.sx flow helpers. Completes the
Phase 5 backlog. Total 278/278 across 17 suites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 13:01:16 +00:00
parent da349b169e
commit e66fbfc540
6 changed files with 198 additions and 9 deletions

View File

@@ -21,7 +21,7 @@ reconciliation — all auditable via the event log.
## Status (rolling)
`bash lib/commerce/conformance.sh`**258/258** (16 suites; + stock) — **roadmap + full Phase 5 backlog complete**
`bash lib/commerce/conformance.sh`**278/278** (17 suites; + refund) — **roadmap + full Phase 5 backlog complete**
## Ground rules
@@ -75,7 +75,7 @@ lib/commerce/api.sx ── (commerce/add) (commerce/total) (commerce/checkout)
- [x] cross-instance catalog (federated marketplace) — out-of-scope stub
- [x] tests: webhook replay, partial refund, double-charge guard
## Phase 5 — Extensions (backlog; base roadmap complete)
## Phase 5 — Extensions (backlog; base roadmap complete) — **ALL DONE (278/278)**
Thesis-aligned deepenings of the relational/composition showcase. Pick the one
that unlocks the most tests per effort each iteration.
- [x] line-level discount attribution — "which line item triggered this discount?"
@@ -87,8 +87,9 @@ that unlocks the most tests per effort each iteration.
- [x] discount-aware tax policy — `nettax.sx`: `cart-quote-net` taxes the net
(post-discount) base; `allocate-discount` spreads the basket discount across
lines by extended share with largest-remainder so per-line shares sum exactly.
- [ ] refund as a flow — refund lifecycle (request → approve → settle) as a second
flow-on-sx flow, recorded in the ledger; idempotent.
- [x] refund as a flow — `refund.sx`: refund lifecycle (request → approve →
settle) as a second flow-on-sx flow with two suspension points; idempotent
settle, reject path, ledger-recorded; reuses order.sx flow helpers.
- [x] stock-constrained reservation — `stock.sx`: `can-reserve?`/`reserve-check`
precondition (host gates order-begin! on it, keeping the flow pure);
`reservation-shortfalls` detail; `effective-available` nets out concurrent
@@ -100,6 +101,16 @@ that unlocks the most tests per effort each iteration.
agnostic; `order-settle!(ref, amount)` is the resume seam.
## Progress log
- 2026-06-07 — `refund.sx` (**Phase 5 backlog complete**): refund lifecycle as a
second flow-on-sx flow `(lambda (oid) (begin (request 'approve oid) (request
'settle oid)))` — two suspension points (approval = human/policy decision,
settle = provider). `refund-begin!` records :refund-requested and suspends at
approval; `refund-approve!` advances to settle; `refund-settle!` records
:refunded (idempotent) and completes; `refund-reject!` records :refund-rejected
and cancels the flow. Only :refunded moves the books, so requested/rejected
refunds leave recon unchanged. Reuses order.sx flow helpers. refund suite
20/20; total 278/278 (17 suites). NB: conformance now has two env-building
suites (order, refund) — each builds the ~150s flow env in its own process.
- 2026-06-07 — `stock.sx` (Phase 5 ext): stock-constrained reservation. Design
choice: reservation is a precondition the host checks BEFORE order-begin!
(validate → begin), keeping the order flow pure orchestration. `available-stock`