Tasks completed: 2/2 - Portal authentication via subscriber account number - PortalService, API routes, and integration tests (5 tests) SUMMARY: .planning/phases/05-visibility-and-client-portal/05-02-SUMMARY.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.9 KiB
4.9 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, decisions, metrics
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | decisions | metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-visibility-and-client-portal | 02 | portal |
|
|
|
|
|
|
|
|
Phase 05 Plan 02: Subscriber Portal Authentication and API Summary
Portal auth via account number + password with subscriber-scoped read-only API endpoints, 5 tests passing
What Was Done
Task 1: Portal Authentication
- Added
passwordHash(nullable String) to Subscriber model in Prisma schema - Added second CredentialsProvider (
portal-credentials) to NextAuth config accepting accountNumber + password + tenantId - Provider looks up subscriber by @@unique([tenantId, accountNumber]) with non-null passwordHash
- JWT callback persists
subscriberIdinto token; session callback exposes it on session.user - Extended next-auth type definitions (Session, User, JWT) with optional
subscriberId - Updated middleware matcher to exclude
/portal/loginand/api/portal/authfrom auth requirement
Task 2: PortalService and API Routes
- Created
PortalServicewith three subscriber-scoped methods:getPortalAccount(db, subscriberId)-- returns profile, plan details, credit balance, billing daygetPortalInvoices(db, subscriberId, options)-- paginated invoices with line items, ordered by periodStart DESCgetPortalPayments(db, subscriberId, options)-- paginated payments, ordered by createdAt DESC
- Created
withPortalAuthmiddleware HOF that validates subscriberId in session (401 if no session, 403 if not portal user) - Created three portal API routes:
GET /api/portal/account-- subscriber profile + planGET /api/portal/invoices-- paginated invoices (query: page, limit)GET /api/portal/payments-- paginated payments (query: page, limit)
Integration Tests (5/5 passing)
getPortalAccount returns subscriber with plan details-- verifies all fields including plan name, speed, price, billingTypegetPortalInvoices returns paginated invoices-- creates 3 invoices, verifies page 1 limit 2 returns 2 with total 3getPortalPayments returns paginated payment history-- creates 2 payments, verifies list and subscriber scopinggetPortalAccount scoped to subscriberId only-- creates 2 subscribers, verifies each sees only own datagetPortalInvoices includes invoice line items-- verifies lines array populated with description and lineTotal
Deviations from Plan
None -- plan executed exactly as written.
Commits
| Hash | Message |
|---|---|
539564d |
feat(05-02): portal authentication via subscriber account number |
7222dbe |
feat(05-02): portal service, API routes, and integration tests |
Requirements Satisfied
- PORT-01: Subscriber can log in with account number and password
- PORT-02: Subscriber can view current bill and outstanding balance (via invoices endpoint + account creditBalance)
- PORT-04: Subscriber can view full payment history (via payments endpoint)
- Account overview includes plan details, balance, and billing day
- Invoice and payment history are paginated
- Portal API endpoints scoped to logged-in subscriber only