Files
kevin-asprec ea58620c7d docs(05): create phase plan
Phase 05: Visibility and Client Portal
- 5 plans in 3 waves
- 2 parallel (wave 1), 1 sequential (wave 2), 2 parallel (wave 3)
- Ready for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:14:54 +08:00

5.4 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
phase plan type wave depends_on files_modified autonomous must_haves
05-visibility-and-client-portal 04 execute 3
05-01
05-02
05-03
src/lib/__tests__/integration/api-rbac.test.ts
true
truths artifacts key_links
All API endpoints return 401 for unauthenticated requests
Role-restricted endpoints return 403 for unauthorized roles
Tenant A data is never returned to Tenant B users
COLLECTOR cannot access billing or subscriber management write endpoints
TECHNICIAN cannot access payment or invoice endpoints
CLIENT role can only read their own data
path provides min_lines
src/lib/__tests__/integration/api-rbac.test.ts Comprehensive API RBAC integration tests 200
from to via pattern
src/lib/__tests__/integration/api-rbac.test.ts src/lib/middleware/authorize.ts tests verify withPermission enforcement withPermission|401|403
Create integration tests that verify API-layer RBAC enforcement across all endpoints, including unauthorized access assertions and two-tenant cross-contamination tests.

Purpose: INFRA-03 — prove that the authorization layer cannot be bypassed at the API level. Output: Comprehensive integration test suite covering all roles and endpoints.

<execution_context> @C:\Users\KevinAsprec.claude/get-shit-done/workflows/execute-plan.md @C:\Users\KevinAsprec.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md

@src/lib/middleware/authorize.ts @src/lib/casl/permissions.ts @src/lib/casl/types.ts @src/middleware.ts

Task 1: API RBAC integration test suite src/lib/__tests__/integration/api-rbac.test.ts Create a comprehensive integration test file that tests API-layer authorization. Since Next.js API routes cannot be easily called via HTTP in test mode without starting the server, test at the SERVICE + MIDDLEWARE layer instead — test the withPermission HOF behavior and service-level tenant isolation.

Approach: Test the authorization logic directly by:

  1. Creating users with different roles in the test database
  2. Calling service methods with different tenant contexts
  3. Verifying CASL ability checks for each role against each subject

Test structure:

describe("API RBAC Integration Tests")
  describe("Authentication (401)")
    - Verify getCurrentUser returns null for no session -> would produce 401
    - Verify withPermission returns 401 when no user (mock getCurrentUser to return null)

  describe("Authorization by Role (403)")
    For each role, test what they CAN and CANNOT access:

    describe("ADMIN")
      - Can access all subjects (manage all)

    describe("OFFICE_STAFF")
      - Can manage Subscriber, Invoice, Payment, Ticket, JobOrder, Inventory, Expense, Vendor
      - Can read Report, Account
      - CANNOT create/update/delete Account

    describe("COLLECTOR")
      - Can read Subscriber, Zone
      - Can create Payment, read Payment
      - CANNOT read Report, manage Invoice, manage Subscriber, manage Ticket

    describe("TECHNICIAN")
      - Can read/update JobOrder (own only)
      - Can read Subscriber, read Inventory (own only)
      - CANNOT manage Payment, Invoice, Report, Ticket

    describe("CLIENT")
      - Can read Invoice (own), Payment (own), Subscriber (own)
      - Can create Ticket, read Ticket (own)
      - CANNOT manage User, read Report, manage Subscriber

  describe("Tenant Isolation")
    - Create Tenant A and Tenant B with subscribers, invoices, payments
    - Using Tenant A's context, query subscribers -> returns ONLY Tenant A data
    - Using Tenant B's context, query subscribers -> returns ONLY Tenant B data
    - Cross-query: Tenant A's subscriber ID passed to Tenant B context -> returns null or throws
    - Verify: invoice created in Tenant A is invisible to Tenant B
    - Verify: payment recorded in Tenant A is invisible to Tenant B

Implementation details:

  • Use defineAbilityFor and definePermissionsFor directly to test CASL rules
  • Use withTenantContext to create tenant-scoped Prisma clients for isolation tests
  • Use real database with actual tenant/user/subscriber records
  • Test at least 5 role combinations with at least 3 subjects each = 15+ assertions
  • Test at least 3 cross-tenant scenarios

Cleanup order: Follow the most comprehensive pattern (expense report cleanup from 04-04) since we create data across multiple subsystems.

Minimum test count: 15+ tests across all describe blocks. npx vitest run src/lib/__tests__/integration/api-rbac.test.ts — all tests pass All 5 roles tested against all relevant subjects; cross-tenant isolation verified with real data; 15+ tests pass; INFRA-03 satisfied

- `npx vitest run src/lib/__tests__/integration/api-rbac.test.ts` — all tests pass - Every role's can/cannot boundaries are explicitly tested - Two-tenant cross-contamination test proves data isolation

<success_criteria>

  • 15+ integration tests covering all 5 roles
  • Unauthorized access assertions prove RBAC enforcement
  • Two-tenant isolation tests prove no cross-contamination
  • INFRA-03 requirement satisfied </success_criteria>
After completion, create `.planning/phases/05-visibility-and-client-portal/05-04-SUMMARY.md`