Skip to content

feat: Workbench Phase 1 — gate admin page, count/transfer forms, datalists, filter, honest errors - #1

Merged
DanMat merged 1 commit into
mainfrom
feat/workbench-phase1
Aug 30, 2026
Merged

DanMat merged 1 commit into
mainfrom
feat/workbench-phase1

Conversation

@DanMat

@DanMat DanMat commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Part of the Inventory/Commerce Phase 1 "Workbench" slice (from Fable's Stocked & Shipped design). Depends on core ADR 0020 (NimbusCMS/nimbus#195, merged): a plugin admin page can now gate on the plugin's own capability.

What

  • Authorization parity. The Inventory page and all four form actions now require nimbuscms.inventory:write — the same wildcard-immune capability the MCP tools gate on. A content-only editor can no longer receive/adjust/count/transfer stock from the admin UI. (Closes the High from the pre-build security review.)
  • Count + Transfer forms. Ledger::count/transfer already existed and were agent-drivable; the UI and H3 actions were missing. Now present.
  • Typo-proof inputs. SKU + location <datalist> suggestions sourced from this plugin's own tables. Suggestions only — a genuinely new SKU can still be typed (Inventory deliberately owns no catalog), so first-receipt still works.
  • Stock filter. A bound ?q= SKU substring filter (no string-built SQL; the term is echoed back escaped — no reflected XSS).
  • Honest errors. InvalidArgumentException → badqty, InsufficientStock → short, same-location transfer → samelocation, instead of collapsing every \Throwable into one generic "check the SKU" notice.

Tests

  • InventoryAdminTest — rendering: datalists list known SKUs/locations, the filter narrows the stock table, a hostile filter term is bound + escaped (SQLi/XSS regression), notice codes map (unknown → no banner).
  • InventoryAdminActionsTest — the four H3 actions through the real PluginLoader (which also proves the page gates on the plugin capability — registration would throw on a pre-0020 core) with happy + honest-error paths and stock landing correctly.

43 tests green; PHPStan + php-cs-fixer clean. Reviewed pre-build by nimbus-review-loop (classified Official plugin) and nimbus-security-review.

🤖 Generated with Claude Code

…talists, filter, honest errors

Now that core can gate a plugin admin page on the plugin's own capability
(ADR 0020), the Inventory page and all four form actions require
`nimbuscms.inventory:write` — parity with the MCP tools, so a content-only
editor can no longer move stock from the UI.

- Count + Transfer forms (Ledger::count/transfer already existed; only the UI
  and the H3 actions were missing).
- SKU + location <datalist> suggestions sourced from this plugin's own tables
  (a typo-guard; a genuinely new SKU can still be typed — Inventory owns no
  catalog).
- A bound SKU substring filter (?q=) on the stock table — no string-built SQL,
  the term echoed back escaped (no reflected XSS).
- Honest notices: InvalidArgumentException -> "badqty", InsufficientStock ->
  "short", same-location transfer -> "samelocation", instead of collapsing
  every failure into one generic message.

Tests: InventoryAdminTest (render — datalists, filter narrowing, term
escaping/SQLi-safety, notice mapping) and InventoryAdminActionsTest (the H3
actions through the real loader — proving the page gates on the plugin cap and
each action maps failures honestly). 43 tests green; PHPStan + php-cs-fixer clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DanMat
DanMat merged commit c126ef8 into main Aug 30, 2026
2 checks passed
@DanMat
DanMat deleted the feat/workbench-phase1 branch August 30, 2026 18:23
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