feat(kanban): complete phase-2 primitive sweep - #146
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4b0f2a7. Configure here.
There was a problem hiding this comment.
Security Review — No high-confidence vulnerabilities found
Reviewed the full diff (29 files, ~1 700 changed lines). The changes introduce a resource-form abstraction, UI-level permission gates (CanAccess / useCan), and a localization sweep. No injection, SSRF, secret-handling, or supply-chain issues were found. Two informational observations are noted below.
1. CanAccess / useCan are UI presentation gates only
All new <CanAccess> wrappers (around "New Board", "Add Column", "Edit Board", "Delete Board", "Delete Task", drag handles, etc.) hide UI elements when the configured can() callback denies access. They do not prevent the underlying API mutations from being invoked directly (e.g., via DevTools or a crafted request).
This is documented library behaviour (auth.tsx comment: "all permission checks pass, and <CanAccess> renders its children — preserving pre-auth behaviour exactly") and is consistent with the existing pattern. However, consumers must be aware that server-side enforcement is required independently. The fix in resource/internal.ts — forwarding headers to every mutation — is a positive change that ensures auth headers reach the backend on all write paths.
Recommendation: The public docs (or the CanAccess JSDoc) should explicitly state that this is a presentation-layer gate and link to the server-side auth configuration.
2. Consumer-supplied template string with server error content (task-form.tsx)
const partialErrorTemplate = localization?.taskMovePartialError;
throw new Error(
partialErrorTemplate
? partialErrorTemplate.replaceAll("{{message}}", message)
: t(...)
);message is derived from error.message of a failed network call, which is server-controlled. The substituted string is later rendered as React text (not dangerouslySetInnerHTML), so there is no XSS risk. The only edge case is if message itself contains {{message}}; String.prototype.replaceAll does a single pass so there is no recursive substitution. No action required, but the pattern is worth being aware of in future localization templates.
3. select: (data: any) in kanbanResources declaration (query-keys.ts)
All new resource select callbacks use as casts (data as SerializedBoard, etc.) without runtime schema validation. If the server returns an unexpected shape (breaking API change, proxy modification), client code will silently operate on mistyped data. This is a code-quality concern, not a direct security risk, and matches the pattern of the removed code it replaces.
Sent by Cursor Automation: Find vulnerabilities
|
✅ Shadcn registry validated — no registry changes detected. |



Summary
kanban.*i18n with legacy localization override precedenceVerification
pnpm buildpnpm typecheckpnpm lintpnpm knippnpm test(CLI: 100 tests; stack: 451 tests)cd docs && pnpm buildpnpm --filter @btst/stack test-registry -- --skip-buildNote
Medium Risk
Broad UI and form/mutation behavior changes plus client-only auth gates; server APIs must still enforce policy, and column-change task saves have a two-step failure mode.
Overview
Kanban client UI now uses resource-form hooks (
useBoardForm/useColumnForm/useTaskForm) for create/update, with inline serverfieldErrors, and task edits that update thenmoveTaskwhen the column changes. Resource mutations forward pluginheadersfrom context.Authorization gates list/new/board routes via
ComposedRoutepermission, and hides or disables actions withCanAccess/useCan(boards, columns, tasks, drag handles, task open/delete). Copy goes throughuseTranslate(kanban.*) withoverrides.kanban.localizationstill winning.Registry, docs (permissions, localization, hooks), unit/client-sweep/query-key tests, and e2e (direct Add Task, move task via edit form) align with the above.
Reviewed by Cursor Bugbot for commit 9c17534. Bugbot is set up for automated code reviews on this repo. Configure here.