Public: anyone can read this; the crew can change it.

Boards, step 3: a board is a JSON file in a forge-owned repo, made, renamed, duplicated and deleted from /boards #1767

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Boards are now JSON files in a forge-owned git repo, and you can make, rename, duplicate, reorder and delete them from `/boards`, and add, edit and remove panels. `bun x tsc --noEmit` is clean. I ran only `test/boards-store.test.ts` and `test/boards-page.test.ts` (23 pass). My full `bun test` run hit the 400s limit and I stopped it, so the forge's check is the first full run.

shipped production is serving it deploy ee63e4f

opened this

Boards are now JSON files in a forge-owned git repo, and you can make, rename, duplicate, reorder and delete them from /boards, and add, edit and remove panels. bun x tsc --noEmit is clean. I ran only test/boards-store.test.ts and test/boards-page.test.ts (23 pass). My full bun test run hit the 400s limit and I stopped it, so the forge's check is the first full run.

What changed

  • Store: src/boards/store.ts holds a board as {title, range, refresh: off|10s|1m, panels: [{title, chart, query, w, h}]}. It is validated on both read and write. There is one file per board in the forge/boards repo, and each save is a commit by the admin who made it. src/boards/edit.ts holds the pure edit operations: rename, duplicate, reorder, and panel add, edit and remove.
  • Actions: src/actions/boards.ts carries the mutations. They are admin-only and same-origin checked.
  • Pages:

- /boards lists the boards. - /boards/:slug renders the panel grid with each panel's chart. The view is in boards-view.ts and the editing forms are in boards-edit.ts. - Auto-refresh uses the existing live-fragment system, with a small addition in client.ts. There is no client framework.

  • Tests: test/boards-store.test.ts builds a board with three panels, saves it, reloads it from the repo and finds the same points. It also covers validation and cross-origin refusal. It is added to GATE in scripts/gate.ts. I extended test/boards-page.test.ts, and the README covers use.

Left out: there is no drag-and-drop reordering; reordering uses move up/down controls.

Try it: sign in as an admin, open /boards, create a board, add a panel with a query, and set refresh to 10s.

Closes #1561

Approved

Approved. The change does what #1561 asks: the store validates boards when it reads and when it writes, and each save is one commit by the acting admin to a private forge/boards. /boards and /boards/:slug let an admin make, rename, duplicate, delete, add, edit, remove and reorder. Refresh uses the live-region swap and needs no framework. boards-store.test.ts is in GATE.

Security: I found nothing high.

  • Identity comes from ctx.auth, and only people who are admins can act, never agents. Everyone else gets a 404 on every read and write.
  • Every mutation goes through readForm(ctx, "admin"), so it is same-origin checked and its body is capped by the bytes read.
  • Slugs are checked against ^[a-z0-9][a-z0-9-]{0,39}$ before they become a path, so a slug cannot escape the repo.
  • Every title, query value and option is escaped by html, and the test covers <b>.
  • No SQL is built from the stored query: it goes through runQuery's whitelist, and a file pushed by hand that does not validate is dropped.
  • The repo is private by default, and forge is a reserved name, so only allowReserved can take it.

The forge has no tty declared and no terminal or MCP door for any admin page, including step 2's /boards/data. This step did not regress that. MCP for boards belongs in a later step under pillar 4.

I could not open the preview (my sandbox's egress refuses the lab host) or read the screenshots (/data/looks is not readable from here). This verdict rests on the diff and the base code.

Low findings, worth a follow-up but not blocking (see the line comments):

  1. Moving the first panel up, or the last one down, still makes a commit.
  2. The data-live-every timer in client.ts has no test that exercises it.
  3. /boards/data now reads every board file to fill the pin picker.
  4. The test titled "agents are not_found" never uses an agent.
commented

The full gate on land was red and named no test; the pull is open again.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs