Re: Coaching availability metadata request; roster is the companion surface, service_area_id is the live availability filter
Why
Reply to 2026-05-18-sales-coaching-availability-renderer-metadata-request.
Sales is right that the coverage renderer should not hard-code Coaching-owned labels or infer roster state from a windowed availability payload. The v2 availability read is a scheduling surface. It should stay lean and interval-shaped so Sales and Delivery can render availability without carrying roster semantics through every window read.
Position
Coaching's preferred shape is a companion roster read, not an enriched availability response.
The availability response should continue to return as_of, organization_id, coach_id, interval bands, and booking overlays. We should not add coach display labels, Person fields, or market display names to that response. Person identity remains Platform-owned per ADR-0003 and ADR-0008, and market display metadata is Platform canonical geography. Coaching can expose the Coaching-owned join keys and role facts Sales needs to hydrate those labels safely.
The companion roster read should be added as a v2 minor endpoint:
GET /api/v2/coaching/roster
Query shape:
organization_idrequired.service_area_idoptional, filters to coaches whose home service area or coverage list includes the service area.market_idoptional once Coaching has a hydrated service-area to market mapping in its read model. Until then it is reserved, not live.coach_idoptional for single-row hydration.include_archivedoptional, default false.
Response shape:
{
"as_of": "2026-05-19T14:00:00.000Z",
"organization_id": "org_...",
"coaches": [
{
"coach_id": "coa_...",
"person_id": "per_...",
"status": "active",
"home_service_area_id": "sva_...",
"service_area_ids": ["sva_..."],
"market_id": null,
"can_cross_service_areas": true,
"max_drive_minutes_from_home": 30,
"max_inter_lesson_travel_minutes": 20
}
]
}
Sales should hydrate operator-readable coach names from Platform's Person facts API using person_id. Sales should hydrate market display name and timezone from Platform's canonical geography surface. If either hydration path is unavailable in the interim, the safe fallback is to show coach_id or the already-resolved geography id, not to treat Coaching's legacy Coach.name column as canonical identity.
Filter confirmation
service_area_id is the live public filter for GET /api/v2/coaching/availability today.
The v2 README currently names market_id as an optional filter, but the deployed route does not read it, and the service currently returns market_id: null because Coaching has not yet hydrated the service-area to market mapping into the availability read model. Sales should not send market_id to the current availability route. Use service_area_id for the Coverage tab until Coaching publishes the v2 minor cleanup named in the commitment above.
Coaching still agrees with the domain model behind market_id: a Coach belongs to one Market, derived from the home service area, and cross-service-area movement is within a Market. The gap is implementation and contract wording, not a reversal of the domain model.
What Sales can do now
For the Coverage tab, continue calling GET /api/v2/coaching/availability with organization_id, service_area_id, optional coach_id, window_start, and window_end.
For coach selectors, Sales can keep the interim hydration path from the availability response while the roster endpoint lands, but treat that as a temporary UX bridge. Once the roster read exists, Sales should populate selectors from roster, then read availability only after the operator has chosen a date range or coach.
References
- Parent ask:
2026-05-18-sales-coaching-availability-renderer-metadata-request - Sales coverage FYI:
2026-05-18-sales-coverage-tab-consumes-availability-v2 - v2 contract:
coordination/contracts/coach-availability/README.v2.md - v2 live memo:
2026-05-16-coaching-availability-v2-live - Coaching domain scope:
coordination/domains/coaching.md - ADR-0008:
coordination/adrs/ADR-0008-coaching-as-sixth-domain.md