Claude: changes for issue #96 #97

Merged
Grandiras merged 1 commit from claude/issue-96 into main 2026-08-18 02:01:54 +00:00
Collaborator

Closes #96.

Closes #96.
Open a shared card link that points at another board
All checks were successful
CI / build (pull_request) Successful in 31s
be66002dd6
Following a link card to a card on a *different* board switched the
board and then said the card was not on it — the toast that says
"That card isn't on this board any more" — leaving the card unopened.

A change of board and a change of ?card= are two separate parameter
sets on the same reused BoardPage: the router re-renders it for the new
route parameter, and the framework's query-parameter supplier then
notifies it separately that the query changed. The second notification
lands inside the first one's await on the database, with the outgoing
board torn down and the incoming board's cards not fetched yet — so
OpenSharedCard answered "not here" from a board that was not loaded,
toasted it, and stripped ?card= off the URL before the load's own call
could open anything.

So the query is left alone while a board is in flight: the call that
can actually tell is a few milliseconds behind.

tests/e2e/share.spec.js follows a cross-board link from inside the app,
which is the only way to see it — a page.goto is a single parameter set
and always worked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Author
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/265); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-97/run-265.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

Verdict: approve — no blocking issues found.

Fixes a real re-entrancy bug: a cross-board shared-card link changes both the route parameter and the query parameter, which Blazor delivers as two separate OnParametersSetAsync invocations — the query-driven one lands mid-await of the route-driven one's ReloadAsync, before _columns reflects the new board, causing OpenSharedCard to wrongly conclude the card is gone, toast, and strip ?card= before the real load could open it.

The fix places the _loadingBoard guard inside OpenSharedCard() itself rather than only in the caller, which correctly protects both call sites — the full-reload branch in OnParametersSetAsync and the same-board branch that also calls OpenSharedCard() directly. Traced through the sequencing: _loadedBoardId is assigned synchronously before the await ReloadAsync(), so the reentrant query-only call takes the "same board" branch and hits the guard; once the load finishes, _loadingBoard is cleared and OpenSharedCard() is called again with SharedCardId still intact, so the open succeeds. No await points exist between clearing the flag and the final call, so there's no residual race there.

The new e2e test follows the established patterns in this suite (board creation/teardown mirrors boards.spec.js/calendar-all.spec.js), and its selectors (#desc-tab-preview, .link-card, data-card-id) match the actual markup in CardModal.razor and LinkCard.razor. The CLAUDE.md addition accurately documents the mechanism and the fix. No issues found.


⏱ 1m 29s · 13 turns · tokens: 74.4k in / 7.0k out (+1128.6k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Fixes a real re-entrancy bug: a cross-board shared-card link changes both the route parameter and the query parameter, which Blazor delivers as two separate `OnParametersSetAsync` invocations — the query-driven one lands mid-await of the route-driven one's `ReloadAsync`, before `_columns` reflects the new board, causing `OpenSharedCard` to wrongly conclude the card is gone, toast, and strip `?card=` before the real load could open it. The fix places the `_loadingBoard` guard inside `OpenSharedCard()` itself rather than only in the caller, which correctly protects **both** call sites — the full-reload branch in `OnParametersSetAsync` and the same-board branch that also calls `OpenSharedCard()` directly. Traced through the sequencing: `_loadedBoardId` is assigned synchronously before the `await ReloadAsync()`, so the reentrant query-only call takes the "same board" branch and hits the guard; once the load finishes, `_loadingBoard` is cleared and `OpenSharedCard()` is called again with `SharedCardId` still intact, so the open succeeds. No await points exist between clearing the flag and the final call, so there's no residual race there. The new e2e test follows the established patterns in this suite (board creation/teardown mirrors `boards.spec.js`/`calendar-all.spec.js`), and its selectors (`#desc-tab-preview`, `.link-card`, `data-card-id`) match the actual markup in `CardModal.razor` and `LinkCard.razor`. The CLAUDE.md addition accurately documents the mechanism and the fix. No issues found. --- ⏱ 1m 29s · 13 turns · tokens: 74.4k in / 7.0k out (+1128.6k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-97/run-265.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:be66002dd67441f6382192c1c785577af1710b5f -->
Grandiras deleted branch claude/issue-96 2026-08-18 02:01:54 +00:00
Grandiras referenced this pull request from a commit 2026-08-18 02:01:55 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/Ponente!97
No description provided.