Commit Graph

6 Commits

Author SHA1 Message Date
Ronni Baslund e33b7f18a3 feat(scheduling): pluggable captcha (Turnstile) on public booking 2026-06-07 09:02:35 +02:00
Ronni Baslund e1a77b085f feat(scheduling): optional JWT-authed dezky Meet rooms 2026-06-07 08:58:00 +02:00
Ronni Baslund f41475ac3b feat(scheduling): ignoreAllDayEvents option 2026-06-07 08:53:31 +02:00
Ronni Baslund 2cb13a1a14 feat(scheduling): retry calendar writes for pending bookings
A failed Stalwart calendar write during confirmation no longer deletes the
booking + SlotLock. The booking stays 'pending' with its lock retained, and a
new @Cron worker (every 2 min, max 5 attempts by default) re-drives the write:
on success it promotes to 'confirmed' and sends the confirmation email; after
the cap it moves to the terminal 'calendar_failed' state and releases the lock.

Tracks calendarWriteAttempts + lastCalendarError on the Booking. The public
confirm endpoint still throws 503 on a failed first write (preserving the DoD:
never surface a confirmed booking without a calendar event); the pending row is
left for the background retry to finish.
2026-06-07 08:49:53 +02:00
Ronni Baslund 9e1defa946 feat(scheduling): booking reminder emails 2026-06-07 00:31:33 +02:00
Ronni Baslund 5ed3d2bc5f feat(scheduling): dezky Scheduling — Calendly-style booking on Stalwart calendars
First-party booking system on top of Stalwart calendars (no third-party
scheduling dependency). Hosts expose public booking pages; visitors pick a
slot computed from the host's live Stalwart free/busy, and confirming writes
the event to the host's calendar and sends a dezky-branded confirmation with
an .ics.

platform-api (services/platform-api/src/scheduling):
- Schemas: Host, StalwartCredential (AES-256-GCM at rest), AvailabilitySchedule,
  EventType, Booking, SlotLock (unique (hostId,startUtc) + TTL).
- StalwartCalendarModule: JMAP gateway (free/busy via Principal/getAvailability,
  event create/delete, scheduleAgent=client) + on-behalf app-password
  provisioning. CredentialCipher for at-rest encryption.
- DST-correct slot engine (Luxon) with unit tests; two-layer double-booking
  guard (atomic SlotLock + live free/busy re-check).
- Booking confirm/cancel/reschedule, branded email + .ics via JMAP submission,
  self-service manage tokens. /api/v1 public + tenant-gated admin routes,
  per-IP rate limiting.

apps/booking: standalone public, whitelabel booking app (booking.dezky.eu) —
path-based tenant resolution, per-tenant brand colour, booking + manage flows.

apps/portal: admin scheduling page (hosts, event types, availability, bookings
with edit/delete + admin cancel/reschedule) and proxy routes.

infra: booking dev service in docker-compose; scheduling env vars.
2026-06-07 00:17:36 +02:00