Public: anyone can read this; the crew can change it.
Every ledger row says who did it, and /admin/audit is the whole money trail on one page #77
Check · Review · Land · Live done — Landed and live in production.
`stock_entry`, `payment`, `order_event`, `gift_card_entry` and `discount_redemption` now carry `actor_id`, `actor_name` and `actor_role`, added through `addColumn` so the rows written before the column say `unknown` rather than guess. `src/actor.ts` is the one place an actor comes from — the buyer for a purchase, the admin for an admin action, `stripe` for a webhook, `system` for the seed, the for…
shipped production is serving it deploy ab962da
Sign in to join this conversation.
stock_entry,payment,order_event,gift_card_entryanddiscount_redemptionnow carryactor_id,actor_nameandactor_role, added throughaddColumnso the rows written before the column sayunknownrather than guess.src/actor.tsis the one place an actor comes from — the buyer for a purchase, the admin for an admin action,stripefor a webhook,systemfor the seed, the forge's account at the terminal — and every writer (note,addStock,takeStock,setStock, the payment and refund inserts, the gift-card and discount rows,createVariant's opening stock) takes it as a required argument, so the call sites are all accounted for rather than defaulted.src/audit.tsmerges the five ledgers into one timeline: one indexed read per table with a limit and a merge in memory, never five scans — each table gained an(at DESC, id DESC)index — and paging is a cursor of (when, which table, which row) so rows arriving while somebody reads cannot shift the page.GET /admin/auditis that timeline, admin-only, filtered by order number and paged with?before=; for one order it prints the arithmetic instead of a claim (charges plus the gift card, less refunds and what went back on the card, against what the order says was paid) and says whether the two agree./admin/orders/:numbershows the actor on every payment and every event, and the terminal has the same trail on an eighth tab, with/narrowing it to one order and the same reconciliation at its foot.Worth a look in the preview:
/admin/auditand/admin/audit?q=<order>after a purchase and a partial refund, and theaudittab over ssh. What I did not do:admin_changekeeps its own two actor columns and gained no role, and it is not merged into the timeline — it has its own page and is not money. No arithmetic changed;src/units.test.ts's totals tests pass with only their call signatures updated. Tests cover a buyer-named sale, an admin-named refund, astripe-named webhook charge, a terminal-named stock move, the page's ordering and reconciliation, the admin-only gate, and that the cursor neither repeats nor skips a row.🤖 Generated with Claude Code
Closes #12