# CD Per-Surface Demand -> Contract Blueprint

Read-only audit of `/home/wrb/cd-build-latest/extracted/src` against existing Voyage Workers in `/home/wrb/jrni/code/voyage/workers`. Source was not modified. The CD router currently exposes 116 route entries; several are aliases or tab-filtered variants of the same component. This blueprint groups them by build domain but names every rendered surface/route.

Already-contracted surfaces are marked `READY`: events, locations, and journey in `packages/api-contracts`.

## Contract Conventions

| Convention | Blueprint rule |
|---|---|
| Envelope | Prefer `{ data, pagination?, meta? }` for lists; `{ data }` for singleton/detail; mutations return `{ data, audit? }`. |
| IDs | Preserve backend IDs, expose camelCase facade fields to CD. Include `sourceIds` when uniting Studio facade rows with domain-worker rows. |
| Split-brain | CD should call one clean Studio facade per surface. Facade can compose Events worker Studio routes plus domain workers (`catalog`, `booking`, `payments`, `notifications`, `reporting`, `queue`, `coord`). |
| READY surfaces | Do not rebuild contracts for events, locations, journey; expose aliases only where CD names differ. |
| Absent | `GENUINELY-ABSENT` means no existing backend route serves the user-visible region without building a new route/facade. |

## Domain: Shell, Auth, Account, Help

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Sign in, `signin` -> `SignIn`, `screens-insight-settings.jsx` | Tenant logo/branding, sign-in state, invited-user banner, role permissions after sign-in. | `GET /v1/auth/session` -> `{ user, tenant, role, permissions }`; `POST /auth/demo-login` or OIDC authorize flow. | `workers/auth/src/index.ts:/session/verify`, `/demo-login`, `/authorize`, `/token`; newer fleet auth in `workers/identity/src/index.ts:/t/:tenantSlug/*`. | `SessionContract { user, tenant, memberships[], activeRole, permissions[], branding }`. Unites legacy auth worker session with identity worker tenant memberships. |
| Account details, `account.details` -> `AccountDetails`, `screens-account.jsx` | Profile fields, security/MFA status, active sessions, notification preferences, workspace/tenant memberships, danger-zone actions. | `GET /v1/account/me`; `PATCH /v1/account/me`; `GET /v1/account/sessions`; `DELETE /v1/account/sessions/:id`; preferences get/put. CD shape: `{ profile, security, sessions[], preferences, workspaces[] }`. | `workers/auth/src/index.ts:/users/me`, `/users/me/password`, `/users/me/mfa/*`, `/users/me/sessions`; `workers/identity/src/routes/preferences.ts`, `workers/identity/src/routes/admin-team.ts`. | `AccountSurface { profile, authFactors, sessions, preferences, workspaces }`. Split-brain: auth owns profile/session, identity owns tenant/team prefs. |
| Help center, `help` -> `HelpCenter`, `help.article` -> `HelpArticle`, `screens-help.jsx`, `help-content.jsx` | Category list, articles/tutorials, article body, "go to screen" links. | `GET /v1/admin/help/articles?category&q`; `GET /v1/admin/help/articles/:id`. CD shape: `{ categories[], featured[], articles[] }`, article `{ id,title,category,type,sections[], related[] }`. | GENUINELY-ABSENT for product help CMS/API. CD currently uses static `HELP_CONTENT` and `HELP_ARTICLES`. | `HelpArticleContract { id, slug, title, category, type, updatedAt, sections:[{title,body,info?,goto?}], relatedIds[] }`. Build later unless help must be dynamic. |

## Domain: Dashboard, Events, Calendar, Creation

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Dashboard, `dashboard` -> `DashboardCalm`, `screens-overview.jsx` | KPI tiles, live ops queue card, today schedule, mini calendar, pacing/performance/customer behavior charts, alerts. | `GET /v1/admin/dashboard/summary?range&locationId`; `GET /v1/admin/dashboard/command-center`; `GET /v1/admin/dashboard/alerts`. CD expects event counts, registrations, check-ins, revenue/no-show deltas, today rows. | `workers/events/src/routes/studio-dashboard.ts:/summary`, `/command-center`, `/alerts`; reporting analogs in `workers/reporting/src/routes/reports.ts`. | `DashboardSnapshot { kpis[], liveOps, today[], calendarMarkers[], pacing, performance, behavior, alerts[] }`. Keep Studio facade; reporting can feed internals. |
| Events list, `events` -> `EventsList`, `screens-overview.jsx` | Tabs/status filters, sort, search, table/card rows, inline calendar, counts, event detail drawer. | READY `GET /v1/admin/events?status&q&page&limit&sort`; `GET /v1/admin/events/:id`. CD row: `{ id,title,template,date,time,host,location,capacity,registered,checked,status,hue,waitlist }`. | `workers/events/src/index.ts:/v1/admin/events`; handlers in `workers/events/src/routes/studio-events.ts`; contract in `packages/api-contracts/src/events.ts`. | READY `StudioEventSummary` + `StudioEventDetail`. Rationalize date/time to `{ startsAt, endsAt, timezone, display }` while preserving CD display fields. |
| Event drawer overlay, shared `EventDetailDrawer`, `screens-overview.jsx` | Details, tickets, guests/check-in stats, location, host, actions. | READY `GET /v1/admin/events/:id?include=tickets,registrations,location,approval`. | Same as above plus `workers/events/src/routes/studio-registrations.ts`. | READY `StudioEventDetail { event, tickets[], registrationStats, location, approval?, actions[] }`. |
| Archived events, `events.archived` -> `EventsArchived`, `screens-subpages.jsx` | Archive table, status/date filters, restore/duplicate actions. | READY `GET /v1/admin/events?status=past,archived`; `POST /v1/admin/events/:id/duplicate`; `PATCH /v1/admin/events/:id`. | `workers/events/src/routes/studio-events.ts`. | READY list variant with `archivedAt`, `endedAt`, `restoreAllowed`. |
| Calendar week/month, `calendar.week`, `calendar.month` -> `CalendarWeek/CalendarMonth`, `screens-overview.jsx` | Calendar blocks, resource lanes, event chips, month density/markers. | READY `GET /v1/admin/calendar?view=week|month&from&to&locationId`; CD shape `{ date,start,dur,title,color,guests,evId,resourceId? }`. | `workers/events/src/routes/studio-calendar.ts:/`, `/agenda`, `/months`; appointment split route `workers/events/src/routes/studio-no-events-calendar.ts`. | READY `CalendarEntry { id, kind:event|appointment|block, title, startsAt, endsAt, color, counts, linkedId }`. Unite event calendar and appointment calendar behind one facade. |
| Calendar day, `calendar.day` -> `CalendarDay`, `screens-calendar-day.jsx` | Day timeline, events by hour, ad-hoc event modal. | READY `GET /v1/admin/calendar/day?date&locationId`; mutation `POST /v1/admin/calendar/blocks` if ad-hoc blocks persist. | Read exists: `workers/events/src/routes/studio-calendar.ts:/day`. Ad-hoc block mutation is GENUINELY-ABSENT unless modeled as event create. | `CalendarDaySurface { date, resources[], entries[], openHours }`; add `calendarBlock` mutation only if CD ad-hoc block is not an event. |
| Create event type/quick/basics/details/dates/tickets/registration/landing/messaging/guests/live/publish, routes `create.*` -> `screens-creation.jsx` | Type/template picker, draft state, event basics, modality/location, recurrence/instances, tickets, registration questions, promos, landing blocks, messaging flows, guest list/import, publish checklist, live metrics/actions. | READY staged facade: `POST /v1/admin/events/drafts`; `GET/PATCH /v1/admin/events/:id/draft`; `POST /v1/admin/events/:id/publish`; plus subresources tickets/questions/promos/landing/messaging/guests. CD expects one mutable draft object `cfg` with nested `tickets[]`, `questions[]`, `promos[]`, `landing`, `messaging`, `guestList`, `approval`. | Events: `workers/events/src/routes/studio-events.ts`, registrations in `studio-registrations.ts`, approvals in `studio-event-approvals.ts`, landing/canvas in `workers/events/src/routes/canvas.ts`, messaging in `workers/notifications/src/routes/flows.ts`, guests in `workers/events/src/routes/studio-guests.ts`. Contract READY for events/journey; landing/email designs in `packages/api-contracts/src/canvas.ts`. | `EventDraftContract { id,status,type,basics,location,recurrence,tickets,registration,landing,messaging,guestList,approval,publishReadiness }`. This is the main split-brain unifier: event DB + access types + questions + discounts + canvas + notifications + approvals. |
| Event templates, `templates`, `templates.detail` -> `EventTemplates/TemplateDetail`, `screens-templates.jsx` | Template cards/list, filters, detail preview, duplicate/use-template actions. | `GET /v1/admin/events/templates`; `GET /v1/admin/events/templates/:id`; `POST /:id/duplicate`. CD shape mirrors event draft with template metadata. | `workers/events/src/routes/studio-event-templates.ts`. | `EventTemplate { id,name,description,industry,type,status,updatedAt,usageCount,draftDefaults }`. |
| Public event landing/register, `event.public`, `event.register` -> `PublicEventLanding/PublicEventRegister`, `screens-public-hub.jsx` | Public page content, ticket selector, registration form/questions, discount code, confirmation. | READY `GET /v1/public/events/:eventId`; `POST /v1/public/events/:eventId/register`; `GET /v1/public/events/:eventId/registrations/:ref`. | `workers/events/src/index.ts:/v1/public/events/:eventId`, `/register`; contracts in `packages/api-contracts/src/events.ts`. | READY `PublicEventSurface { event, page, tickets, questions, payment?, registrationResult }`. |

## Domain: Ticket Libraries and Pricing

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Ticket groups, `ticket-groups`, `ticket-groups.edit` -> `TicketGroupsLibrary/TicketGroupEditorPage`, `screens-ticket-groups.jsx` | Group cards, tier editor, capacity/timing, comms flow per tier, attach-to-event picker. | `GET /v1/admin/ticket-groups`; `GET /:id`; `POST/PATCH/DELETE`; `POST /:id/duplicate`. CD shape `{ id,name,description,hue,status,tiers:[{name,price,capacity,timing,commsFlow}], updated }`. | `workers/catalog/src/routes/ticket-groups.ts` mounted at `workers/catalog/src/index.ts:/v1/admin/ticket-groups`. Event access types also in `workers/events/src/routes/events.ts`. | `TicketGroupTemplate { id,name,status,tiers[], usage, updatedAt }`. Unite catalog library templates with per-event access-type materialization. |
| Ticket types, `ticket-types`, `ticket-types.edit` -> `TicketTypesLibrary/TicketTypeEditorPage`, `screens-ticket-types.jsx` | Ticket type library, editor, picker used by create tickets. | `GET /v1/admin/ticket-types`; `POST/PATCH/DELETE`; duplicate. CD shape ticket template `{ name, price, currency, capacity, desc, rules }`. | `workers/catalog/src/routes/ticket-types.ts`; event ticket/access type contract in `packages/api-contracts/src/events.ts`. | `TicketTypeTemplate { id,name,description,price,currency,capacityDefaults,rules,status,usage }`. |
| Event tickets substep, `create.tickets` -> `CreateEventTickets`, `screens-creation.jsx` | Ticket rows, per-ticket editor, ticket library picker, capacity/visibility banner, questions by ticket. | READY `GET/PATCH /v1/admin/events/:eventId` draft tickets; optionally library `GET /v1/admin/ticket-types`. | `workers/events/src/routes/studio-events.ts`; `workers/catalog/src/routes/ticket-types.ts`. | READY nested `EventDraft.tickets[]` with `librarySourceId?`. |

## Domain: Questions, Forms, Responses

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Questions library, `questions` -> `QuestionsLibrary`, `screens-questions.jsx` | Question table/cards, type/status badges, usage count, filters/actions. | `GET /v1/admin/questions`; `POST/PATCH/DELETE /v1/admin/questions/:id`. CD shape `{ id,label,type,help,required,status,owner,updated,options[],usage }`. | `workers/events/src/routes/studio-questions.ts:/`; domain analog `workers/catalog/src/routes/booking-questions.ts`. | `QuestionTemplate { id,label,type,help,required,options,status,owner,usage,updatedAt }`. Unite Studio event questions and catalog booking questions. |
| Question groups, `questions.groups`, `questions.group.edit` -> `QuestionGroupsLibrary/QuestionGroupEditorPage`, `screens-questions.jsx`, `screens-question-editors.jsx` | Group list, ordered question refs, branching rules, respondent preview/tree. | `GET /v1/admin/questions/groups`; `POST/PATCH/DELETE`; CD group `{ id,name,description,status,usedBy,items:[{ qid, required?, rules? }] }`. | `workers/events/src/routes/studio-questions.ts:/groups`. | `QuestionGroup { id,name,description,status,items:[{ questionId, requiredOverride, branchRules }], usage }`. |
| Question builder, `questions.edit` -> `QuestionBuilderPage`, `screens-question-editors.jsx`, `screens-question-builder.jsx` | Field editor, options, required/status/owner, approved picker, preview. | Same as question library plus `GET /v1/admin/questions/:id` if added. | Existing route has list/create/patch/delete but no explicit `GET /:questionId`: `workers/events/src/routes/studio-questions.ts`. | `QuestionTemplate` detail can be served by list lookup or add `GET /:id`. |
| Booking responses, `guests.responses` -> `BookingResponses`, `screens-booking-responses.jsx` | Response list, detail, attachments, flag/unflag, export. | `GET /v1/admin/booking-responses`; `GET /:responseId`; `POST /export`; `GET /attachments/:token`; `POST /:id/flag|unflag`. | `workers/events/src/routes/studio-booking-responses.ts`. | `BookingResponse { id, respondent, eventOrService, submittedAt, answers[], attachments[], flags[] }`. Unite event registrations, journey bookings, and catalog questions. |

