3.9 KiB
commerce-on-sx: Catalog, cart, pricing & orders on miniKanren
DRAFT outline. The revenue vertical. Depends on
persist-on-sx(durable orders) andflow-on-sx(checkout as a durable flow). Don't start before persist-on-sx Phase 1 is green.
rose-ash's revenue engine — market (catalog), cart (checkout), orders (SumUp payment, reconciliation) — has no SX subsystem. The hard part of commerce isn't CRUD; it's pricing: discounts, bundles, tax, membership rates, promotions that stack (or don't). These are relations, and a relational engine can run them in multiple directions — forward ("what's the total?") and backward ("what promo code yields this total?", "which line item triggered the discount?").
That's a miniKanren fit. Pricing/promotion rules are relational; cart and order
lifecycle (reserve → pay → fulfil → reconcile) is a durable flow; the order
ledger is a persist stream. Commerce is the first real composition subsystem.
End-state: a catalog model, a relational pricing/promotion engine, a cart with deterministic totals, and an order lifecycle flow with payment-webhook reconciliation — all auditable via the event log.
Status (rolling)
bash lib/commerce/conformance.sh → 0/0 (not yet started)
Ground rules
- Scope: only
lib/commerce/**andplans/commerce-on-sx.md. May import fromlib/minikanren/, and (once they exist)lib/persist/+lib/flow/. Do not edit substrates. - Architecture: prices/promotions are miniKanren relations over catalog facts;
a cart total is a deterministic query result (first solution under a fixed rule
order). Order lifecycle is a
flowthat suspends at the payment IO boundary. Money is integer minor units — never floats. - Determinism: promotion stacking must have explicit, tested precedence; totals must be reproducible from the cart + catalog snapshot.
- Commits: one feature per commit. Progress log + tick boxes.
Architecture sketch
Catalog + cart Total / order
product(id,price,tags) {:subtotal :discounts :tax :total}
│ ▲
▼ │
lib/commerce/catalog.sx lib/commerce/price.sx
— product / variant / stock facts — miniKanren pricing relations
│ — promo stacking, membership rates
▼ ▲
lib/commerce/cart.sx lib/commerce/order.sx (flow + store)
— line items, quantities — reserve→pay→fulfil→reconcile
│ — SumUp webhook = flow resume
▼ │
lib/commerce/api.sx ── (commerce/add) (commerce/total) (commerce/checkout) ──┘
Phase 1 — Catalog + cart + deterministic totals
catalog.sx— product/variant/stock as factscart.sx— line items, add/remove/qtyprice.sx— base pricing relation, subtotal; taxapi.sx+ tests + scoreboard + conformance.sh
Phase 2 — Promotions (relational)
- promo rules: percentage, fixed, bundle, member rate
- explicit stacking precedence; "best price" backward query
- tests: stacking order, mutually-exclusive promos, member vs guest
Phase 3 — Order lifecycle (flow + store)
- order flow: reserve stock → await payment → fulfil
- payment webhook resumes the suspended flow
- order ledger as a
persiststream; idempotent reconciliation
Phase 4 — Reconciliation + federation
- mismatch detection (paid≠ordered) as queries over the ledger
- cross-instance catalog (federated marketplace) — out-of-scope stub
- tests: webhook replay, partial refund, double-charge guard
Progress log
(loop fills this in)
Blockers
(loop fills this in)