Lay the foundations for multi-board support #68
Labels
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/Ponente#68
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Rework the backend to support multiple boards (for now without separate access rights)
🤖 On it — follow along in the action run; the reply will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the task runs.
The work is done and pushed. Here's my reply for the issue:
Reworked the backend for multiple boards — branch
claude/issue-68.A deployment now holds any number of boards, with no per-board access rights: every allowlisted member sees every board, and every admin can edit every one, which is what the issue asked for. Where rights would go when they land is written down in
CLAUDE.md(a join table besideBoard, andBoardService.ResolveAsyncas the one place that decides what somebody without access sees).The model. A board owns its columns and its tags. Cards deliberately carry no board of their own — the column they sit in already answers that, and a second copy of the answer is a second thing to keep in step — so reads take a board id and writes find it from the column or the card.
What changed
Boardentity,BoardIdonBoardColumnandTag, and anAddBoardsmigration that backfills: an existing installation's columns and tags are handed to a board created for them before the foreign keys go on. Its name goes in as plaintext because SQL inside a migration has no encryptor —EncryptionMigrator(now with aBoardsentry) seals it at the next startup.BoardService(cards, columns, the board query) is nowCardService;BoardServiceis the boards themselves — list, default, create/rename/reorder/delete. A page component namedBoardshadows the entity in every razor file, soBoard.razoris nowBoardPage.razor— the route (/) is unchanged.BoardNotifier.BoardChangednow carries a board id so a circuit only reloads for its own board; it is nullable for the mutations that genuinely touch every board (a member's avatar or display name), and there is a separateBoardsChangedfor the set of boards./board/{id},/calendar/board/{id},/admin/columns/{id},/admin/tags/{id}. The bare paths mean the default board, so every existing link still works; a stale id renders "this board no longer exists" rather than silently substituting another board's cards.Restrictall the way down, and the service refuses a board that still holds cards (the admin page shows the count) and refuses the last board outright./admin/boardsmanages them with drag-reorder — the first is the default — and the columns/tags admin pages get a board picker. The column sort interop is parameterised rather than copied. New strings in both locales..icsdownload and the subscribable feed all take an optionalboard, 404 on one that has gone, and name the board inX-WR-CALNAME.What I verified.
dotnet buildclean;dotnet test157 passed (3 newIcsCalendarTests, and the en/de key-parity test covers the new strings). Then, because the interesting parts are only visible at runtime, I stood up Postgres and ran the real app: applied the schema at the previous migration, seeded legacy columns/tags/cards, ranAddBoards, and checked the backfilledBoardIds row by row. Against that live app I ran Playwright: the newtests/e2e/boards.spec.js(6 tests: a new board is usable and its own page, cards don't leak between boards, delete refuses while cards remain, the nav switcher, per-board tags and admin pages, a dead board link, and the export/feed naming their board) plusboard,calendar,filter,mobile,i18nandprefs— 97 passed on a clean board. Three did not: two board-spec flakes that pass in isolation and on a re-run, and one calendar test that needs a dated card in the next month, which my throwaway database had none of. I also checked thesix-week monthandstored localefailures against unmodifiedmainon the same machine — they fail there too (accumulated tags making the legend two rows tall; a cookie hard-coded tolocalhost:8090), so they aren't from this change.Two existing calendar assertions needed updating, since the export href legitimately carries
board=now, andglobal-teardown.jsnow reclaims boards a run created (and their columns, which carry no timestamp of their own).CLAUDE.mdhas a new Multiple boards section plus the updates the rename and the notifier change imply.⏱ 63m 11s · 210 turns · tokens: 349.7k in / 144.5k out (+49438.6k cache-read)
📜 Full session transcript
→ Opened PR: #70