Files
suaveplan/openspec/changes/enterprise-booking/tasks.md
2026-05-27 23:29:53 +01:00

5.1 KiB

Tasks: enterprise-booking

Change ID: enterprise-booking Package: @suaveplan/booking Target path: universal/commerce/booking Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/events, @suaveplan/datetime, @suaveplan/idempotency, @suaveplan/fsm


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create universal/commerce/booking/ with src/, tests/, src/__benchmarks__/ and all feature subdirectories per the layout in proposal.md.
  • Write package.json at version 0.1.0 with "type": "module", "sideEffects": false, correct exports map, dependencies, and devDependencies.
  • Write tsconfig.json extending @suaveplan/typescript-config/library.json.
  • Write vitest.config.ts using createTestConfig() from @suaveplan/testing/config.
  • Add lint, typecheck, test, test:coverage, build, docs:check scripts.

2. Types + errors

  • src/types/common.ts — BookingStatus, Resource, AvailabilityRule, Booking, BookingPolicy, BookingTransition, TimeSlot, BookOptions, CancelOptions, BookingFilter, AvailabilityOptions, BookingStore (interface), BookingEngineOptions.
  • src/types/common.md (≥200 words, both examples, API reference).
  • src/error-codes.ts — BookingErrorCode (8 codes), metadata, register, eager call.
  • src/types/schemas.ts + schemas.md — Zod schemas.

3. Core modules

  • src/availability/rule-evaluator/ — evaluateRule(rule, date, time): boolean: checks if a given datetime is within a working_hours rule (day-of-week + time range), blocked by a blackout rule (specific dates), or override capacity. Tests: each rule type, timezone edge cases (via injectable clock).
  • src/availability/availability-calculator/ — calculateSlots(resource, from, to, options): TimeSlot[]: expands AvailabilityRule[] over date range to produce time slots with remaining capacity. Tests: single-day slots, multi-day, blackout removes slot, capacity override, no rules returns empty.
  • src/core/booking-fsm/ — BookingFsm: wraps @suaveplan/fsm; legal transitions: pending→confirmed, pending→cancelled, confirmed→completed, confirmed→cancelled, confirmed→no_show, completed→[terminal]. Tests: all legal paths, two illegal transitions.
  • src/store/memory-store/ — createMemoryBookingStore(): in-memory BookingStore. Tests: CRUD, listByResource filter, waiting list operations.
  • src/waiting-list/waiting-list/ — WaitingList(store): add(resourceId, slot, guestId), get(resourceId, slot): string[], notifyNext(resourceId, slot, count): string[]. Tests: add/get, notifyNext removes from list and returns correct guest IDs.
  • src/core/booking-engine/ — BookingEngine: addResource, getAvailability, book, confirm, cancel, reschedule, complete, markNoShow, get, listByResource, waitingList, addToWaitingList, notifyWaitingList. book checks slot availability, capacity, wraps with idempotency guard, runs FSM transition. cancel checks cancellation window policy. reschedule cancels old slot and creates new booking. Tests: book/confirm/complete happy path, overbooking → joins waiting list, cancellation within window, cancellation outside window throws, reschedule, no-show.

4. OTel instrumentation

  • Span booking.transition with attributes booking.resource_id, booking.from_status, booking.to_status; counter booking.transition_total; histogram booking.availability_query_duration_ms.

5. Property-based tests (tests/property.test.ts)

  • Slot generation monotonicity: for arbitrary working-hours rules, slots in the returned list are strictly ordered by start and no two slots overlap.
  • FSM: any path from pending reaches a terminal state (completed, cancelled, no_show) in ≤3 transitions.

6. Benchmarks (src/__benchmarks__/booking.bench.ts)

  • calculateSlots for 30-day range with hourly slots.
  • BookingEngine.book 10 000 sequential bookings.

7. Docs + verify

  • One .md per implementation file (≥200 words, both examples, API reference). Root README.md.
  • bunx turbo lint typecheck test --filter=@suaveplan/booking — green.
  • bunx turbo test:coverage --filter=@suaveplan/booking — 100%.
  • bun scripts/publish.ts --package @suaveplan/booking.
  • Archive: openspec/archive/2026-04-24-enterprise-booking/.