Skip to content

feat(kanban): complete phase-2 primitive sweep - #146

Merged
olliethedev merged 3 commits into
v3from
feat/kanban-phase2-sweep
Aug 20, 2026
Merged

feat(kanban): complete phase-2 primitive sweep#146
olliethedev merged 3 commits into
v3from
feat/kanban-phase2-sweep

Conversation

@olliethedev

@olliethedev olliethedev commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • migrate Kanban board, column, and task data access to the v3 resource factory while preserving public hooks, query keys, routes, and SSG hydration
  • add resource-form hooks, field-level errors, exact cache invalidation, mutation header forwarding, and the task edit/move lifecycle
  • apply granular auth checks, provider-backed notifications, and kanban.* i18n with legacy localization override precedence
  • update the shadcn registry, consumer docs, unit coverage, and cross-framework Kanban smoke coverage

Verification

  • pnpm build
  • pnpm typecheck
  • pnpm lint
  • pnpm knip
  • pnpm test (CLI: 100 tests; stack: 451 tests)
  • cd docs && pnpm build
  • pnpm --filter @btst/stack test-registry -- --skip-build
  • Kanban Playwright suite on Next.js, TanStack Start, and React Router (12 scenarios per framework; corrected create-task selector reverified individually on all three)

Note

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 server fieldErrors, and task edits that update then moveTask when the column changes. Resource mutations forward plugin headers from context.

Authorization gates list/new/board routes via ComposedRoute permission, and hides or disables actions with CanAccess / useCan (boards, columns, tasks, drag handles, task open/delete). Copy goes through useTranslate (kanban.*) with overrides.kanban.localization still 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.

@vercel

vercel Bot commented Aug 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
better-stack-docs Ready Ready Preview Aug 19, 2026 10:29pm
better-stack-playground Ready Ready Preview Aug 19, 2026 10:29pm

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread packages/stack/registry/btst-kanban.json Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

@github-actions

Copy link
Copy Markdown
Contributor

Shadcn registry validated — no registry changes detected.

@olliethedev
olliethedev merged commit 058c6fc into v3 Aug 20, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant