Files
NetForge/.planning/phases/05-visibility-and-client-portal/05-06-SUMMARY.md
kevin-asprec a7022c33ab docs(05-06): complete tenant isolation and CASL subjects gap closure plan
Tasks completed: 2/2
- Add 6 missing models to tenant scoping (28 total)
- Add Collection and Remittance CASL subjects, update 8 routes

SUMMARY: .planning/phases/05-visibility-and-client-portal/05-06-SUMMARY.md

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

113 lines
4.3 KiB
Markdown

---
phase: 05-visibility-and-client-portal
plan: 06
subsystem: api, auth, database
tags: [prisma, casl, tenant-isolation, rbac, multi-tenancy, security]
# Dependency graph
requires:
- phase: 01-foundation
provides: Prisma tenant scoping pattern (withTenantContext)
- phase: 03-operational-modules
provides: Collection, remittance, expense, inventory, vendor models
- phase: 05-04
provides: RBAC integration tests verifying permission enforcement
provides:
- Complete tenant isolation for all 28 tenant-scoped models
- Dedicated Collection and Remittance CASL subjects with role-based permissions
affects: [all future phases using expense/inventory/vendor/ticketComment queries]
# Tech tracking
tech-stack:
added: []
patterns:
- "All tenant-scoped models must have $extends query blocks in prisma-tenant.ts"
- "Each domain entity gets its own CASL subject (not borrowed from Subscriber)"
key-files:
created: []
modified:
- src/lib/prisma-tenant.ts
- src/lib/casl/types.ts
- src/lib/casl/permissions.ts
- src/app/api/collections/route.ts
- src/app/api/collections/[id]/route.ts
- src/app/api/collections/[id]/void/route.ts
- src/app/api/remittances/route.ts
- src/app/api/remittances/[id]/verify/route.ts
- src/app/api/reports/collections/route.ts
key-decisions:
- "6 missing models use simple tenantId injection (no tenant relation stripping needed)"
- "Collection/Remittance subjects added to OFFICE_STAFF (manage) and COLLECTOR (create/read)"
patterns-established:
- "Every tenant-scoped Prisma model requires 14 query method overrides in $extends"
- "CASL subjects must match domain entities 1:1 for precise permission control"
# Metrics
duration: 7min
completed: 2026-03-05
---
# Phase 5 Plan 6: Gap Closure - Tenant Isolation and CASL Subjects Summary
**Closed P0 tenant isolation gap for 6 models (expense, expenseCategory, inventoryItem, stockMovement, vendor, ticketComment) and replaced borrowed Subscriber CASL subject with dedicated Collection/Remittance subjects across 8 route files**
## Performance
- **Duration:** 7 min
- **Started:** 2026-03-05T10:22:11Z
- **Completed:** 2026-03-05T10:29:00Z
- **Tasks:** 2
- **Files modified:** 9
## Accomplishments
- TENANT_SCOPED_MODELS expanded from 22 to 28 entries with complete $extends query blocks
- Collection and Remittance added as first-class CASL subjects with proper role assignments
- All 8 collection/remittance route handlers now use semantically correct permission subjects
- All 533 existing tests continue to pass
## Task Commits
Each task was committed atomically:
1. **Task 1: Add 6 missing models to tenant scoping** - `b462120` (fix)
2. **Task 2: Add Collection and Remittance CASL subjects and update routes** - `a59a246` (fix)
## Files Created/Modified
- `src/lib/prisma-tenant.ts` - Added 6 models to TENANT_SCOPED_MODELS array and 6 complete $extends query blocks (577 lines)
- `src/lib/casl/types.ts` - Added Collection and Remittance to AppSubjects union
- `src/lib/casl/permissions.ts` - Added Collection/Remittance rules for OFFICE_STAFF and COLLECTOR roles
- `src/app/api/collections/route.ts` - Switched from Subscriber to Collection subject
- `src/app/api/collections/[id]/route.ts` - Switched from Subscriber to Collection subject
- `src/app/api/collections/[id]/void/route.ts` - Switched from Subscriber to Collection subject
- `src/app/api/remittances/route.ts` - Switched from Subscriber to Remittance subject
- `src/app/api/remittances/[id]/verify/route.ts` - Switched from Subscriber to Remittance subject
- `src/app/api/reports/collections/route.ts` - Switched from Subscriber to Collection subject
## Decisions Made
- Used the simpler create pattern (direct tenantId injection without tenant relation stripping) for all 6 new models since none have a `tenant` Prisma relation field
- Granted COLLECTOR create+read (not manage) for Collection/Remittance to maintain principle of least privilege
## Deviations from Plan
None - plan executed exactly as written.
## Issues Encountered
None.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- Tenant isolation is now complete across all 28 models
- Permission model is semantically accurate for all route handlers
- Ready for plan 05-07 (remaining gap closure items)
---
*Phase: 05-visibility-and-client-portal*
*Completed: 2026-03-05*