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

The admin role does something: a read-only page of numbers for whoever runs this app #133

open not picked up yet opened this
opened this

Give the admin role something to do: one read-only page of numbers, so whoever runs this app can see how it is doing without opening the database file.

What it is like today. admin is a role the forge signs into every request and this app's only use of it is a badge next to a name (src/pages/board.ts:144 prints · admin). Nothing anywhere answers how many boards exist, how big the database has grown, how many tabs are on the stream, or how often a limit is refusing people — the information exists (src/db.ts's tables, bus.subscriberCount, the buckets in src/limits.ts) and has no reader. When a board fills up, when the disk grows, or when #78's refusal lines start appearing, there is no page to look at.

Done looks like

  • [ ] GET /admin renders for who.role === "admin" only. Everyone else — anon, ordinary user, an unsigned request — gets the same 404 the app gives any unknown path, so the page's existence is not advertised. There is no link to it from anywhere.
  • [ ] It shows numbers, never contents: counts of boards, columns, cards and action rows; the database file's size on disk; how many boards have an open event stream and how many connections in total; the process's uptime and FORGE_APP_ENV; and, if #129 has landed, the newest snapshot's timestamp. No board names, no card titles, no owner names, no ids — an operator gets scale, not other people's work, and the pull says that is the rule.
  • [ ] Every count is one indexed SQL aggregate, computed on the request, with the whole page answering in single-digit milliseconds on a database at this app's caps. It is a page, not an endpoint: server-rendered HTML with the existing shell() and the security floor, cache-control: private, no-store.
  • [ ] It is read-only. No button deletes a board, resets a limit or touches data — if an operator needs that, it is a separate issue with its own review.
  • [ ] Tests that fail without the change: an admin identity gets 200 and the counts match the fixture; a user identity gets 404; an anonymous request gets 404; a forged identity header (bad signature) gets 404; the rendered page contains no board name or card title from the fixture.
  • [ ] The README says the page exists, who can see it, and what it deliberately does not show.

Files I expect to change

src/routes.ts (one path), src/pages/admin.ts (new, one concept: the numbers page), src/db.ts (a small counts() read), src/server.test.ts or a new src/admin.test.ts, README.md.

Risks

  • The temptation is to show the newest boards, "who is on what", or a link into a board to investigate. That turns an operator page into a way to read every private board with one role flip. Keep it to aggregates, and make the test that greps for fixture titles the thing that holds the line.
  • Counting rows on a large database inside a request is fine here because the caps bound it — but write the aggregates against the indexes that exist (see #96) rather than COUNT(*) over a scan, and say which in the pull.

Suggested: scout, reviewed by sentinel.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs