Skip to content

feat: Phase 2 — order detail + append-only status timeline - #3

Merged
DanMat merged 1 commit into
mainfrom
feat/phase2-order-detail
Aug 30, 2026
Merged

DanMat merged 1 commit into
mainfrom
feat/phase2-order-detail

Conversation

@DanMat

@DanMat DanMat commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Phase 2a "Answers" (from Fable's Stocked & Shipped), pairs with NimbusCMS/plugin-inventory#3.

What

An order detail at GET /admin/commerce?order=REF — a branch of the existing gated page (no new route; holdsPageGate/ADR 0020 applies): the order, its lines, its lifecycle buttons, and a timeline.

The timeline is backed by a new append-only commerce_order_event table (002_order_events); OrderBook records one row inside each existing gated transition (place/pay/fulfil/cancel). The actor is server-setadmin-ui from the admin actions, the token principal over MCP — never from request input. The order's status stays the authoritative current state. Order refs in the list link to the detail.

place/pay/cancel gained an optional actor param (default system, backward-compatible); the now-unused transition() helper was inlined into pay().

Safety

Read views are bound + escaped (REF); the only write is the append-only event, server-set fields inside existing gated transactions — no new endpoint. (Both review skills run pre-build; security-green.)

Deploy note

Adds a migration → the demo/redeploy needs php bin/nimbus migrate + a golden.sql reseed.

Tests

Detail renders lines + timeline (pending → "Placed"), currency-correct totals, rows link to it, unknown/hostile ?order= handled + escaped; migration list updated; Choreography + actions suites create the event table. 26 tests green; PHPStan + php-cs-fixer clean.

🤖 Generated with Claude Code

An order detail view at GET /admin/commerce?order=REF (a branch of the existing
gated page — no new route, holdsPageGate still applies): the order, its lines,
its lifecycle buttons, and a real timeline.

The timeline is backed by a new append-only commerce_order_event table
(002_order_events); OrderBook records one row inside each existing gated
transition (place/pay/fulfil/cancel). The actor is server-set — 'admin-ui' from
the admin actions, the token principal name over MCP — never from request input.
The order's own status stays the authoritative current state.

Order references in the list link to the detail. All reads bound; REF escaped.
place/pay/cancel gained an optional actor param (default 'system', BC); the
now-unused transition() helper was inlined into pay().

Tests: order detail renders lines + timeline (pending reads as "Placed"),
currency in the order's currency, rows link to it, unknown/hostile ?order= are
handled + escaped; migration list asserts 002_order_events; Choreography +
actions tests create the event table. 26 tests green; PHPStan + php-cs-fixer clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DanMat
DanMat merged commit 17227de into main Aug 30, 2026
2 checks passed
@DanMat
DanMat deleted the feat/phase2-order-detail branch August 30, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant