GRO-1898: Ensure UAT seed data includes clients and pets with extended
profile fields (temperamentScore, temperamentFlags, medicalAlerts,
preferredCuts, coatType).
- Add data pools for extended profile fields in pet batch generation
- Populate all 5 extended fields for randomly generated pets
- Update UAT test client pets with fully populated extended profiles
- Fix type mismatches: medicalAlerts uses MedicalAlert[] with
{type, description, severity} shape per @groombook/types
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Conflicts resolved:
- src/middleware/rbac.ts: keep dev version (email null-guard, type assertion, single null-check)
- .gitea/workflows/ci.yml: keep uat version (branches: [main, dev, uat])
Co-Authored-By: Paperclip <noreply@paperclip.ing>
fix(gro-1866): add session-from-auth portal endpoint + role scope (#93)
Bridges Better Auth SSO sessions to portal sessions for real customers.
Adds role to genericOAuth scopes for Authentik role propagation.
Closes GRO-1866
Fixes two bugs found in QA review:
- ReferenceError: getAuth not defined in beforeEach - add import
- TypeError: wrong mock chain insert().into().values() vs insert().values()
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds POST /api/portal/session-from-auth which bridges a valid Better Auth
customer session (from SSO login) to a portal impersonation session, so
real SSO customers can access the client portal.
The endpoint is registered before the validatePortalSession catch-all so it
is not subject to that middleware. It validates the Better Auth session
from request cookies, looks up the client by email, creates an active
impersonation session, and returns { sessionId, clientId, clientName }.
Also adds "role" to the genericOAuth scopes so Authentik propagates the
role claim into Better Auth user objects (GRO-1862 root cause fix).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
GRO-1850: Adds temperament_score, temperament_flags, medical_alerts,
and preferred_cuts to the pets table.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
feat(GRO-1177): add pet profile summary endpoint (#30)
Adds GET /api/pets/:id/profile-summary with aggregated pet profile,
grooming history, visit count, and upcoming appointment.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Replace .select({ count: appointments.id }).limit(1) + .length with
sql<number>`count(*)::int` pattern per project standard (references invoices.ts:86)
- Add gte(appointments.startTime, new Date()) to upcomingAppointment query
so past appointments in scheduled/confirmed status are excluded
- Add visitCount regression tests: 2+ completed appointments → visitCount >= 2,
no completed → visitCount = 0
Updated UAT_PLAYBOOK.md §profile-summary (visitCount regression + date filter)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
With noUncheckedIndexedAccess:true, split("@")[0] returns string|undefined,
making `name` typed as string|undefined and failing the notNull staff.name
insert constraint. Fix by using ?? fallback on the array access.
Also add newStaff null guard after .returning() destructure — array
destructuring yields T|undefined with noUncheckedIndexedAccess enabled.
With noUncheckedIndexedAccess:true, split("@")[0] returns string|undefined,
making `name` typed as string|undefined and failing the notNull staff.name
insert constraint. Fix by using ?? fallback on the array access.
Also add newStaff null guard after .returning() destructure — array
destructuring yields T|undefined with noUncheckedIndexedAccess enabled.
Duplicate 'provenance: false' in each docker/build-push-action step caused
Gitea to reject the workflow file, breaking push CI and workflow_dispatch.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The DB coat_type enum only accepts: smooth, double, wire, curly, long, hairless.
"short" is not a valid value — corrected to "smooth".
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Lint Roller (QA) flagged that buildPet in factories.ts was missing the
4 fields added to the pets table schema, causing TS2739 in the Docker
build job (run 1701, job 3717).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Returns aggregated pet profile with:
- All pet fields (basic + extended)
- recentGroomingHistory: last 10 entries from groomingVisitLogs with staff name join
- lastVisitDate: most recent groomedAt timestamp
- visitCount: count of completed appointments
- upcomingAppointment: next scheduled/confirmed appointment with service/staff name
Enforces same groomer RBAC as GET /:id. Returns 404 for non-existent pets.
Adds PetProfileSummary, GroomingHistoryEntry, and UpcomingAppointment types.
Adds unit tests covering: 404, 403, aggregated profile, empty history, no upcoming appt.
Updates UAT_PLAYBOOK.md §3 with TC-API-3.8 and TC-API-3.9.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Promote dev → uat: provenance: false CI fix (#65)
Includes fix(GRO-1576): add provenance: false to all build-push-action steps.
Approved-by: The Dogfather (CTO)