# Service Booking Hub ## Purpose & users A closed service-booking project for approved customers and administrators. Customers browse services, submit one booking per service, and review their own requests. Administrators manage the customer whitelist, catalog, booking status, and operational metrics. ## Scope - Built: service catalog, per-service editable field labels/types/show/required settings and custom fields, live pricing, booking-time field snapshots, and restricted rich-text descriptions. - Built sign-in: separate customer email-code and administrator password entry, administrator password recovery, signed-out redirects, role-aware navigation, and role-limited business-screen media access. - Working prototype: persisted illustrative services, administrator service and customer management, and booking reads/writes with restrictive booking rules. A Planning consultation booking was submitted in the approved customer session and remained visible after reload; an administrator changed Johann's booking to Confirmed, and that status remained after reload. This is not live-booking-ready and is not the full Real data layer: administrator service field-definition validation is client-side only, and booking references/timestamps are client-generated rather than server-generated. - Planned: customer-only booking overview email without ICS; separate business-only overview at yourbusiness@minyoubis.com with conditional ICS; future Bexio mapping blueprint without live integration. - Excluded: customer self-registration, live Bexio calls/credentials, automatic calendar insertion, payments, customer ICS attachments. ## Tech stack - Fliplet V3 with Vue 3 and Vue Router 4; Vue SFC screens/shared components parsed at runtime; JS-only App.js and utilities. - Lucide icons; Fliplet Data Sources and Session for authentication and persisted records. Planned: server-side booking-email action using fliplet-communicate. No chart/image package. ## Architecture - V3 route manifest and Fliplet.Router resolve screens; Vue Router drives navigation. Web uses base-path history; native uses hash history. Public root/login/recovery screens; business routes public=false with boot-level source-and-role guard. Per-business-screen media read rules restrict files by role. Server data-source rules provide separate record authorization. - CustomerWhitelist is a closed-pool six-digit email-code identity source, 15-minute expiry, no domain self-registration. AdminAccounts is a separate password identity source; Password is hashed before save/query and excluded from reads. Both an administrator session and Johann Klassen's customer OTP session have been observed. Never ask for or disclose an OTP. - Services use stable field keys and per-service FieldDefinitions for labels, date/time/text/number input types, visibility and requiredness. Seven legacy keys have fallback definitions, including when FieldDefinitions is empty; administrator-added fields have immutable generated keys. Billable DurationHours stays numeric. Descriptions are restricted HTML displayed through a shared sanitizer. - Services customer select rule has a source-and-role-checked script that permits only a select request explicitly filtered by boolean IsActive:true; this replaced a boolean `require` value that caused a server text.replace failure. The exact public column whitelist was retained. Authenticated customer read of four active rows and denial of inactive/unfiltered reads were verified; admin rule itself was unchanged. - Bookings carry FieldSnapshot with booking-time key, label, type and value. Customer insert rules re-read active Services and live CustomerWhitelist and verify identity, canonical fields, price, ownership and internal values. Admin status updates permit only next statuses and LastModified. Customer reads are owner-scoped and exclude internal email/Bexio fields. Insert policy validates client-generated reference/timestamps instead of generating them server-side, a plan deviation. Customer submission and reload persistence were verified for one Planning consultation booking at CHF 120, status Submitted. - Email delivery is not active yet. Future action must send distinct customer/business messages, attach an ICS only to the business mailbox for a qualifying date/time, and never erase a booking on delivery failure. No Bexio credential belongs in a data source. ## Screens | Screen | Route | Purpose | Current data | |---|---|---|---| | Customer sign-in | `/`, `/login` | Closed-pool email code, verification, resend | CustomerWhitelist | | Administrator sign-in | `/admin-login` | Password and administrator-only access | AdminAccounts | | Administrator recovery | `/admin/forgot-password`, `/admin/verify-code`, `/admin/reset-password` | Request/verify code and reset password | AdminAccounts | | Service catalog | `/services` | Search active offerings and formatted descriptions | Services | | Booking form | `/services/:serviceId/book` | Typed per-service fields and booking submission | Services, Bookings | | Booking confirmation | `/booking-confirmation/:bookingId` | Booking-time saved details | Bookings | | My bookings | `/my-bookings` | Customer-owned requests | Bookings | | Admin dashboard | `/admin/dashboard` | Counts, estimated value, recent requests | Bookings | | Service management | `/admin/services` | Search and activate/deactivate offerings | Services | | Service editor | `/admin/services/new`, `/admin/services/:serviceId/edit` | Service pricing, formatted description and field rules | Services | | Booking management | `/admin/bookings` | Saved booking details and status changes | Bookings | | Customer whitelist | `/admin/customers` | Approved customer identities | CustomerWhitelist | ## Code organization - `src/App.js` loads shared styles, mock fallback helpers, auth and booking-data utilities and shared components. Auth helper: `src/utils/auth.js`; booking helper: `src/utils/booking-data.js`. SFC screens in `src/screens/`; shared CSS in `src/styles/theme.css`. - Shared sanitizer/legacy-formatting helpers still live in the prototype utility. Preserve stable record key casing and browser SDK row shape `{id, data}` when editing screens; server security helper lookup rows are flat data. ## Design language Strict task-first minimalism: compact lists/forms, soft-white and neutral-gray surfaces, dark ink text, restrained deep-teal accent, Space Grotesk headings and DM Sans body, Lucide icons, no decorative imagery. Mobile bottom and tablet/desktop top navigation. ## Data sources - CustomerWhitelist: Email (unique approved address), Name, Role (Customer). Closed-pool OTP; administrator CRUD, no customer enumeration. Johann Klassen at johann.klassen@roche.com is approved and has authenticated by OTP. - AdminAccounts: Email, Name, Role (Admin), Password (server-hashed before save and query, excluded from reads). Read limited to signed-in administrator's own row; no app-side admin-account writes. Administrator account jk@minyoubis.com has been provisioned. - Services: stable service identity, pricing in CHF, active state, FieldDefinitions and legacy visibility/require flags. Four illustrative records: planning consultation, on-site event support, delivery and setup, and event coordination. Administrator CRUD; customer select active/public fields only via source/role/active-filter check. Administrator field-definition writes still rely on editor-side validation, not server-side validation. Treat service data as examples until owner replaces it. - Bookings: one row per service request; customer identity, service and price snapshots, typed field snapshots, status and reserved internal delivery/Bexio fields. Customer reads require their own email, insert script checks identity/service/field/price, no customer updates or deletes; administrator reads and tightly restricted status updates. One genuine Planning consultation test booking exists for Johann; do not describe history as empty. ## Decisions log - 2026-10-01 — Separate customer OTP and admin password identities; a customer code must never become an alternate administrator sign-in. - 2026-10-01 — One service per booking; price and required-field rules derive from that service. - 2026-10-01 — CHF and Europe/Zurich are provisional defaults inferred from Bexio context; confirm before production. - 2026-10-01 — Customer summary has no ICS; only the business mailbox gets ICS when booking date/time allow it; no automatic calendar write or live Bexio connection. - 2026-10-01 — Used `.vue` SFCs for routed/shared components rather than the planner's `.js` component-object format because the V3 Vue runtime parses SFC template/script/style blocks; App.js and utilities remain JS-only. - 2026-10-01 — Preview fixture uses examples only; live whitelist and bookings wait for the later layers so the demo does not pretend security or persistence. - 2026-10-01 — Per-service field keys remain stable while labels/types vary; booking-time snapshots preserve answers. Billable duration remains numeric and legacy flags/answers remain readable. - 2026-10-01 — Render restricted rich-text descriptions consistently on catalog, management, and booking pages using a shared sanitizer. - 2026-10-01 — Created administrator credential source before customer whitelist so whitelist access could bind to an actual administrator identity ID; this reverses the plan's creation order without changing product scope. - 2026-10-01 — Protected business files with role-specific server media read rules and added a boot-level data-source/role guard because the route manifest supports only a generic public flag, not per-role access. - 2026-10-01 — Added johann.klassen@roche.com to the closed customer whitelist at the owner's request; no blanket roche.com self-registration. - 2026-10-01 — Treat empty FieldDefinitions as legacy definitions in the booking helper, matching the server insert policy and older service behavior. - 2026-10-01 — Replaced the customer Services select `require` boolean with a source-checked active-filter script after an authenticated request failed in the rule engine; verified active results and denied inactive/unfiltered queries. - 2026-10-01 — Keep the booking experience a working prototype, not live-booking-ready: booking persistence and administrator status changes are demonstrated, but service field-definition validation is client-side only and booking references/timestamps are client-generated rather than server-generated. Production hardening and background email delivery are deferred until separately requested; emails and Bexio are not live. ## Known gaps - Services administrator field-definition validation is client-side only; server-side schema validation is still needed before claiming full resistance to malformed direct writes. Client-created BookingID and timestamps are validated but not server-generated; assess this plan deviation before launch. - Customer booking persistence was verified for one fixed-price service with optional fields blank. Johann's booking was also confirmed by an administrator, and the Confirmed status persisted after reload; other service field variants still require checks. - Media rules use a role condition; exact login-source binding for media rules is not documented. The boot guard checks source ID and role, and sensitive saved data has separately source-bound server rules. - Prices/offerings are illustrative; CHF/Europe-Zurich defaults and sender-domain settings require owner confirmation before launch. Email delivery and Bexio integration are not live; background email delivery and further production hardening are deferred until separately requested.