Files
2026-03-05 18:41:32 +08:00

129 lines
9.3 KiB
Markdown

---
phase: 05-visibility-and-client-portal
verified: 2026-03-05T19:30:00Z
status: passed
score: 7/7 must-haves verified
re_verification:
previous_status: passed
previous_score: 5/5
audit_findings:
- "6 models missing from TENANT_SCOPED_MODELS (fixed in 05-06)"
- "CASL subject naming for collection/remittance routes (fixed in 05-06)"
- "E2E test coverage gaps for inventory/expense and portal ticket flows (fixed in 05-07)"
- "Phase 2 VERIFICATION.md outdated (fixed in 05-07)"
gaps_closed:
- "All 6 missing models registered in TENANT_SCOPED_MODELS with complete extends query blocks"
- "Collection and Remittance API routes use dedicated CASL subjects"
- "E2E tests cover inventory/expense and portal ticket workflows (21 tests across 5 workflows)"
- "Phase 2 VERIFICATION.md corrected to passed 5/5"
gaps_remaining: []
regressions: []
---
# Phase 5: Visibility and Client Portal Verification Report
**Phase Goal:** The ISP owner can see the complete financial and operational picture on a single dashboard; subscribers can log in to view their bills, payment history, and plan details, and submit tickets; and the full system is covered by integration and end-to-end tests on critical workflows.
**Verified:** 2026-03-05T19:30:00Z
**Status:** PASSED
**Re-verification:** Yes -- after milestone audit gap closure (plans 05-06 and 05-07)
## Goal Achievement
### Observable Truths
| # | Truth | Status | Evidence |
|---|-------|--------|----------|
| 1 | Dashboard shows revenue today/month, overdue count, outstanding amount, subscriber breakdown, cash flow summary | VERIFIED | DashboardService (424 lines) with 6 methods. GET /api/dashboard returns composite. Regression check: file unchanged, still substantive. |
| 2 | Subscriber can log in to portal and view bill, balance, payment history, plan details -- scoped to own account | VERIFIED | PortalService (123 lines), withPortalAuth middleware (64 lines). Regression check: files unchanged, still substantive. |
| 3 | Subscriber can submit a support ticket and it appears in staff ticket queue | VERIFIED | PortalTicketService (283 lines). Regression check: file unchanged. NEW: E2E Workflow 5 explicitly tests portal ticket to staff queue flow (lines 846-919). |
| 4 | All API endpoints have integration tests asserting RBAC enforcement for authorized/unauthorized roles | VERIFIED | api-rbac.test.ts (851 lines, 43 tests). Regression check: file unchanged, still substantive. |
| 5 | Critical workflows pass end-to-end tests (billing, collection/remittance, ticket/job-order, inventory/expense, portal ticket) | VERIFIED | e2e-workflows.test.ts (919 lines, 21 tests across 5 workflows). Extended from 16 to 21 tests in plan 05-07. |
| 6 | All tenant-scoped models have application-layer tenant isolation via TENANT_SCOPED_MODELS and extends query blocks | VERIFIED | prisma-tenant.ts (2517 lines) has 28 models in TENANT_SCOPED_MODELS array. All 6 previously missing models have complete extends blocks. |
| 7 | Collection and remittance routes use dedicated CASL subjects with proper role permissions | VERIFIED | types.ts has Collection and Remittance in AppSubjects. permissions.ts grants OFFICE_STAFF manage and COLLECTOR create/read for both. Zero matches for withPermission Subscriber in collections/ or remittances/ routes. |
**Score:** 7/7 truths verified
### Required Artifacts (Gap Closure)
| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| src/lib/prisma-tenant.ts | 28 models with extends blocks | VERIFIED | 2517 lines. 28 entries in TENANT_SCOPED_MODELS. Extends blocks at lines 1900, 1996, 2092, 2188, 2284, 2380. |
| src/lib/casl/types.ts | Collection and Remittance in AppSubjects | VERIFIED | Lines 16-17: Collection and Remittance present in union type. |
| src/lib/casl/permissions.ts | Collection/Remittance rules for OFFICE_STAFF and COLLECTOR | VERIFIED | Lines 70-71 and 95-99. |
| src/app/api/collections/route.ts | Uses Collection CASL subject | VERIFIED | POST=create/Collection, GET=read/Collection |
| src/app/api/collections/[id]/route.ts | Uses Collection CASL subject | VERIFIED | GET=read/Collection |
| src/app/api/collections/[id]/void/route.ts | Uses Collection CASL subject | VERIFIED | update/Collection |
| src/app/api/remittances/route.ts | Uses Remittance CASL subject | VERIFIED | POST=create/Remittance, GET=read/Remittance |
| src/app/api/remittances/[id]/verify/route.ts | Uses Remittance CASL subject | VERIFIED | update/Remittance |
| src/app/api/reports/collections/route.ts | Uses Collection CASL subject | VERIFIED | GET=read/Collection |
| src/lib/__tests__/integration/e2e-workflows.test.ts | 5 workflows | VERIFIED | 919 lines, 21 tests, 5 describe blocks. |
| .planning/phases/02-subscriber-and-billing-core/02-VERIFICATION.md | status: passed, score: 5/5 | VERIFIED | Frontmatter confirmed. |
### Required Artifacts (Original - Regression Check)
| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| src/lib/services/dashboard-service.ts | Dashboard metric aggregation | VERIFIED | 424 lines, unchanged |
| src/app/api/dashboard/route.ts | Dashboard API endpoint | VERIFIED | exists |
| src/lib/services/portal-service.ts | Subscriber-scoped data retrieval | VERIFIED | 123 lines, unchanged |
| src/lib/middleware/portal-auth.ts | Portal auth middleware | VERIFIED | 64 lines, unchanged |
| src/lib/services/portal-ticket-service.ts | Portal ticket creation + threads | VERIFIED | 283 lines, unchanged |
| src/lib/__tests__/integration/api-rbac.test.ts | RBAC integration tests | VERIFIED | 851 lines, unchanged |
### Key Link Verification (Gap Closure)
| From | To | Via | Status | Details |
|------|----|-----|--------|---------|
| prisma-tenant.ts | expense model queries | extends block at line 1900 | WIRED | All query methods inject tenantId |
| prisma-tenant.ts | expenseCategory model queries | extends block at line 1996 | WIRED | Full 14-method override set |
| prisma-tenant.ts | inventoryItem model queries | extends block at line 2092 | WIRED | Full 14-method override set |
| prisma-tenant.ts | stockMovement model queries | extends block at line 2188 | WIRED | Full 14-method override set |
| prisma-tenant.ts | vendor model queries | extends block at line 2284 | WIRED | Full 14-method override set |
| prisma-tenant.ts | ticketComment model queries | extends block at line 2380 | WIRED | Full 14-method override set |
| collections/route.ts | CASL permissions.ts | withPermission create/read Collection | WIRED | Zero Subscriber references remain |
| remittances/route.ts | CASL permissions.ts | withPermission create/read Remittance | WIRED | Zero Subscriber references remain |
| e2e-workflows.test.ts | InventoryService | import + registerItem + recordMovement calls | WIRED | Lines 49, 707, 720 |
| e2e-workflows.test.ts | ExpenseService | import + createCategory + createExpense calls | WIRED | Lines 50, 777, 785 |
| e2e-workflows.test.ts | createPortalTicket | import + function call | WIRED | Lines 51, 864 |
| e2e-workflows.test.ts | listTickets (staff view) | import + function call | WIRED | Lines 43, 880 |
### Anti-Patterns Found
| File | Line | Pattern | Severity | Impact |
|------|------|---------|----------|--------|
| None | - | - | - | No new anti-patterns introduced by gap closure plans |
### Human Verification Required
#### 1. Portal Login Flow
**Test:** Navigate to portal login page, enter subscriber account number and password, verify session persists
**Expected:** Subscriber sees their account overview with plan details, balance, billing day
**Why human:** Auth flow requires browser session, NextAuth redirect handling
#### 2. Dashboard Visual Layout
**Test:** Log in as admin, navigate to dashboard page
**Expected:** All 5 metric sections render with real data, no layout breaks
**Why human:** Phase 5 built the API layer only -- dashboard UI consumption needs frontend verification
#### 3. Portal Ticket Submission UX
**Test:** As a subscriber, submit a ticket through the portal UI, then log in as staff and check ticket queue
**Expected:** Ticket appears in staff queue with SUBSCRIBER source label
**Why human:** End-to-end browser flow crossing two auth contexts
### Gaps Summary
No gaps remain. All four issues identified by the milestone audit have been verified as resolved:
1. **Tenant scoping (P0 security):** All 28 tenant-scoped models now have complete extends query blocks in prisma-tenant.ts. The 6 previously missing models (expense, expenseCategory, inventoryItem, stockMovement, vendor, ticketComment) each have 14 query method overrides injecting tenantId.
2. **CASL subject naming:** Collection and Remittance are now first-class CASL subjects. All 8 collection/remittance route files use their dedicated subjects. Zero references to Subscriber remain in those routes. Role permissions are correctly assigned (OFFICE_STAFF: manage, COLLECTOR: create/read).
3. **E2E test coverage:** e2e-workflows.test.ts expanded from 3 workflows (16 tests) to 5 workflows (21 tests). Workflow 4 covers inventory receiving with JE posting and expense recording with auto-post JE, both verified against trial balance. Workflow 5 covers portal ticket creation with shadow user bridge and staff queue visibility.
4. **Phase 2 VERIFICATION.md:** Corrected from gaps_found (4/5) to passed (5/5), accurately reflecting the billing-service.ts fix that was applied earlier.
---
_Verified: 2026-03-05T19:30:00Z_
_Verifier: Claude (gsd-verifier)_