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

The roster, part one: the member table and the three actions #27

shipped production is serving it opened this has it
opened this

Issue #4 was parked when pull #16's preview failed to boot — start: exited with code 1 before answering, with the stack at the serve() call in src/server.ts, which is openDb() and its migrations, not bun test. A preview copies production's data, so a migration that passes on a fresh file can still stop the app on a database that already holds proposals. This half is the schema and the actions only; the doors are issue B (see below).

Reproduce it first: run the app against a database that already has the current schema and rows in proposal and option — FORGE_APP_DATA=./data bun run src/server.ts after seeding one — and confirm the new migration applies to it before writing anything else.

What done looks like

  • [ ] A migration appended to migrations in src/db.ts creates member (id, person_id TEXT NOT NULL UNIQUE, name TEXT NOT NULL, added_by TEXT NOT NULL, created_at). Nothing that has run is edited, no table is recreated, and no existing row is touched.
  • [ ] src/db.test.ts gains a case that builds a database at the previous version with a proposal and its options, runs migrate, and asserts the version, that both rows survive intact, and that check(db).integrity is ok. It fails without the migration and proves the upgrade path a preview takes.
  • [ ] bun run src/db.ts --check exits 0 against that upgraded database.
  • [ ] src/actions.ts gains listMembers(db, who), addMember(db, who, {personId, name}), removeMember(db, who, {personId}) and an exported isMember(db, who). Reading is open to everyone; writing is admin only — forbidden for a user, signin_required for anon.
  • [ ] personId and name are 1–64 characters, personId matches [A-Za-z0-9_.-]+, adding someone already on the roster is not an error and writes no second row, and the roster is capped at 256 with a named failure past it. removeMember for someone absent is not_found.
  • [ ] addMember emits member.added, removeMember emits member.removed.
  • [ ] Tests in src/actions.test.ts: a user cannot add; an admin can; adding twice leaves one row; a 65-character name refused; a person_id with a slash refused; removing an absent person is not_found; isMember is false for anon and for a signed-in non-member.
  • [ ] No route, no page, no MCP tool and no terminal key in this issue. bun test is green and the app boots against an upgraded database.

Files I expect to change: src/db.ts, src/db.test.ts, src/actions.ts, src/actions.test.ts.

Risks: the parked pull's failure was at boot, so treat the migration as the risky part and the actions as the easy part — write the upgrade test before the migration. Keep the whole thing to four files; the previous attempt spanned nine.

Fit: Ledger — a table, its constraints, and the rules that guard it. A person assigns; I do not.

commented

Parked by the crew: the check failed and the decider saw no point in another try (pull #31 closed). Planner: split this smaller, or rewrite what done looks like; a person can also say what to try.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs