@topy-ai/maggie 0.7.38 → 0.7.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README-zh-TW.md +82 -6
  2. package/README.md +99 -7
  3. package/bin/maggie.js +30 -3
  4. package/bundled-contracts/maggie-clone/interaction-state-v1.schema.json +26 -0
  5. package/bundled-contracts/maggie-content/provenance-v1.schema.json +20 -0
  6. package/bundled-contracts/maggie-design/brand-kit-v1.schema.json +18 -0
  7. package/bundled-contracts/maggie-design/browser-interactions-v1.schema.json +27 -0
  8. package/bundled-contracts/maggie-design/css-utility-evidence-v1.schema.json +10 -0
  9. package/bundled-contracts/maggie-design/dashboard-surface-v1.schema.json +11 -0
  10. package/bundled-contracts/maggie-design/progressive-enhancement-v1.schema.json +12 -0
  11. package/bundled-contracts/maggie-design/sample-surface-v1.schema.json +13 -0
  12. package/bundled-contracts/maggie-design/style-editing-v1.schema.json +35 -0
  13. package/bundled-contracts/maggie-media/image-generation-policy-v1.json +28 -0
  14. package/bundled-contracts/maggie-media/video-generation-policy-v1.json +40 -0
  15. package/bundled-contracts/maggie-media/video-job-v1.schema.json +20 -0
  16. package/bundled-contracts/maggie-media/video-playback-evidence-v1.schema.json +15 -0
  17. package/bundled-contracts/maggie-ops/npm11-preflight-v1.schema.json +17 -0
  18. package/bundled-contracts/maggie-scaffold/host-scaffold-v1.schema.json +25 -0
  19. package/bundled-contracts/maggie-seo/gsc-readiness-v1.schema.json +19 -0
  20. package/bundled-contracts/maggie-seo/privacy-origin-evidence-v1.schema.json +11 -0
  21. package/bundled-contracts/maggie-service-booking/delivery-provider-default-v1.json +8 -0
  22. package/bundled-contracts/maggie-service-booking/delivery-provider-v1.schema.json +16 -0
  23. package/bundled-contracts/maggiedash/booking-access-v1.json +5 -4
  24. package/bundled-contracts/maggiedash/booking-customer-surface-v1.json +12 -1
  25. package/bundled-contracts/maggiedash/booking-email-templates-v1.json +2 -0
  26. package/bundled-contracts/maggiedash/booking-host-adapter-v1.json +14 -2
  27. package/bundled-contracts/maggiedash/booking-runtime.v1.json +41 -0
  28. package/bundled-contracts/maggiedash/browser-session-v1.schema.json +18 -0
  29. package/bundled-contracts/maggiedash/content-overrides-v1.schema.json +19 -0
  30. package/bundled-contracts/maggiedash/execution-board.json +526 -26
  31. package/bundled-contracts/maggiedash/host-capabilities-v1.schema.json +10 -0
  32. package/bundled-contracts/maggiedash/public-session-cache-v1.schema.json +17 -0
  33. package/bundled-contracts/maggiedash/site-structure-v1.schema.json +13 -0
  34. package/bundled-references/browser-inspection.md +21 -0
  35. package/bundled-references/maggiedash-booking/ARCHITECTURE.md +218 -0
  36. package/bundled-references/maggiedash-booking/CURRENT-STATE.md +92 -0
  37. package/bundled-references/maggiedash-booking/DATA-FLOW.md +143 -0
  38. package/bundled-references/maggiedash-booking/DATA-MODEL.md +367 -0
  39. package/bundled-references/maggiedash-booking/DECISIONS.md +94 -0
  40. package/bundled-references/maggiedash-booking/EXECUTION-BOARD.json +2387 -0
  41. package/bundled-references/maggiedash-booking/HOST-ADAPTER.md +314 -0
  42. package/bundled-references/maggiedash-booking/ORAWELLNESS-INTEGRATION-AUDIT.md +227 -0
  43. package/bundled-references/maggiedash-booking/PAYMENT-GATEWAY.md +267 -0
  44. package/bundled-references/maggiedash-booking/PRD.md +228 -0
  45. package/bundled-references/maggiedash-booking/PROGRESS.md +2434 -0
  46. package/bundled-references/maggiedash-booking/QA-TEST-PLAN.md +235 -0
  47. package/bundled-references/maggiedash-booking/README.md +271 -0
  48. package/bundled-references/maggiedash-booking/RUNTIME-OPERATIONS.md +152 -0
  49. package/bundled-references/maggiedash-booking/SECURITY-COMPLIANCE.md +158 -0
  50. package/bundled-references/maggiedash-booking/SKILLS-AND-CLI.md +542 -0
  51. package/bundled-references/maggiedash-booking/STRIPE-INTEGRATION.md +129 -0
  52. package/bundled-references/maggiedash-booking/TASK-RUNBOOK.md +107 -0
  53. package/bundled-references/maggiedash-booking/TASKS.md +137 -0
  54. package/bundled-references/maggiedash-booking/USER-JOURNEYS.md +224 -0
  55. package/bundled-references/maggiedash-booking/diagrams/booking-dfd.excalidraw +1 -0
  56. package/bundled-references/maggiedash-booking/diagrams/booking-dfd.mmd +16 -0
  57. package/bundled-references/maggiedash-booking/diagrams/booking-dfd.png +0 -0
  58. package/bundled-references/maggiedash-booking/diagrams/booking-dfd.svg +1 -0
  59. package/bundled-references/maggiedash-booking/diagrams/booking-state-machine.mmd +19 -0
  60. package/bundled-references/maggiedash-booking/diagrams/booking-state-machine.png +0 -0
  61. package/bundled-references/maggiedash-booking/diagrams/booking-state-machine.svg +1 -0
  62. package/bundled-references/maggiedash-booking/diagrams/manager-journey.excalidraw +1 -0
  63. package/bundled-references/maggiedash-booking/diagrams/manager-journey.mmd +11 -0
  64. package/bundled-references/maggiedash-booking/diagrams/manager-journey.png +0 -0
  65. package/bundled-references/maggiedash-booking/diagrams/manager-journey.svg +1 -0
  66. package/bundled-references/maggiedash-booking/diagrams/payment-sequence.mmd +20 -0
  67. package/bundled-references/maggiedash-booking/diagrams/payment-sequence.png +0 -0
  68. package/bundled-references/maggiedash-booking/diagrams/payment-sequence.svg +1 -0
  69. package/bundled-references/maggiedash-booking/diagrams/system-context.excalidraw +1 -0
  70. package/bundled-references/maggiedash-booking/diagrams/system-context.mmd +10 -0
  71. package/bundled-references/maggiedash-booking/diagrams/system-context.png +0 -0
  72. package/bundled-references/maggiedash-booking/diagrams/system-context.svg +1 -0
  73. package/bundled-skills/maggie-blog/SKILL.md +12 -0
  74. package/bundled-skills/maggie-blog-bootstrap/SKILL.md +39 -0
  75. package/bundled-skills/maggie-booking/SKILL.md +112 -18
  76. package/bundled-skills/maggie-clone/SKILL.md +13 -0
  77. package/bundled-skills/maggie-deployment/SKILL.md +6 -0
  78. package/bundled-skills/maggie-design/SKILL.md +64 -3
  79. package/bundled-skills/maggie-ops/SKILL.md +12 -0
  80. package/bundled-skills/maggie-seo-geo/SKILL.md +45 -0
  81. package/bundled-skills/maggie-service-booking/SKILL.md +14 -0
  82. package/bundled-tools/clis/maggie_analytics.py +43 -1
  83. package/bundled-tools/clis/maggie_booking.py +161 -26
  84. package/bundled-tools/clis/maggie_browser_audit.py +99 -3
  85. package/bundled-tools/clis/maggie_clone.py +46 -1
  86. package/bundled-tools/clis/maggie_contracts.py +393 -0
  87. package/bundled-tools/clis/maggie_dash.py +22 -6
  88. package/bundled-tools/clis/maggie_design.py +84 -12
  89. package/bundled-tools/clis/maggie_service_booking.py +50 -1
  90. package/bundled-tools/clis/maggie_workflows.py +387 -0
  91. package/bundled-tools/clis/site_audit.py +77 -1
  92. package/bundled-tools/integrations/analytics.md +14 -0
  93. package/bundled-tools/runtime/site_baseline.py +3 -0
  94. package/package.json +1 -1
  95. package/references/browser-inspection.md +21 -0
@@ -0,0 +1,314 @@
1
+ # Booking host adapter contract
2
+
3
+ This is the versioned screen-level contract for `/_maggie/booking`. It extends
4
+ the current MaggieDash host adapter model rather than replacing it. The host
5
+ continues to own routes, email/password sessions, database access, provider
6
+ secrets, and deployment.
7
+
8
+ ## 1. Route and auth rules
9
+
10
+ ```text
11
+ Public/customer booking: host-owned public route, no admin session required
12
+ Manager UI: /_maggie/booking, host email/password session required
13
+ Manager API: /api/maggie/booking/*, same-origin session required
14
+ Provider webhooks: host server endpoint, provider signature required
15
+ ```
16
+
17
+ The booking UI is `noindex,nofollow`. It uses the existing host-session cookie
18
+ and role/membership checks. Passkeys and passwordless login are not part of this
19
+ contract.
20
+
21
+ When the session role is `staff`, the host must return the linked Booking
22
+ `staffId` in the server-only session context. The repository then limits staff
23
+ reads and lifecycle mutations to allocations and schedule/location records
24
+ owned by that staff profile. A staff role without a linked profile is rejected;
25
+ the browser must never be allowed to choose or override this scope.
26
+
27
+ MaggieDash also ships a framework-neutral dispatcher at
28
+ `backend/booking/route-handler.mjs`. Hosts can inject `createBookingService`
29
+ plus their session lookup and verified webhook handler to obtain the complete
30
+ 47-route mapping with common JSON parsing, idempotency, project scope, role
31
+ checks, correlation headers, and safe error responses. The host remains
32
+ responsible for the actual repository, transaction, provider verification, and
33
+ deployment. Validate the boundary with
34
+ `npm run booking:route-handler:test` before wiring framework routes.
35
+
36
+ Customer traffic uses a separate public-noindex dispatcher at
37
+ `backend/booking/customer-route-handler.mjs`. It does not use the manager
38
+ session. The host must bind the request to a tenant and apply origin/CSRF,
39
+ rate-limit, bot, and opaque payment-return-token controls. Its DTO and
40
+ notification boundary is in `backend/booking/customer-flow.mjs`.
41
+
42
+ ## 2. Proposed endpoints
43
+
44
+ All JSON errors use:
45
+
46
+ ```json
47
+ {
48
+ "error": "safe human-readable message",
49
+ "code": "stable.machine.code",
50
+ "correlationId": "corr_...",
51
+ "retryable": false
52
+ }
53
+ ```
54
+
55
+ | ID | Method | Route | Purpose |
56
+ |---|---|---|---|
57
+ | `booking.overview.read` | GET | `/api/maggie/booking/overview.json` | KPI cards, provider health, readiness, next bookings |
58
+ | `booking.calendar.read` | GET | `/api/maggie/booking/calendar.json` | Day/week allocations and filters |
59
+ | `booking.bookings.read` | GET | `/api/maggie/booking/bookings.json` | Search and paginated booking list |
60
+ | `booking.booking.read` | GET | `/api/maggie/booking/bookings/{id}.json` | Detail, timeline, payments, notifications |
61
+ | `booking.booking.create` | POST | `/api/maggie/booking/bookings.json` | Manager-created booking |
62
+ | `booking.booking.transition` | POST | `/api/maggie/booking/bookings/{id}/transition.json` | Check-in, complete, cancel, no-show |
63
+ | `booking.booking.no-show-fee` | POST | `/api/maggie/booking/bookings/{id}/no-show-fee.json` | Explicitly charge a consented, policy-derived no-show fee |
64
+ | `booking.booking.reschedule` | POST | `/api/maggie/booking/bookings/{id}/reschedule.json` | Preview and apply a reschedule |
65
+ | `booking.availability.read` | GET | `/api/maggie/booking/availability.json` | Calculate valid slots |
66
+ | `booking.holds.create` | POST | `/api/maggie/booking/holds.json` | Create customer/manager hold |
67
+ | `booking.holds.release` | POST | `/api/maggie/booking/holds/{id}/release.json` | Release a hold explicitly |
68
+ | `booking.customers.read` | GET | `/api/maggie/booking/customers.json` | Search customers within scope |
69
+ | `booking.customer.read` | GET | `/api/maggie/booking/customers/{id}.json` | Customer profile and safe history |
70
+ | `booking.catalog.read` | GET | `/api/maggie/booking/catalog.json` | Services, variants, policies, readiness |
71
+ | `booking.catalog.write` | POST | `/api/maggie/booking/catalog.json` | Create/update catalog draft |
72
+ | `booking.packages.read` | GET | `/api/maggie/booking/packages.json` | Tenant-scoped prepaid treatment package catalogue |
73
+ | `booking.package.write` | POST | `/api/maggie/booking/packages.json` | Create/update package price, expiry, and included treatments |
74
+ | `booking.customer-packages.read` | GET | `/api/maggie/booking/customer-packages.json` | Read tenant/customer package balances and remaining visits |
75
+ | `booking.customer-package.grant` | POST | `/api/maggie/booking/customer-packages.json` | Grant a package entitlement to an existing customer |
76
+ | `booking.locations.read` | GET | `/api/maggie/booking/locations.json` | Tenant locations and setup state |
77
+ | `booking.location.write` | POST | `/api/maggie/booking/locations.json` | Create/update location configuration |
78
+ | `booking.staff.read` | GET | `/api/maggie/booking/staff.json` | Staff and eligibility |
79
+ | `booking.staff.write` | POST | `/api/maggie/booking/staff.json` | Create/update staff configuration |
80
+ | `booking.resources.read` | GET | `/api/maggie/booking/resources.json` | Resources and requirements |
81
+ | `booking.resources.write` | POST | `/api/maggie/booking/resources.json` | Create/update resource configuration |
82
+ | `booking.schedule.read` | GET | `/api/maggie/booking/schedule.json` | Hours, shifts, blocks, closures |
83
+ | `booking.schedule.write` | POST | `/api/maggie/booking/schedule.json` | Save a validated schedule change |
84
+ | `booking.payments.read` | GET | `/api/maggie/booking/payments.json` | Payment attempts, transactions, refunds |
85
+ | `booking.payment.start` | POST | `/api/maggie/booking/payments/start.json` | Start a normalized payment attempt |
86
+ | `booking.payment.reconcile` | POST | `/api/maggie/booking/payments/{id}/reconcile.json` | Request provider read/reconciliation |
87
+ | `booking.refund.start` | POST | `/api/maggie/booking/refunds.json` | Start a full or partial refund |
88
+ | `booking.notifications.read` | GET | `/api/maggie/booking/notifications.json` | Inspect redacted Resend delivery state |
89
+ | `booking.notification.replay` | POST | `/api/maggie/booking/notifications/{id}/replay.json` | Replay one dead-letter notification with an audited reason |
90
+ | `booking.payment-health.read` | GET | `/api/maggie/booking/payment-health.json` | Provider config and capability summary |
91
+ | `booking.payment-health.verify` | POST | `/api/maggie/booking/payment-health.json` | Server-side Stripe account verification; owner/manager may submit credentials once, which are encrypted at rest |
92
+ | `booking.settings.read` | GET | `/api/maggie/booking/settings.json` | Policy and integration settings, redacted |
93
+ | `booking.settings.update` | PATCH | `/api/maggie/booking/settings.json` | Save non-secret settings |
94
+ | `booking.audit.read` | GET | `/api/maggie/booking/audit.json` | Booking-scoped audit timeline |
95
+ | `booking.events.read` | GET | `/api/maggie/booking/events.json` | Outbox/reconciliation operational view |
96
+ | `booking.runtime.read` | GET | `/api/maggie/booking/runtime.json` | Sanitized screen/runtime evidence |
97
+ | `booking.provider.webhook` | POST | `/api/maggie/booking/webhooks/{provider}` | Server-only verified provider event ingress |
98
+
99
+ `booking.payment-health.verify` accepts `{ "provider": "stripe" }` for a
100
+ deployment-managed connection. An owner or manager may instead include
101
+ `secretKey` and `webhookSecret` in the same HTTPS request. The host verifies
102
+ the pair before sealing it with `BOOKING_TOKEN_SECRET`; the values are never
103
+ returned, logged, or included in the redacted payment-health response.
104
+
105
+ ### Booking permission registry
106
+
107
+ The administrator-managed Team access contract exposes the complete
108
+ server-enforced capability list: `calendar.read`, `bookings.read`,
109
+ `bookings.manage`, `customers.read`, `waitlist.read`, `waitlist.manage`,
110
+ `catalog.read`, `catalog.manage`, `packages.read`, `packages.manage`,
111
+ `staff.read`, `staff.manage`, `resources.read`, `resources.manage`,
112
+ `schedule.read`, `schedule.manage`, `locations.read`, `locations.manage`,
113
+ `payments.read`, `payments.manage`, `refunds.manage`, `notifications.read`,
114
+ `notifications.manage`, `settings.read`, `settings.manage`, `reports.read`,
115
+ and `audit.read`. The UI receives the registry from `/access.json`; the route
116
+ handler applies it server-side, so a hidden UI control cannot grant or bypass
117
+ access. Owners and managers retain the full surface, while staff and finance
118
+ accounts require explicit capability entries.
119
+
120
+ Webhook routes are not called by the browser and should be separate from the
121
+ session-authenticated dashboard endpoint:
122
+
123
+ ```text
124
+ POST /api/maggie/booking/webhooks/{provider}
125
+ ```
126
+
127
+ ### Public customer routes
128
+
129
+ The eleven public routes are versioned separately in
130
+ `MaggieDash/contracts/booking-customer-surface-v1.json`:
131
+
132
+ | ID | Method | Route |
133
+ |---|---|---|
134
+ | `booking.public.catalog.read` | GET | `/api/maggie/booking/public/catalog.json` |
135
+ | `booking.public.availability.read` | GET | `/api/maggie/booking/public/availability.json?serviceVariantId={serviceVariantId}&locationId={locationId}&date={date}` |
136
+ | `booking.public.hold.create` | POST | `/api/maggie/booking/public/holds.json` |
137
+ | `booking.public.checkout.start` | POST | `/api/maggie/booking/public/checkout.json` |
138
+ | `booking.public.payment-return.read` | GET | `/api/maggie/booking/public/payment-return.json` |
139
+ | `booking.public.manage.read` | GET | `/api/maggie/booking/public/manage.json?token={token}` |
140
+ | `booking.public.booking-cancel` | POST | `/api/maggie/booking/public/bookings/{id}/cancel.json` |
141
+ | `booking.public.booking-reschedule` | POST | `/api/maggie/booking/public/bookings/{id}/reschedule.json` |
142
+ | `booking.public.waitlist.join` | POST | `/api/maggie/booking/public/waitlist.json` |
143
+
144
+ The public handler sets `no-store` and `X-Robots-Tag: noindex`, requires an
145
+ idempotency key for writes, and fails closed if the host cannot bind a tenant.
146
+ It returns only the redacted customer DTOs and payment-return states; a
147
+ redirect cannot mark a payment paid. Use the existing outbox adapter for
148
+ confirmation, cancellation, reschedule, and reminder email intents. The host
149
+ stores customer token purpose explicitly: payment-return tokens are short-lived
150
+ and the Resend worker uses a separate 30-day sealed `manage` token for links.
151
+
152
+ For a deterministic end-to-end public journey, run:
153
+
154
+ ```bash
155
+ npm run booking:customer-reference-host:test
156
+ ```
157
+
158
+ This wraps the reference state with the public customer dispatcher and verifies
159
+ hold replay, checkout-to-pending recovery, token-bound cancellation, manager
160
+ session isolation, and notification intents. It is test evidence, never a
161
+ production customer or payment host.
162
+
163
+ ## 3. Response shapes
164
+
165
+ Overview:
166
+
167
+ ```json
168
+ {
169
+ "date": "2026-09-20",
170
+ "timezone": "Europe/London",
171
+ "metrics": {
172
+ "bookings": 0,
173
+ "revenueMinor": 0,
174
+ "currency": "GBP",
175
+ "noShows": 0,
176
+ "balanceDueMinor": 0
177
+ },
178
+ "providerHealth": [],
179
+ "readiness": { "bookable": false, "checks": [] },
180
+ "nextBookings": [],
181
+ "correlationId": "corr_..."
182
+ }
183
+ ```
184
+
185
+ Availability:
186
+
187
+ ```json
188
+ {
189
+ "query": {
190
+ "locationId": "loc_1",
191
+ "serviceVariantId": "variant_1",
192
+ "date": "2026-09-25",
193
+ "timezone": "Europe/London"
194
+ },
195
+ "slots": [
196
+ {
197
+ "startAt": "2026-09-25T09:00:00Z",
198
+ "endAt": "2026-09-25T10:00:00Z",
199
+ "localLabel": "10:00",
200
+ "staffIds": ["staff_1"],
201
+ "resourceIds": ["room_1"]
202
+ }
203
+ ],
204
+ "warnings": [],
205
+ "correlationId": "corr_..."
206
+ }
207
+ ```
208
+
209
+ Booking detail must include booking status and payment status separately, plus
210
+ segments, allocations, safe timeline events, payment summary, allowed actions,
211
+ and capability flags.
212
+
213
+ ## 4. Request rules
214
+
215
+ - Mutations require a same-origin session and a role permission.
216
+ - Mutations require `Idempotency-Key`; missing keys return `400`.
217
+ - Requests carry `X-Correlation-Id` or receive a server-generated one.
218
+ - JSON mutating requests declare `content-type: application/json`.
219
+ - Server validates all IDs against tenant/location scope.
220
+ - Server ignores client-supplied role, amount, currency, status, and provider
221
+ capability claims.
222
+ - Mutations return the canonical persisted result, not the input echo.
223
+ - Errors are safe, bounded, and do not include SQL, stack traces, provider
224
+ secrets, or raw webhook payloads.
225
+
226
+ ### Role-specific route boundary
227
+
228
+ The shared route handler enforces the coarse role boundary and any explicit
229
+ capabilities supplied on the session, while the host supplies the
230
+ session-derived tenant, location, and assignment scope:
231
+
232
+ - `staff` may read operational booking routes and transition assigned work to
233
+ `checked_in`, `in_progress`, `completed`, or `no_show`.
234
+ - `staff` must be denied payment routes, payment-health details, customer
235
+ directory routes, configuration writes, and all other mutations.
236
+ - `finance` may operate payment/refund routes and payment health, but does not
237
+ gain customer or configuration administration by implication.
238
+ - The host must filter staff results to permitted locations and assignments
239
+ before the service returns list or detail DTOs. The shipped PostgreSQL
240
+ repository applies the standard `staff_id` assignment filter; custom host
241
+ repositories and reporting endpoints must preserve the same invariant.
242
+
243
+ The source validator covers the coarse policy. A production host must add
244
+ authenticated route and browser evidence proving its narrower tenant/location
245
+ and assignment queries.
246
+
247
+ The MaggieDash source includes a provider-neutral service seam in
248
+ `backend/booking/request.mjs`, `dto.mjs`, and `service.mjs`. It is deliberately
249
+ repository/transaction injected: the host supplies the PostgreSQL repository,
250
+ session-derived project and role, clock, and provider adapter. The service
251
+ returns canonical DTOs and the versioned safe error object; it does not import a
252
+ database driver or payment SDK.
253
+
254
+ ## 5. Capability and feature flags
255
+
256
+ ```json
257
+ {
258
+ "booking": {
259
+ "nativeAvailability": true,
260
+ "nativeBooking": true,
261
+ "waitlist": true,
262
+ "resources": true
263
+ },
264
+ "payment": {
265
+ "provider": "stripe",
266
+ "onlinePayment": true,
267
+ "refunds": true,
268
+ "partialRefunds": true,
269
+ "terminal": false,
270
+ "savedPaymentMethod": false
271
+ }
272
+ }
273
+ ```
274
+
275
+ Capabilities describe configured and verified behavior. They do not mean that
276
+ an SDK is installed. A missing capability must result in a safe disabled state,
277
+ not an invented UI action.
278
+
279
+ ## 6. Conformance evidence
280
+
281
+ Add `booking.*` endpoints to a future version of the host-adapter contract and
282
+ capture sanitized observations with the existing `maggie dash conformance`
283
+ pattern. The evidence must include method, route, status, content type,
284
+ required fields, and `passed`, but never cookies, authorization headers,
285
+ provider payloads, or customer contact data.
286
+
287
+ The release gate should also verify:
288
+
289
+ - all booking screens mounted;
290
+ - no public booking/admin route is indexable accidentally;
291
+ - auth redirects work;
292
+ - database migration version is current;
293
+ - provider health is truthful;
294
+ - payment fixtures and webhook fixtures pass;
295
+ - browser screenshots have no overflow or console errors.
296
+
297
+ ## 7. Local reference host
298
+
299
+ MaggieDash includes a secret-free, in-memory reference host for contract and
300
+ browser development. It is not a production database adapter and must never be
301
+ used to serve real customer or payment traffic.
302
+
303
+ From the MaggieDash source repository:
304
+
305
+ ```bash
306
+ npm run booking:reference-host:test
307
+ npm run booking:reference-host -- --port 4175
308
+ ```
309
+
310
+ The validator exercises all 47 endpoint IDs, required response fields,
311
+ email/password-session presence, project scope, role scope, idempotent replay,
312
+ provider webhook authentication, and fixture redaction. The local server is
313
+ useful for wiring a browser route before a host supplies PostgreSQL and real
314
+ provider adapters.
@@ -0,0 +1,227 @@
1
+ # ORA Wellness Booking integration audit
2
+
3
+ Date: 2026-09-21
4
+ Project: `/home/balalior/Dev/clients/orawellness.uk`
5
+ Source: MaggieDash Booking `0.2.8` plus ORA host adapter
6
+
7
+ ## Short answer
8
+
9
+ The host now has the main Fresha-style foundation: manager workspace, services,
10
+ staff, resources, working hours, availability, holds, bookings, customer
11
+ tokens, Stripe payment boundary, Resend notification outbox, audit records,
12
+ email/password login, and separate Booking roles.
13
+
14
+ It is not production-ready yet. The remaining work is deployment evidence and
15
+ provider operations, not another UI shell.
16
+
17
+ The ORA `.env` currently contains a Stripe test secret under the existing
18
+ `ST_SECRECT_KEY` compatibility name and a publishable test key under
19
+ `ST_PUB_KEY`. The secret value is intentionally not recorded here. No
20
+ `STRIPE_WEBHOOK_SECRET` is configured yet, so the account is not considered
21
+ verified or connected for Booking.
22
+
23
+ Current database gate: the existing ORA application schema check passes and the
24
+ Booking migration dry-run passes transactionally, but the live Booking schema
25
+ has not been applied. The 2026-09-21 read-only preflight confirmed that the
26
+ core schema exists while `maggiedash_booking_allocations` and
27
+ `maggiedash_booking_user_roles` are still absent. The worker therefore fails
28
+ closed without touching production data. Do not enable the live dashboard or
29
+ scheduler until the owner approves the migration, verifies the backup/restore
30
+ path, creates the first owner, and captures runtime evidence.
31
+
32
+ ## Verified in the codebase
33
+
34
+ | Capability | Evidence | State |
35
+ |---|---|---|
36
+ | Manager dashboard | `/_maggie/booking`, `_maggie/booking/booking.tsx` | Installed |
37
+ | Traditional authentication | `src/lib/maggie/auth.ts`, registration and login routes | Installed |
38
+ | Booking roles | `maggiedash_booking_user_roles`, Staff access panel, complete server-enforced capability registry for calendar/bookings/customers/waitlist/catalogue/packages/staff/resources/schedule/locations/payments/refunds/notifications/settings/reports/audit | Installed; explicit staff/finance grants and safe legacy defaults covered by BK-101 |
39
+ | Staff account lifecycle | Booking Staff panel creates accounts, sends Resend invitations, supports one-time password setup and password reset | Installed; real delivery/browser proof pending |
40
+ | Staff data scope | Linked `staff_id` passed into the server context and filtered in the repository | Installed; host migration/staging proof pending |
41
+ | Services/treatments | Searchable catalogue with editable service/variant details, payment policy, price, preparation/cleanup buffers, active/inactive state, manager multi-treatment appointments, public multi-treatment holds/checkout, and live service/location selectors | Installed; legacy allocation backfill and staging data verification pending |
42
+ | Treatment packages | Tenant-scoped manager catalogue, manager-granted entitlements, public package checkout/payment return and fully covered public customer redemption, webhook fulfillment, balance reads, expiry checks, atomic redemption, cancellation-safe package-credit restoration, guarded refunds, and package confirmation/refund Resend outbox events | Installed locally; real Stripe/DB migration, webhook, Resend, and staging delivery proof pending |
43
+ | Locations | Tenant-scoped Locations screen and `locations.json` route for first-location setup, timezone, locale, address, active state, and online-booking controls; public catalogue exposes all active online-booking locations | Installed; staging data verification pending |
44
+ | Staff/resources | Editable staff profiles, service/location assignments, bookable state, resources, capacity, resource service assignments, and overlap constraints | Installed; staging data verification pending |
45
+ | Calendar/availability | Day/week calendar, working hours, shifts, time off, closures, holds | Installed |
46
+ | Booking defaults | Settings screen edits venue timezone/currency, pauses new booking writes, and selects automatic/manual capture policy | Installed; staging policy verification pending |
47
+ | Stripe | Injected SDK gateway, account capability row, signed webhook boundary | Host-wired; staging proof pending |
48
+ | Resend | Notification outbox plus `scripts/maggie-booking-worker.mjs` dispatcher, including a separate 30-day sealed customer-manage link | Host-wired; scheduled delivery proof pending; worker waits for Booking schema |
49
+ | Notification operations | Tenant-scoped Notifications screen, redacted delivery-state list, and owner/manager-only dead-letter replay with reason/idempotency/audit controls | Installed; ORA validators/build passed; real delivery proof pending |
50
+ | Public self-booking | `/_maggie/booking/book`, catalog/location selector, location-scoped combined-duration availability, multi-treatment hold/checkout, return, token-bound segment-safe reschedule/cancel, and 30-day customer-manage history | Installed; staging proof pending |
51
+ | Waitlist | Public no-slot join, tenant-scoped manager queue, manual notify/cancel/priority actions, transactional conversion to a linked booking, priority/FIFO worker matching, and `booking.waitlist.available` Resend intent | Installed; explicit worker scope, real migration, scheduler, and delivery proof pending |
52
+ | Reports | `/reports.json` plus Booking Reports screen with period/service/staff/location breakdowns | Installed; staging data verification pending |
53
+ | Bookability readiness | Overview reports active location, catalogue variant, assigned bookable staff, working hours, overall bookable state, and payment capability | Installed; staging data verification pending |
54
+ | Customer history | Searchable tenant-scoped manager directory plus token-bound public customer-manage history with redacted appointment summaries | Installed; staging data verification pending |
55
+ | Schedule rules | Searchable/editable working hours, staff shifts, time off, and location closures through the audited schedule route | Installed; staging data verification pending |
56
+ | 24-hour reminders | Worker queues one idempotent `booking.reminder` email into the Resend outbox for each eligible confirmed booking | Installed; scheduled Resend delivery evidence pending |
57
+ | Payment policy and balance | Service-level full/deposit/pay-later/no-payment policy, purpose-labelled attempts, paid/balance projection, and refund projection | Installed; migration and Stripe staging evidence pending |
58
+ | Payment truth | Verified webhook/provider read projects payment and booking state | Implemented; Stripe event test pending |
59
+ | Legacy `/book` | Request-by-email flow | Kept as fallback |
60
+
61
+ ## Fixes made during this audit
62
+
63
+ 1. Public catalogue now returns all active online-booking locations plus a
64
+ backwards-compatible first `locationId`. The browser displays the tenant
65
+ locations, scopes availability to the selected location, and posts that
66
+ selected ID instead of using the fake `location-1` fallback.
67
+ 2. Public origin and rate-limit failures now return safe 403/429 responses.
68
+ 3. Stripe account status and capabilities are upserted into
69
+ `maggiedash_booking_payment_accounts`; no secret value is stored there.
70
+ 4. Webhook records store a SHA-256 payload hash instead of using the provider
71
+ event ID as a misleading hash.
72
+ 5. Customer cancellation queues the Booking notification through the same
73
+ Resend outbox.
74
+ 6. Customer rescheduling now uses the same sealed token, transactional
75
+ allocation conflict checks, idempotent replay, and `booking.rescheduled`
76
+ Resend outbox path as manager rescheduling.
77
+ 7. Customer checkout now creates a short-lived payment-return token and a
78
+ separate 30-day `manage` token. The Resend worker reuses or creates the
79
+ manage token for booking notifications without storing a raw token in the
80
+ outbox.
81
+ 8. Verified payment events now project `pending_payment` to `confirmed` and
82
+ `paid`, or cancel failed payment bookings and release their allocations,
83
+ before the worker acknowledges the event. Confirmation/cancellation
84
+ notifications are then queued once.
85
+ 9. Booking Staff can now create an email/password account directly, link its
86
+ staff profile, assign permissions, and resend a secure invitation without
87
+ using a separate People screen.
88
+ 10. Added the `/_maggie/reset-password` middleware rewrite so invitation and
89
+ password-reset links resolve to the Astro reset page.
90
+ 11. Added a manager Overview setup checklist that reads the existing payment
91
+ health response, shows Stripe status and test/live mode, and provides a
92
+ copyable webhook URL without exposing provider secrets.
93
+ 12. Fixed the installed UI validator to resolve ORA's `_maggie/booking`
94
+ workspace instead of assuming a source-package `maggiedash/booking/src`
95
+ directory.
96
+ 13. Added provider-neutral automatic waitlist matching. The worker matches one
97
+ eligible waiting customer per explicit service/location slot, persists the
98
+ offered interval, and queues an idempotent Resend notification without
99
+ auto-reserving the appointment.
100
+ 14. Added the public `GET /api/maggie/booking/public/manage.json` history
101
+ surface. The existing 30-day Resend manage token now resolves the current
102
+ customer's tenant-scoped appointments through a redacted DTO; payment
103
+ tokens and manager credentials are not accepted by this endpoint.
104
+ 15. Added manager multi-treatment appointments. The form can compose up to 12
105
+ service segments, while the host validates duration, availability, shared
106
+ location/currency, per-segment staff/resource allocation, and persists the
107
+ segments and allocations atomically with the booking.
108
+ 16. Added public multi-treatment booking and segment-safe rescheduling. Customer
109
+ holds persist `segments_json`, checkout sums all treatment prices, and both
110
+ customer and manager rescheduling shift each segment/allocation together
111
+ while checking conflicts independently and preserving the total duration.
112
+ 17. Removed install-time `location-1`/`service-1` assumptions. Catalog and
113
+ schedule reads now return tenant locations; manager forms derive defaults
114
+ from those responses, and resource writes persist service assignments.
115
+ 18. Added tenant-scoped location management so a blank project can create its
116
+ first venue before configuring services, staff, resources, and schedules.
117
+ The same audited location contract is mirrored in ORA's installed Booking
118
+ workspace.
119
+ 19. Fixed a runtime catalogue query that referenced the nonexistent
120
+ `service_variants.created_at` column. Variant reads now use stable existing
121
+ columns for ordering. Hardened the ORA initial catalogue seed so a partial
122
+ retry reuses matching services and upserts variants instead of creating
123
+ duplicate services.
124
+ 20. Closed the treatment catalogue UI parity gap: the manager can now manage
125
+ every variant under a service, including duration, price, currency, and
126
+ active state, while preserving the existing idempotent backend write.
127
+
128
+ ## Installer productization update
129
+
130
+ The MaggieDash distribution now declares an Astro host bootstrap. New Astro
131
+ projects can use:
132
+
133
+ ```bash
134
+ maggie booking install --project . --confirm
135
+ ```
136
+
137
+ The installer adds missing Booking routes, email/password registration/login,
138
+ PostgreSQL/Stripe adapter wiring, public booking route, middleware scaffold,
139
+ schema command, Resend worker, and `.env.maggie-booking.example`. Existing
140
+ host files are preserved. ORA already has host-owned versions of these files,
141
+ so a repeat install should preserve ORA's middleware, auth, and adapter rather
142
+ than overwrite them. Existing Astro middleware in either the full-context or
143
+ common destructured-context form now receives the idempotent rewrite block;
144
+ unknown middleware shapes remain fail-closed and are reported for manual review
145
+ before the Booking URL is exposed.
146
+
147
+ For hosts that use the installed Resend outbox and reminder worker, the CLI can
148
+ also generate a reviewed scheduler artifact:
149
+
150
+ ```bash
151
+ maggie booking install --project . --confirm --bootstrap --schedule systemd
152
+ ```
153
+
154
+ The command writes the systemd service/timer under `deploy/` but does not
155
+ enable or start it. Production still requires an approved service user,
156
+ migration, backup/restore, alert routing, and authenticated runtime evidence.
157
+
158
+ ## Release blockers
159
+
160
+ | Priority | Work | Why it matters | Owner |
161
+ |---|---|---|---|
162
+ | P0 | Apply `maggiedash-booking-install.sql` and host role migration on staging | Current ORA database check shows core MaggieDash tables exist, but Booking and Booking-role tables are not installed | ORA deployment |
163
+ | P0 | Release the current MaggieDash source used by the default installer | The public `9d99de7` source is a validated `0.2.8` baseline, but the current 47-route/no-show changes remain uncommitted in the working tree | MaggieDash release owner |
164
+ | P0 | Configure the Stripe webhook secret and verify the existing test account; keep `BOOKING_TOKEN_SECRET` and Resend sender available | The test secret is present through `ST_SECRECT_KEY`, but signed webhook verification and connected readiness remain unavailable | ORA deployment |
165
+ | P0 | Run worker every minute with alerting | Holds, payment projections, and Resend delivery otherwise remain pending; `maggie booking worker-schedule` now generates the reviewed systemd/cron artifact, but host enablement and alert routing remain pending | ORA operations |
166
+ | P0 | Capture authenticated runtime/browser/ops evidence | Local build and reference fixtures cannot prove the real host | ORA + release owner |
167
+ | P1 | Run Stripe test-mode scenarios | Confirm success, failure, delayed/duplicate webhook, and refund behavior against the actual account | ORA + Stripe |
168
+ | P1 | Capture Resend invitation/reset evidence | Booking notifications are wired; staff account invitation and password reset now use the same server-side Resend configuration | ORA + release owner |
169
+ | P1 | Capture reminder delivery evidence | The worker now enqueues reminders; staging must prove scheduler timing, Resend acceptance, retry, and no duplicate send | ORA + release owner |
170
+ | P1 | Verify customer-manage links in real Resend emails | Staging must prove the 30-day link opens the noindex customer page and reschedule/cancel remain token-bound | ORA + release owner |
171
+ | P1 | Verify waitlist notification delivery and conversion workflow | Staging must prove queue scope, one-time notification behavior, Resend acceptance, conflict handling, and the linked booking/confirmation email | ORA + product owner |
172
+ | P1 | Switch marketing CTAs from `/book` to `/_maggie/booking/book` | Avoid sending customers to the new flow before staging proves it | Product owner |
173
+ | P2 | Add richer Fresha features | Package purchase/refund paths are implemented locally. Memberships, gift cards, advanced multi-location staff rules, and customer-side package/membership pricing remain roadmap items. Customer self-service history, bounded automatic waitlist matching, and segment-safe multi-treatment rescheduling still need real host delivery proof | Product roadmap |
174
+
175
+ ## Evidence already run
176
+
177
+ - ORA `npm run build`: passed with no errors, warnings, or hints;
178
+ the Stripe setup checklist is included in the built Booking workspace.
179
+ - ORA `npm audit --omit=dev --audit-level=high`: passed with zero
180
+ vulnerabilities after refreshing the Cloudflare/Wrangler lockfile chain.
181
+ - ORA `maggie booking inspect --project .`: passed all installed workspace,
182
+ contract, schema, customer, worker, and ops checks.
183
+ - ORA installed UI and customer UI validators: passed after resolving the
184
+ `_maggie/booking` workspace path.
185
+ - Central and ORA Booking UI validators now also reject fixture location/service
186
+ IDs in the installed manager source; both copies passed.
187
+ - Central and ORA location configuration, service-contract, route-handler, and
188
+ reference-host validators now cover the 47-route manager surface; both
189
+ installed UI copies passed.
190
+ - ORA worker/runtime regression: passed for waitlist priority/FIFO matching,
191
+ one-time offered-slot persistence, and idempotent replay.
192
+ - ORA customer reference-host regression: passed public multi-treatment
193
+ availability, hold/checkout, and token-bound multi-treatment rescheduling;
194
+ the PostgreSQL core regression also passed segment-safe rescheduling.
195
+ - MaggieDash customer-flow, customer-UI, runtime-plan, worker-repository, and
196
+ syntax checks: passed.
197
+ - ORA `maggie booking release-gate --project .`: static contract/workspace gate
198
+ passed; runtime, browser, ops, and board evidence were not supplied.
199
+ - ORA `maggie booking setup --project .`: dependencies, database URL, public
200
+ URL, Booking token secret, Resend sender configuration, and a Stripe test
201
+ secret alias are present; the missing webhook secret keeps Stripe in pending
202
+ verification, while schema, first owner, and worker schedule remain explicit
203
+ verification steps.
204
+ - Full required release gate was run read-only on 2026-09-21 and correctly
205
+ returned `blocked` for the missing runtime, browser, ops, and unfinished-board
206
+ evidence. It did not run migrations, create bookings, send email, or deploy.
207
+ - ORA `npm run booking:schema -- --check`: `needs-migration` with core present,
208
+ Booking absent, and Booking access absent. This command was read-only; no
209
+ database migration was applied.
210
+ - Disposable local ORA Astro runtime: first-owner registration HTTP 201,
211
+ password login HTTP 200, authenticated overview/settings/catalog/staff HTTP
212
+ 200, and public catalog HTTP 200 against a temporary PostgreSQL database.
213
+ This caught the variant ordering and partial-seed defects above; it is not
214
+ production or staging evidence.
215
+ - Central and ORA PostgreSQL core integrations now persist two treatment
216
+ variants, assert expanded allocation ranges after rescheduling, and reject a
217
+ buffer-overlapping adjacent booking. The reference hosts and customer
218
+ cursors also apply the same rule. The one-time
219
+ `schema/maggie-booking-buffer-backfill.sql` migration is included but still
220
+ needs staging/owner approval; no live ORA database was changed.
221
+
222
+ ## Decision
223
+
224
+ Do not market this as a complete Fresha replacement yet. It is a valid Booking
225
+ foundation and installable host integration. The next safe step is staging
226
+ migration plus real Stripe/Resend/browser evidence, followed by a canary before
227
+ changing the public CTA.