Skip to content

test: lock tasks and snippet tenancy - #79

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/missing-test-coverage-476a
Draft

test: lock tasks and snippet tenancy#79
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/missing-test-coverage-476a

Conversation

@cursor

@cursor cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Summary

After #44/#45/#68, Hub route tests still skipped the tasks board and CA snippet library — those mutating paths only had access-helper coverage. This run locks those Officer Hub surfaces so a tenancy, assignment, or mass-assign regression cannot ship unnoticed.

PRs #57 (expense/elections/documents list-create) and #68 (polls/check-ins/discussions) are still open and are not duplicated here. Today's playbook, mobile-tool, and export Brand Kit changes already ship with tests.

Risky behavior now covered

  • Tasks: list never leaks another union or local; unknown status is ignored; mine=1 scopes to the session user; future since returns { changed: false }; create rejects forged tenant keys and stamps session union/local/creator; steward cannot assign others; president can; overlay tenant without tasks is 403; GET/PATCH/DELETE 403 another union (including platform_admin) with no write; assignee can mark own task done but cannot edit or delete another officer's task; extra PATCH tenant keys 400; creator can delete; reactions 404 missing / 403 other union / extra keys 400 / steward toggle.
  • Snippets: list never leaks another union or local; search q works; create rejects missing fields and stamps session union/creator even when the body forges tenant keys; GET/PATCH/DELETE 403 another union with no write; PATCH allowlist ignores unionId/localId/createdById; author can delete and another steward cannot; president can delete another officer's snippet.

Test files added/updated

  • src/lib/tasks/api-routes.test.ts
  • src/lib/validation/task.test.ts
  • src/lib/snippets/api-routes.test.ts
  • src/lib/tasks/memory-adapter.ts (test reset helper only)
  • src/lib/snippets/memory-adapter.ts (test reset helper only)
  • src/app/api/snippets/[id]/route.ts (PATCH allowlist — no longer spreads the raw body)

Why this reduces regression risk

These are confidential officer writes on casework to-dos and CA clause text. A missed unionId filter, a steward assigning someone else, or a snippet PATCH that copied unionId from the body would leak or re-home records across tenants. The new tests exercise the real route handlers (not just access helpers) so session gating, Zod .strict(), and the snippet allowlist stay aligned.

Checklist

  • No secrets, .env, keys, or real member/PII data
  • User-facing strings updated in both messages/en.json and messages/fr.json (if applicable)
  • Role/tenancy rules respected (unionId scoping; no cross-union access)
  • npm run lint and npm run test:unit pass
  • Smoke tests run if UI/routes changed (npm run test:smoke)
  • Docs updated if setup/deploy/privacy behaviour changed

Test plan

  • npx vitest run src/lib/tasks/api-routes.test.ts src/lib/validation/task.test.ts src/lib/snippets/api-routes.test.ts src/lib/tasks/access.test.ts src/lib/qol (43 passed)
  • npx eslint on the six touched files (clean)
  • Smoke not required (no UI; snippet PATCH allowlist is server-only)
Open in Web View Automation 

Hub task and CA snippet routes only had access-helper coverage. Route tests now lock list isolation, session stamping, assignment/delete rules, and reactions. Snippet PATCH allowlists title/clause/body/tags so a body cannot overwrite unionId.

Co-authored-by: Ryan Morris <ryan@ryanmorris.ca>
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