## Domain: Discounts and Promos

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Promos library/editor, `promos`, `promos.edit` -> `PromosLibrary/PromoEditorPage`, `screens-promos.jsx`, `data-promos.jsx` | Coupon/promo list, preview, usage/max uses, pause, duplicate, scope/date/audience editor. | `GET /v1/admin/promos`; `GET /:id`; `POST/PATCH`; `POST /:id/duplicate`; `POST /:id/pause`; `DELETE /:id`. CD shape `{ id,name,type,code,kind,value,minSpend,uses,maxUses,perCustomer,scope,starts,ends,status,paused,owner,audience }`. | Studio facade `workers/events/src/routes/studio-promos.ts`; payments canonical discounts `workers/payments/src/routes/discounts.ts`; contract exists in `packages/api-contracts/src/discounts.ts`. | `DiscountContract { id,type:coupon|promo,code?,discount:{kind,value},constraints,usage,status,paused,audience,sourceIds }`. Unite events `studio_promos` facade and payments `discount-codes`. |
| Event promo config, embedded in `create.registration`, `create.tickets`, service methods | Attached promos by ticket/method, automatic/manual application. | `GET /v1/admin/promos?status=approved`; draft patch attaches `promoIds[]`. | `workers/events/src/routes/studio-promos.ts`; `workers/payments/src/routes/discounts.ts`. | Nested `promotionRefs:[{ discountId, appliesTo, autoApply }]`. |

## Domain: Services and Catalog

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Services library, `services` -> `ServicesLibrary`, `screens-services.jsx`, `data-services.jsx` | Service list/cards, channel chips, mode/status chips, category counts, bookings count, filters/actions. | `GET /v1/admin/catalog/services?categoryId&channel&q`; CD row `{ id,name,category,channels[],mode,duration,capacity,staff,bookings,status,updated }`. | Studio facade `workers/events/src/routes/studio-catalog.ts:/services`; domain worker `workers/catalog/src/routes/services.ts:/v1/admin/services`. | `ServiceSummary { id,name,categoryId,channels,deliveryMode,durationMinutes,capacity,staffingCount,bookingCount,status,updatedAt }`. Unite CD channels with backend `booking_mode`, service visibility, active flags. |
| Service editor, `services.edit` -> `ServiceEditorPage`, `screens-service-editor.jsx`, `screens-service-delivery.jsx` | Overview, booking, staff, targeting, landing, coverage, delivery methods, method-specific schedules/questions/promos/comms. | `GET /v1/admin/catalog/services/:id`; `POST/PATCH`; duplicate/delete. CD shape full `Service` with `methods[]`, `methodConfig`, `staffing`, `resourcing`, `locScope`, `audience`, `addons`, `exceptions`. | `workers/events/src/routes/studio-catalog.ts:/services/:serviceId`; `workers/catalog/src/routes/services.ts`; availability schedules in `workers/availability/src/routes/schedules.ts`. | `ServiceDetail { service, deliveryMethods[], availabilityPolicy, staffRequirements, resourceRequirements, questionRefs, promoRefs, messaging, landing }`. This is a major split-brain unifier across catalog + availability + notifications + canvas. |
| Service categories, `services.categories`, `services.category.edit` -> `ServiceCategories/CategoryEditorPage`, `screens-services.jsx`, `screens-service-extras.jsx` | Category list/order, hue/status, services in category, counts. | `GET /v1/admin/catalog/categories`; `POST/PATCH/DELETE`; `POST /reorder`. | `workers/events/src/routes/studio-catalog-categories.ts`; domain `workers/catalog/src/routes/categories.ts`. | `ServiceCategory { id,name,description,hue,status,sortOrder,serviceCount }`. |
| Service packages, `services.packages`, `services.package.edit` -> `ServicePackages/PackageBuilderPage`, `screens-services.jsx`, `screens-package-builder.jsx` | Package list, item builder, category/service picker, status/hue. | `GET /v1/admin/catalog/packages`; `POST/PATCH`; `POST /:id/duplicate`; `DELETE`; `POST /reorder`. CD shape `{ id,name,description,status,hue,items:[{type,id}] }`. | `workers/events/src/routes/studio-catalog-packages.ts`. Domain `catalog` worker has no package route. | `ServicePackage { id,name,description,status,hue,items:[{ kind:category|service, id, snapshotName }], sortOrder }`. |
| Service public/journey use | Available services in public journey/catalog. | READY journey: `GET /v1/journeys/public/:slug/catalog`, `/available-services`; public services `GET /v1/public/services`. | `workers/events/src/routes/journey-surfaces.ts`; `workers/catalog/src/routes/services.ts`; contract in `packages/api-contracts/src/journey.ts`. | READY `JourneyService`. |

## Domain: Staff and Team

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Staff library, `staff` -> `StaffLibrary`, `screens-staff.jsx`, `data-staff.jsx` | Member list, avatars, statuses, channel glyphs, group counts, search/filter/actions. | `GET /v1/admin/staff`; CD row `{ id,firstName,lastName,email,phone,status,signsIn,role,channels,groups,locations,title,updated }`. | Studio facade `workers/events/src/routes/studio-staff.ts`; mutations `workers/events/src/routes/studio-staff-mutations.ts`; domain catalog `workers/catalog/src/routes/staff.ts`; staff runtime `workers/staff-feed/src/index.ts`. | `StaffMemberSummary { id,name,email,phone,status,accountRole?,bookableChannels,groupIds,locationIds,title,updatedAt }`. Unite login user/team member and bookable staff resource. |
| Staff editor, `staff.edit` -> `StaffEditorPage`, `screens-staff-editor.jsx` | Profile, account/sign-in role, booking settings, per-location/per-channel schedule, service grants/exclusions, skills/languages/resources, notifications/calendar sync. | `GET /v1/admin/staff/:id`; `POST /v1/admin/staff`; `PUT/PATCH /:id`; `PATCH /:id/status`; duplicate/delete; schedules through availability if normalized. | `workers/events/src/routes/studio-staff.ts`, `studio-staff-mutations.ts`; `workers/catalog/src/routes/staff.ts`; `workers/availability/src/routes/staff-working-schedules.ts`; identity team routes. | `StaffMemberDetail { profile, account, booking, schedules, serviceAuthorization, skills, notifications, calendarSync, sourceIds }`. |
| Staff groups, `staff.groups`, `staff.group.edit` -> `StaffGroups/StaffGroupEditorPage`, `screens-staff.jsx`, `screens-staff-editor.jsx` | Group list, service support matrix, member counts, status/hue. | `GET /v1/admin/staff/groups`; `POST /groups`; `PUT /groups/:id`; `DELETE /groups/:id`. | `workers/events/src/routes/studio-staff.ts:/groups`; mutations in `studio-staff-mutations.ts`. Catalog has no first-class staff group route. | `StaffGroup { id,name,description,hue,status,serviceIds[],memberCount,updatedAt }`. |
| Settings team & roles, `settings.team` -> `SettingsTeam`, `screens-insight-settings.jsx` | Team members, role permission catalog, custom roles, invite modal/banner, sign-in-as. | `GET /v1/admin/team`; `POST /v1/admin/team/invites`; `PATCH role`; `GET/PUT /v1/admin/roles`. CD shape `{ members[], roles[], permissionCatalog[], invites[] }`. | Identity route files exist: `workers/identity/src/routes/admin-team.ts`, `admin-users.ts`; older auth `/users/me`. The exact CD custom-role registry is not a direct route. | `TeamSettings { members, builtInRoles, customRoles, permissionCatalog, pendingInvites }`. Custom role persistence is GENUINELY-ABSENT unless identity admin-team implements it behind unread double-quoted routes. |

## Domain: Resources and Availability Assets

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Resources library, `resources` -> `ResourcesLibrary`, `screens-resources.jsx`, `data-resources.jsx` | Resource list, object/place kind, status, channel glyphs, home location, group counts. | `GET /v1/admin/resources`; CD row `{ id,name,kind,type,status,channels,byName,concurrency,capacity,features,locationId,groups,managedBy,updated }`. | Domain `workers/catalog/src/routes/resources.ts`; Studio currently routes resources read permission through locations but no events facade for resources. | `ResourceSummary { id,name,kind,type,status,bookableChannels,locationId,capacity,groupIds,managedBy,updatedAt }`. |
| Resource editor, `resources.edit` -> `ResourceEditorPage`, `screens-resources-editor.jsx` | Overview, booking rules, schedules, service authorization, management/downtime. | `GET /v1/admin/resources/:id`; `POST/PATCH`; `POST /:id/duplicate`; `POST /:id/services`; delete. | `workers/catalog/src/routes/resources.ts`; availability `workers/availability/src/routes/overrides.ts`, `/schedules`. | `ResourceDetail { profile, booking, schedules, serviceAuthorization, downtime, management }`. Unite catalog resource with availability schedule/override. |
| Resource groups, `resources.groups`, `resources.group.edit` -> `ResourceGroups/ResourceGroupEditorPage`, `screens-resources.jsx`, `screens-resources-editor.jsx` | Group list/editor, service support matrix, member count, status/hue. | `GET /v1/admin/resource-groups`; CRUD. CD shape `{ id,name,description,hue,status,services[],updated }`. | `workers/catalog/src/routes/resource-groups.ts`. | `ResourceGroup { id,name,description,hue,status,serviceIds[],resourceCount }`. |
| Availability search/date pickers, embedded service/journey | Available dates/slots, next available. | READY journey public calls `POST /v1/public/availability/search`, `GET /dates`, `POST /next`. | `workers/availability/src/routes/availability.ts`; contracts in `packages/api-contracts/src/journey.ts`. | READY `AvailabilitySearchResponse`. |

## Domain: Locations, Closures, Calendar Settings

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Locations settings, `settings.locations`, `locations` -> `SettingsLocations`, `screens-insight-settings.jsx` | Location list, rooms/events counts, active/archive status, public hub link, filters/actions. | READY `GET /v1/admin/settings/locations?page&limit&q&status`; CD row `{ id,name,address,rooms,events,tz,hoursSet,hours,status,publicHub }`. | `workers/events/src/routes/studio-settings.ts:/locations`; contract in `packages/api-contracts/src/locations.ts`. | READY `Location`. |
| Location editor, `locations.edit` -> `LocationEditorPage`, `screens-insight-settings.jsx` | Address, capacity, amenities, timezone, hours, rooms, active/archive. | READY `POST/PATCH /v1/admin/settings/locations`; archive/delete routes. | `workers/events/src/routes/studio-settings.ts:/locations/:locationId`, `/archive`; contract in `packages/api-contracts/src/locations.ts`. | READY `LocationDetail`; hours should rationalize `tz`/`hours` to `timezone` + weekly schedule. |
| Closed days, `settings.closures` -> `ClosedDays`, `screens-bulk.jsx` | Closure list, scope/location selector, date range, reason, status/actions. | `GET /v1/admin/closures`; `POST`; `PUT/PATCH /:closureId`; `DELETE`. CD shape `{ id,name|reason,scope,locationIds,from,to,status,updated }`. | Studio facade `workers/events/src/routes/studio-closures.ts`; availability canonical `workers/availability/src/routes/facility-closures.ts`. | `Closure { id, scope:tenant|location|resource|service, targetIds[], startsAt, endsAt, reason, status }`. Unite Studio closures and facility closures. |
| Calendar settings, `settings.calendar` -> `SettingsCalendar`, `screens-settings-calendar.jsx` | Calendar categories, color palette, counts, preview. | `GET /v1/admin/settings/calendar-categories`; `PUT /calendar-categories`. CD shape `{ id,label,color,enabled,count }`. | `workers/events/src/routes/studio-settings.ts:/calendar-categories`. | `CalendarCategory { id,label,color,enabled,usageCount,system }`. |

## Domain: Guests, Segments, Imports, Waitlist, Invites

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Guests list, `guests` -> `GuestsList`, `screens-guests.jsx` | Guest table, facets, add/filter/export, segment badges, event scoped add modal. | `GET /v1/admin/guests?q&status&segment&eventId&page`; `POST /v1/admin/guests`; `POST /export`. CD row `{ id,name,email,phone,company,ticket,status,checked,source,segments,color,init }`. | `workers/events/src/routes/studio-guests.ts`; event-scoped admin guests in `workers/events/src/routes/studio-admin-guests.ts`; address book `workers/events/src/routes/address-book.ts`. | `GuestSummary { id,profile,status,ticket,source,segments,lastCheckIn,eventRefs }`. Unite contacts, event guests, and imports. |
| Guest profile, `guests.profile` -> `GuestProfile`, `screens-guests.jsx` | Profile stats, timeline, event history, comms, notes, sync rows, send-message/invite/add-to-segment/edit modals. | `GET /v1/admin/guests/:guestId?include=timeline,events,comms,notes,sync`; `PATCH`; `POST note`; `POST message`; `POST segment membership`. | `workers/events/src/routes/studio-guests.ts:/\:guestId`; address book routes; booking customer routes `workers/booking/src/routes/customers.ts`; notifications routes. Notes are GENUINELY-ABSENT as first-class guest notes. | `GuestDetail { profile, stats, timeline[], events[], communications[], notes[], integrations[], segments[] }`. |
| Bulk guest import, `guests.import`, `guests.import.map`, `guests.imports`, `settings.import`, `settings.import.status` -> `BulkImportSource/BulkImportMapping/ImportsHistory/BulkImporter/ImportStatus`, `screens-guests.jsx`, `screens-bulk.jsx`, `screens-subpages.jsx` | Upload source, column mapping, validation rows, import status/progress, imports history, status CSV. | `POST /v1/admin/guests/bulk-import`; `GET /v1/admin/guests/imports`; `GET /v1/admin/imports`; `POST /v1/admin/imports/bulk`; `GET /:runId`; `GET /:runId/status.csv`. | `workers/events/src/routes/studio-guests.ts:/bulk-import`, `/imports`; generic imports `workers/events/src/routes/studio-imports.ts`; event imports `workers/events/src/routes/imports.ts`. | `ImportRun { id,type,status,source,counts,mapping,rows[],errors[],createdBy,createdAt }`. Unite guest import and generic settings import. |
| Segments, `segments`, `segments.detail`, `segments.new` -> `SegmentsList/SegmentDetail/SegmentCreate`, `screens-guests.jsx` | Segment list/count/rules, rule builder, matching guests, archive. | `GET /v1/admin/segments`; `POST`; `PATCH /:segmentId`; `POST /:segmentId/archive`; detail should include `membersPreview`. | `workers/events/src/routes/studio-segments.ts`. | `Segment { id,name,description,count,rules[],status,lastUpdated,membersPreview[] }`. |
| Waitlist, `waitlist` -> `WaitlistView`, `screens-guests.jsx` | Waitlist entries, event/ticket filters, promote/remove actions. | `GET /v1/admin/reports/events/:eventId/waitlist` or `GET /v1/admin/bookings?status=waitlisted`; `POST /v1/admin/bookings/:id/promote`. | Reporting `workers/reporting/src/routes/reports.ts:/events/:eventId/waitlist`; booking `workers/booking/src/routes/bookings.ts:/:id/promote`; event guests have waitlisted status. | `WaitlistEntry { id,person,event,ticket,position,joinedAt,status,actions }`. Unite event waitlist and booking waitlist. |
| Send invite, `invite` -> `SendInvite`, `screens-guests.jsx` | Audience selector, event selector, invite template, preview, send status. | `GET /v1/admin/invite-templates`; `GET/POST /v1/admin/invites`; `POST /v1/admin/invites/:inviteId/send`. | `workers/events/src/routes/studio-segments.ts` exports `studioInvites` and `studioInviteTemplates`. | `InviteDraft { id,audience,eventId,templateId,channel,subject,body,status,sendStats }`. |
| Check-ins today and registrations today, `checkins.today`, `registrations.today` -> `CheckInsToday/RegistrationsToday`, `screens-drilldowns.jsx` | Drilldown table, filters, export/action rows. | `GET /v1/admin/reports/drilldowns/check-ins-today`; `GET /v1/admin/reports/drilldowns/registrations-today`. | `workers/events/src/routes/studio-reports.ts:/drilldowns/check-ins-today`, `/registrations-today`. | `ReportDrilldown { title, range, columns[], rows[], totals, exportUrl? }`. |
| VIP confirmations, `vip.confirmations` -> `VIPConfirmations`, `screens-vip-confirm.jsx` | Confirmation queue, confirm/decline actions, guest/event details. | `GET /v1/admin/vip-confirmations`; `POST /:id/confirm`; `POST /:id/decline`. | `workers/events/src/routes/studio-vip-confirmations.ts`. | `VipConfirmation { id,guest,event,status,requestedAt,decision? }`. |

## Domain: Campaigns, Messaging, Notifications, Inbox

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Campaigns list and filtered aliases, `campaigns`, `campaigns.sent`, `campaigns.scheduled`, `campaigns.drafts`, `campaigns.approvals` -> `CampaignsList`, `screens-comms.jsx` | Tabs, campaign rows, metrics, approval status, row menu/archive/send/approve. | `GET /v1/admin/campaigns?status`; `POST`; `PATCH`; `POST /:id/approve|reject|send|archive`. CD row `{ id,name,type,status,audience,recipients,opens,clicks,sent,approval }`. | Studio facade `workers/events/src/routes/studio-campaigns.ts`; notifications canonical `workers/notifications/src/routes/campaigns.ts`. | `Campaign { id,name,channel,status,audience,metrics,schedule,approval,contentRef }`. Unite Studio campaigns with notifications campaigns. |
| Email composer, SMS composer, `campaigns.email`, `campaigns.sms` -> `EmailComposer/SMSComposer`, `screens-comms.jsx` | Audience/event selectors, subject/body/content, schedule/send test, approval gate. | `POST /v1/admin/campaigns`; `PATCH /:id`; `POST /:id/send`; for SMS `POST /v1/events/:eventId/sms/campaigns`. | `workers/events/src/routes/studio-campaigns.ts`; `workers/notifications/src/routes/sms-campaigns.ts`; email designs in `workers/events/src/routes/studio-email-designs.ts`. | `CampaignDraft { id,channel,audience,content,schedule,approval,metricsPreview }`. |
| Notification templates, `campaigns.notifications` -> `NotificationTemplates`, `screens-comms.jsx` | Template list, trigger/channel/enabled, last edited. | `GET /v1/admin/notification-templates`; `POST`; `PATCH /:templateId`; `POST /:id/archive`. | `workers/events/src/routes/studio-campaigns.ts` `studioNotificationTemplates`; notifications `workers/notifications/src/routes/templates.ts`. | `NotificationTemplate { id,name,trigger,channel,enabled,lifecycleStage,content,updatedAt }`. |
| Notifications inbox, `notifications` -> `NotificationsAll`, `screens-notifications.jsx` | Notification list/outbox, preferences, mark read/dismiss/mark all. | `GET /v1/admin/notifications`; `GET /outbox`; `POST /mark-all-read`; `POST /:id/mark-read|mark-unread|dismiss`. | `workers/events/src/routes/studio-notifications.ts`; notifications worker `workers/notifications/src/routes/notifications.ts`. | `NotificationItem { id,type,title,body,read,dismissed,createdAt,action? }`. |
| Messaging center, `messaging`, `messaging.compose` -> `MessagingScreen/MessageComposer`, `screens-messaging.jsx` | Message list by channel, status chips, recipient, composer. | `GET /v1/admin/notifications?kind=message`; `POST /v1/admin/notifications/test|bulk` or campaign create. CD shape message `{ id,channel,to,subject,body,status,sentAt }`. | Notifications worker `workers/notifications/src/routes/notifications.ts`; Studio campaigns for persisted campaigns. | `Message { id,channel,recipient,content,status,delivery,relatedEntity }`. |
| Flow library/editor, `messaging.flows`, `messaging.flow` -> `FlowsLibraryScreen/FlowEditorScreen`, `flow-library*.jsx`, `flow-builder*.jsx` | Flow list, trigger/type/status, builder nodes/edges, inspector, event flow attach. | `GET /v1/admin/notifications/flows`; `GET /:id`; `POST`; `PUT /:id`; `DELETE`; event attach `GET/POST /v1/events/:eventId/messaging-flow`. CD flow `{ id,name,kind,trigger,status,nodes[],edges[] }`. | `workers/notifications/src/routes/flows.ts`; event live messages `workers/events/src/routes/live-messages.ts`. | `MessagingFlow { id,name,kind,trigger,status,canvas:{nodes,edges},versions?,attachedTo[] }`. |
| Delivery monitor, `messaging.delivery` -> `DeliveryScreen`, `screens-delivery.jsx` | Delivery table, filters, sort, pagination, detail sheet. | `GET /v1/admin/notifications/delivery?q&channel&status&page`; `GET /:id`. | `workers/notifications/src/routes/delivery.ts`. | `DeliveryEvent { id,channel,recipient,status,provider,attempts,lastAttemptAt,error?,relatedCampaignId }`. |
| Inbox, `inbox` -> `InboxView`, `screens-inbox-pages.jsx` | Conversation/message list, detail, reply, archive/unarchive, read/unread, flag. | `GET /v1/admin/inbox`; `GET /:messageId`; `POST /:id/reply`; action routes. | `workers/events/src/routes/studio-inbox.ts`; inbound webhooks in same file. | `InboxMessage { id,channel,from,subject,preview,body,status,flags,thread,relatedGuest? }`. |

## Domain: Reports and Analytics

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Reports overview, `reports` -> `ReportsOverview`, `screens-reports-overview.jsx`, `data-analytics.jsx` | KPI score tiles, funnel, series bars, source/ticket/campaign/location breakdowns, goals, export. | `GET /v1/admin/reports/overview?range&locationId`; `GET/PUT /goals`; export endpoint. CD expects `analyticsFor()` bundle `{ kpis,funnel,bySource,byCampaign,byEvent,byTicket,byLocation,revenue,series,prev }`. | `workers/events/src/routes/studio-reports.ts:/overview`, `/goals`; reporting worker `workers/reporting/src/routes/reports.ts`. | `AnalyticsBundle { range, filters, kpis, funnel, series, breakdowns, revenue, goals, deltas }`. |
| Event performance, `reports.event` -> `EventPerformance`, `screens-reports-overview.jsx` | Event picker, attendance/revenue/funnel/drilldowns. | `GET /v1/admin/reports/events/:eventId`. | `workers/events/src/routes/studio-reports.ts:/events/:eventId`; reporting event jobs in `workers/reporting/src/routes/event-reports.ts`. | `EventPerformanceReport { event, kpis, attendance, tickets, campaigns, guests, exports }`. |
| Event reports library/detail, `reports.library`, `reports.detail` -> `EventReportsLibrary/EventReportDetail`, `screens-event-reports.jsx` | Report cards, detail rows, download menu CSV/XLS/PDF, filters/event picker. | `GET /v1/admin/reports/library`; `GET /library/:reportId`; jobs/downloads if generated. | `workers/events/src/routes/studio-reports.ts:/library`; reporting `workers/reporting/src/routes/reports.ts:/catalog`, `/jobs`. | `ReportDefinition { id,name,description,category,formats,filters }` + `ReportResult { columns,rows,totals,downloadUrls }`. |
| Reports by guest, `reports.guests` -> `ReportsByGuest`, `screens-reports-money.jsx` | Guest segmentation, value/attendance/no-show rows, export. | `GET /v1/admin/reports/guests?range&locationId`. | `workers/events/src/routes/studio-reports.ts:/guests`; reporting `customer-analytics.ts`, `reports.ts:/customers`. | `GuestAnalyticsReport { kpis, segments[], rows[], export }`. |
| Reports by campaign, `reports.campaigns` -> `ReportsByCampaign`, `screens-reports-extra.jsx` | Campaign attribution rows, ROI/cost/conversion, charts/export. | `GET /v1/admin/reports/campaigns?range&locationId`. | `workers/events/src/routes/studio-reports.ts:/campaigns`; reporting `workers/reporting/src/routes/event-campaigns.ts`. | `CampaignAnalyticsReport { kpis, attribution[], funnel, rows[] }`. |
| Revenue reports, `reports.revenue` -> `ReportsRevenue`, `screens-reports-money.jsx` | Gross/net/fees/refunds/promos, by ticket/location/campaign, export. | `GET /v1/admin/reports/revenue?range&locationId`. | `workers/events/src/routes/studio-reports.ts:/revenue`; reporting `workers/reporting/src/routes/reports.ts:/revenue`; payments orders/payments routes. | `RevenueReport { totals, series, byTicket, byLocation, byCampaign, adjustments }`. Unite events analytics with payments actuals. |
| Scheduled reports | Schedules modal/hidden in reports controls. | `GET/POST/PUT/DELETE /v1/admin/reports/schedules`. | `workers/events/src/routes/studio-reports.ts:/schedules`; reporting `workers/reporting/src/routes/scheduled-reports.ts`. | `ScheduledReport { id,reportId,filters,frequency,recipients,nextRunAt,status }`. |

## Domain: Settings, Compliance, Billing, Audit

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| General settings, `settings.general` -> `SettingsGeneral`, `screens-subpages.jsx` | Account/company details, locale/timezone/defaults. | `GET /v1/admin/settings/general`; `PATCH /general`; `PATCH /account`. | `workers/events/src/routes/studio-settings.ts:/general`, `/account`. | `GeneralSettings { organization, defaults, locale, timezone, contact }`. |
| Branding, `settings.branding`, `branding` -> `SettingsBranding`, `screens-insight-settings.jsx` | Logo upload/remove, brand tokens/colors, preview tiles landing/email/kiosk, reset. | `GET /v1/admin/settings`; `PATCH /v1/admin/settings/branding`; `POST /logo`; `DELETE /logo`; public `GET /v1/branding/theme`. | `workers/events/src/routes/studio-settings.ts`; design tokens `workers/events/src/routes/design-tokens.ts`; contract in `packages/api-contracts/src/theme-contract.ts`, `design-tokens.ts`. | `BrandingSettings { logo, colors, typography, previews, tokenScope }`. Unite simple Studio branding with design-token kit. |
| Billing, `settings.billing` -> `SettingsBilling`, `screens-insight-settings.jsx` | Plan, usage/seats, invoices, payment methods, plan change. | `GET /v1/admin/billing`; `GET /invoices`; `GET /invoices/:id/pdf`; payment-method mutations; `PATCH /plan`. | `workers/events/src/routes/studio-billing.ts`; payments provider routes `workers/payments/src/routes/providers.ts`, payments/orders/refunds. | `BillingSurface { plan, usage, invoices[], paymentMethods[], entitlements }`. |
| Security/compliance, `settings.security` -> `SettingsSecurity`, `screens-compliance.jsx` | Control rows for SSO/MFA/password/data retention/IP allowlist, compliance certs/verticals. | `GET /v1/admin/security`; `PATCH /controls/:controlId`. | `workers/events/src/routes/studio-security.ts`; identity SAML/OIDC/admin routes. | `SecuritySettings { controls[], certificates[], policies[] }`. Unite display controls with identity enforcement. |
| Audit log, `settings.audit` -> `SettingsAuditLog`, `screens-audit-log.jsx` | Audit rows, category/severity filters, export, detail/timeline. | `GET /v1/admin/audit?category&severity&q&page`; `GET /export`; `GET /:id`; `GET /:entityType/:entityId/timeline`. CD row `{ id,day,time,actor,action,category,target,ip,severity }`. | Events audit `workers/events/src/routes/audit-log?` mounted `workers/events/src/index.ts:/v1/admin/audit`; reporting audit `workers/reporting/src/routes/audit.ts`. | `AuditEvent { id,occurredAt,actor,action,category,target,ip,severity,metadata }`. |
| Approvals settings/process editor, `settings.approvals`, `approvals.process.edit` -> `SettingsApprovals/ApprovalProcessEditor`, `screens-approvals.jsx` | Approval settings, process list/editor, steps, reviewers, statuses. | `GET/PUT /v1/admin/events/approvals/settings`; `GET/POST /processes`; `GET/PUT/DELETE /processes/:id`. | `workers/events/src/routes/studio-event-approval-processes.ts`. | `ApprovalProcess { id,name,enabled,steps:[{reviewerRole,deadline,action}], appliesTo }`. |
| Approvals inbox/review, `approvals`, `approvals.review` -> `ApprovalsInbox/ApproverReviewScreen`, `screens-approvals.jsx` | Queue, status timeline, review/decide/reset actions, event snapshot. | `GET /v1/admin/events/approvals/queue`; event-specific `GET /v1/admin/events/:eventId/approvals`; `POST submit|review|decide|reset`. | `workers/events/src/routes/studio-event-approvals.ts`. | `ApprovalSubmission { id,event,status,submittedBy,timeline[],reviewers[],decision? }`. |

## Domain: Integrations

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Integrations list, `settings.integ` -> `SettingsIntegrations`, `screens-insight-settings.jsx`, `data.jsx` | Provider cards, connection state, health metric, groups/categories, connect buttons. | `GET /v1/admin/integrations/catalog`; `GET /v1/admin/integrations/connections` or detail status by provider. CD card `{ id,name,desc,on,status,brand,metric,group }`. | `workers/integrations/src/routes/catalog.ts`; `workers/integrations/src/routes/connections.ts`; mounted in `workers/integrations/src/index.ts`. | `IntegrationCard { providerId,name,category,description,status,connected,health,metric,actions }`. |
| Integration detail, `settings.integ.detail` -> `IntegrationDetail`, `screens-integration-detail.jsx` | Setup steps, status, verify/reverify, field mapping, Salesforce guest sync config. | `GET /v1/admin/integrations/:provider/detail`; provider status/setup `GET /provider/status`, `/setup-status`, `/validate-step/:stepId`; config patch. Salesforce sync config `GET/PUT/PATCH /v1/admin/integrations/salesforce/sync-config`. | Detail `workers/integrations/src/routes/detail.ts`; providers: `salesforce-oauth.ts`, `hubspot.ts`, `zoom.ts`, `stripe.ts`, `slack.ts`, `ga4.ts`, etc.; Salesforce Studio sync config in `workers/events/src/routes/studio-guests.ts`. | `IntegrationDetail { provider, connection, setupSteps[], credentialsState, mappings?, syncConfig?, recentActivity[] }`. Unite generic integrations worker and Studio-specific Salesforce guest sync. |
| Calendar sync blocks | Calendar block controls for Google/Outlook/Exchange. | `GET/POST /v1/admin/calendar-sync`; blocks routes under `/v1/admin/calendar-blocks`. | `workers/integrations/src/routes/calendar-sync.ts`, `calendar-blocks.ts`, `google-sync.ts`, `outlook.ts`, `outlook-registration.ts`; google/exchange sync workers. | `CalendarSyncConfig { provider,status,accounts[],blocks[],lastSyncAt }`. |

## Domain: Landing Pages, Hubs, Canvas, Public Pages

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Landing pages index/editor, `landing.pages`, `landing.editor` -> `LandingPagesIndex/LandingPageEditor`, `screens-inbox-pages.jsx`, `screens-creation.jsx` | Page list, page picker from event/template, full block editor, drafts, preview, publish. | `GET /v1/canvas/pages?target_kind=event`; `POST /pages`; `GET/PATCH /pages/:pageId`; `GET /draft`; `PATCH /draft/blocks`; `POST /publish|unpublish`; asset picker. | `workers/events/src/routes/canvas.ts`; public pages `workers/events/src/routes/public-pages.ts`; contracts in `packages/api-contracts/src/canvas.ts`. | `CanvasPage { id,slug,status,target,theme,blocks[],draft,versions,publishSchedule }`. |
| Hub pages index/editor, `hub.pages`, `hub.editor` -> `HubPagesIndex/HubEditor`, `screens-public-hub.jsx` | Hub list, new hub picker, editor sections/fields/toggles, mini preview, event cards/calendar. | `GET /v1/admin/hubs`; likely CRUD under `/v1/hubs`; public `/v1/hubs/public/*`. CD shape hub `{ id,kind,slug,title,locations/groups/workspace,sections,events }`. | Studio index `workers/events/src/routes/studio-hubs.ts`; hub surfaces `workers/events/src/routes/publish-surfaces.ts` or `hubSurfaces` mounted in `workers/events/src/index.ts:/v1/hubs`, `/v1/hubs/public`. | `HubPage { id,kind:location|group|workspace,slug,status,content,filters,eventRefs,publicUrl }`. |
| Public hubs, `hub.public.location`, `hub.public.group`, `hub.public.workspace` -> `PublicLocationHub/PublicGroupHub/PublicWorkspaceHub`, `screens-public-hub.jsx` | Public nav, event cards, filters/calendar, footer, location/group/workspace branding. | `GET /v1/hubs/public/:slug` variants; events under public hub. | `workers/events/src/index.ts:/v1/hubs/public`; `workers/events/src/routes/journey-surfaces.ts` for public journey catalog. | `PublicHubSurface { hub, branding, filters, events[], services?, calendar }`. |
| Canvas assets/email designs embedded in landing/messaging | Asset picker, uploads, email design templates/tokens/render/send-test. | `GET /v1/canvas/assets`; `POST /assets/presign`; upload/confirm; `GET/POST /email-designs`; draft blocks/render/test-send/publish. | `workers/events/src/routes/canvas.ts`; `workers/events/src/routes/studio-email-designs.ts`. | `CanvasAsset` and `EmailDesign` contracts already mostly present in `packages/api-contracts/src/canvas.ts`; expose through one client namespace. |

## Domain: Coord, Queues, Appointments

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Queues module, `queues` -> `QueuesScreen`, `screens-coord-modules.jsx`, `coord-link.jsx` | Deferred Coord module header, seam checklist, queue locations, queue list/board, walk-ins, call-next options, serve/complete. | `GET /v1/admin/locations`; `GET /v1/admin/queues?locationId&mode`; `GET /v1/admin/queues/:queueId/board`; `POST /walkins`; `GET/POST /call-next`; entry actions. | Coord facade `workers/coord/src/index.ts`; canonical queue worker `workers/queue/src/routes/queues.ts`, `entries.ts`, `metrics.ts`. | `CoordQueueSurface { locations[], queues[], board:{waiting,serving,completed}, actions }`. Existing backend already covers Coord; do not rebuild. |
| Appointments module, `appointments` -> `AppointmentsScreen`, `screens-coord-modules.jsx` | Appointment list by queue/location/date, reschedule/cancel actions. | `GET /v1/admin/queues/:queueId/appointments?date`; `POST /appointments/:appointmentId/reschedule`; `POST /cancel`. | `workers/coord/src/index.ts`; booking admin routes `workers/booking/src/routes/bookings.ts`, calendar `workers/booking/src/routes/calendar.ts`. | `CoordAppointmentSurface { queue, date, appointments[], actions, availability? }`. Existing Coord facade should hide booking/queue split. |

## Domain: Public Journey

| Surface | Data-informed regions | Likely API call and CD shape | Existing backend route | Clean contract shape |
|---|---|---|---|---|
| Journey public surfaces (used by hubs/service booking, not direct CD route names except public hub/register) | Staff/service catalog, availability, booking, queue join, event register, visit tracking. | READY `GET /v1/journeys/public/:slug`, `/catalog`, `/availability`, `/available-services`; `POST /book`, `/join`, `/register`, `/visit`. | `workers/events/src/routes/journey-surfaces.ts`; contract in `packages/api-contracts/src/journey.ts`. | READY `JourneySurface`, `JourneyBookingResult`, `JourneyQueueResult`, `JourneyRegistrationResult`. |

## Genuinely Absent or Needs Facade Build

| Gap | Affected surfaces | Why absent / needed |
|---|---|---|
| Help CMS/API | `help`, `help.article` | Static CD help data only; no worker route for product help articles. |
| Guest notes | `guests.profile` | Guest profile notes are a CD local construct; no first-class guest notes route found. Could map to audit/timeline only if read-only. |
| Custom role registry exactly as CD models it | `settings.team` | Built-in role perms are static in CD. Identity has team/admin route files, but a Studio custom-role CRUD facade is not visible in the route map. |
| Ad-hoc calendar block mutation | `calendar.day` modal | Day reads exist; if modal creates non-event blocks, no matching Studio calendar block CRUD route was found. |
| Service packages in domain catalog worker | `services.packages` | Studio facade exists in events worker; `workers/catalog` does not have packages. Contract should use Studio facade unless catalog worker is extended. |
| Help/workspace account memberships | `account.details` workspace panel | Identity tenant memberships likely exist, but the exact account workspace surface contract needs a facade if CD expects cross-tenant workspace rows. |

## Recommended Build Order

1. **Catalog services contract pack**: `services`, `services.edit`, `services.categories`, `services.packages`. This unlocks the largest non-events surface set and feeds public journey, staff/resource authorization, questions/promos attachment, and appointment/queue booking.
2. **Staff/resources contract pack**: `staff*`, `resources*`, schedules and service authorization. This unlocks delivery capacity, booking availability, Coord staffing seams, and service editor dependencies.
3. **Guests/audience contract pack**: `guests*`, `segments*`, `waitlist`, `invite`, imports, booking responses. High surface count and central to campaigns, reports, check-in, and Salesforce sync.
4. **Comms/messaging contract pack**: campaigns, composers, notification templates, flows, delivery, inbox, notifications. This consolidates events Studio routes with notifications worker routes.
5. **Reports analytics contract pack**: overview, event performance, library/detail, guests, campaigns, revenue, drilldowns, schedules. Use one `AnalyticsBundle` facade matching CD's `analyticsFor()` shape.
6. **Settings/admin contract pack**: branding, billing, security, audit, approvals, calendar categories, closures, general settings. Mostly existing Studio facades; contract work is rationalization.
7. **Integrations detail contract pack**: catalog/list/detail/status/setup/verify plus Salesforce sync config. Important but lower screen unlock count than catalog/guests/comms.
8. **Canvas/hubs/landing pack**: landing pages, hub pages, public hub surfaces, assets/email designs. Much exists, but contracts should wrap Canvas shapes cleanly for CD.
9. **Coord pack**: queues and appointments. Existing backend already covers Studio + Coord; contract the `workers/coord` facade last unless CD needs deeper queue board mocks immediately.
10. **Absent small pack**: help CMS, guest notes, custom roles facade, ad-hoc calendar blocks, workspace memberships. Ticket these only when the corresponding surface must move from static/demo to live data.
