feat: iCal calendar feed (GRO-107) #116

Merged
groombook-engineer[bot] merged 11 commits from feat/gro-107-ical-feed into main 2026-03-27 02:37:07 +00:00

11 Commits

Author SHA1 Message Date
Scrubs McBarkley f231a40e7f Merge main into feat/gro-107-ical-feed
Resolves conflict from fix(gro-38) (#117):
- index.ts: keep iCal calendar route, accept adminSeedRouter and portal placement from main
- waitlist.ts / waitlist.test.ts: accept main's implementation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-26 21:26:16 +00:00
Flea Flicker d7d3de999c Merge main into feat/gro-107-ical-feed to resolve merge conflicts
- portal.ts: keep min(1) validation for customerNotes (more restrictive)
- index.ts: keep waitlistRouter import and both calendar + portal public routes
- Both routers can coexist in public section (different URL namespaces)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-26 08:36:57 +00:00
Flea Flicker 21b7eff326 fix(CalendarSync): replace window.confirm() with inline confirmation and rename file
- Replace blocking window.confirm() with showRevokeConfirm state + inline
  confirmation dialog in CalendarSyncSection
- Rename CalendarSync.tsx to CalendarSyncSection.tsx to match export convention

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-26 08:18:54 +00:00
Flea Flicker 1e84823656 fix(calendar): address CTO review follow-up items
- Capture DTSTAMP once before loop instead of new Date() per event
- Return plain text 401 for auth errors (calendar clients can't parse JSON)
- Use encodeURIComponent for Content-Disposition filename

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-26 04:10:40 +00:00
Flea Flicker 8ca120d521 fix(calendar): address CTO review - N+1, Content-Disposition, SEQUENCE, sensitive leak
- Replace N+1 queries with single INNER JOIN across clients, pets, services
- Change Content-Disposition from attachment to inline for calendar auto-sync
- Add SEQUENCE:0 for confirmed, SEQUENCE:1 for cancelled events (RFC 5546)
- Fix sensitive field leak: return only {id, customerNotes, updatedAt}
- Add missing null-check guard after .returning() in portal.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 04:07:35 +00:00
Scrubs McBarkley f147dc3f89 fix: prefix unused staffName with underscore to satisfy ESLint
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-25 11:06:22 +00:00
Scrubs McBarkley c5977ef573 feat(gro-107): add CalendarSync UI component and calendar unit tests
- Add CalendarSync component with generate/revoke/copy functionality
- Add unit tests for generateIcalToken function
- Fix StaffRow type in petPhotos.test.ts and rbac.test.ts to include icalToken

The CalendarSync component can be added to a staff profile/settings page.
Currently the Staff page (admin/staff) does not have a profile section
for individual staff - integration will need a new route or profile section.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-25 11:04:13 +00:00
Scrubs McBarkley 5b1a8858f3 feat: implement iCal calendar feed (GRO-107)
- Add icalToken column to staff table
- Add public calendar feed endpoint GET /api/calendar/:staffId.ics
- Add token management routes POST/DELETE /api/staff/:id/ical-token
- Hand-build iCal output (RFC 5545)
- Update staff factory with icalToken field

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-25 11:04:13 +00:00
Scrubs McBarkley c8884c6c30 fix(waitlist): address QA review comments - auth fixes and pgEnum type
- Add 401 when DELETE /waitlist/:id has no session (auth bypass fix)
- Add auth to PATCH /waitlist/:id (was zero auth)
- Add RBAC guard for /waitlist/* routes
- Fix migration to use proper ENUM type instead of TEXT
- Add unit tests for auth scenarios

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-25 11:04:13 +00:00
Scrubs McBarkley 3bc920f36b feat: add waitlist entries table and API routes (GRO-105)
- Migration 0015: new waitlist_entries table with indexes
- Schema update: add waitlistEntries table and waitlistStatusEnum
- Staff API: GET /api/waitlist, GET /api/waitlist/:id
- Portal API: POST /api/waitlist (via impersonation session), DELETE /api/waitlist/:id
- Note: cancellation hook and email notification pending

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-25 11:04:13 +00:00
Scrubs McBarkley 3e2e19a312 feat: add customer-facing appointment notes (GRO-106)
- Migration 0014: add customer_notes column to appointments
- Schema update: add customerNotes field to appointments table
- Factory update: include customerNotes in buildAppointment
- Portal route: PATCH /api/portal/appointments/:id/notes
  - Ownership validation via impersonation session
  - Future-only validation (no edits after start)
  - 500 character limit
- Register portal router in index.ts

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-25 11:04:13 +00:00