Re local prod-like dev mesh and synthetic seed data proposal; Coaching seed and event-path feedback
Position
Coaching supports the proposed local prod-like mesh and agrees that synthetic, production-shaped fixtures should be the default. Coaching should not use real coach, guardian, student, customer, lead, lesson, payment, or schedule data in localhost for ordinary operator validation.
Coaching also agrees with Platform's dispatcher rule. For Coaching, a localhost availability or eligibility result is operator-valid only when the producer write, producer-local dispatcher_event row, local fanout delivery, Coaching inbox dedup row, and Coaching projection side effect are all visible for the same event. A local row in a producer outbox is durable producer evidence, not proof that Coaching consumed the event.
Coaching seed needs
Coaching needs synthetic rows that exercise the coach supply and eligibility surface without copying business data:
coaching_org_configrows for at least one fake organization, with a known default timezone.- Coach rows across
active,onboarding,inactive, andarchived, with fakeperson_idreferences,market_id, home service area, covered service areas, skill levels, rates, drive constraints, and cross-service-area flags. - Availability templates with recurring weekly supply, plus availability exceptions for both
additionalandunavailableintervals. - Certification types and coach certification rows that cover active, expired, missing, and mismatched-certification cases.
- Zip and geography caches, especially
zip_service_area_cacheandzip_distance_cache, so by-description eligibility and travel-time predicates can be tested without calling real customer addresses. coach_lesson_bookingprojection rows for reserved, locked, released, delivered or consumed-like past lessons, same-day adjacent lessons, and overlapping conflicts.- Eligibility consistency samples only as dashboard evidence. The default seed should not fake consistency success unless the seed also includes the Sales and Delivery reads that produced it.
- Dispatcher table-family rows only as part of a specific event-path test. The default seed should not pre-create successful inbox evidence for an event that did not pass through local fanout.
The seed should target the current continuous-availability model. Any old seed that writes availability_window or projection_state should be treated as stale until it is updated to availability_template, availability_exception, and coach_lesson_booking.
Seed needs from other domains
Coaching needs Platform to seed fake tenant, organization, operator auth or bootstrap state, Person facts for coach person_id references, canonical Market rows, canonical Service Area rows, and the identity endpoint shape used by Coaching's operator surfaces. The fake Platform geography should include at least two markets and multiple service areas in one market so coverage and cross-service-area predicates can be exercised.
Coaching needs Delivery to seed fake lesson ids, lesson windows, service areas, lesson ZIP or address facts, assigned coach ids, hold-created facts, cancellation facts, and delivered lesson facts. Delivery remains the owner of assignment, so Coaching should consume Delivery's assignment and lesson lifecycle facts rather than seed assignment as a Coaching-owned event.
Coaching needs Revenue to seed fake reservation ids, lock ids, and credit projection events with organization_id, coach_id, and lesson_id populated. credit.reserved, credit.locked, credit.released, and credit.forfeited are enough for Coaching's projection path; credit.funded and credit.consumed should not be required for Coaching.
Coaching needs Sales to seed fake lead ids and confirmation request ids for the coach-confirmation handshake. Growth is mostly indirect for Coaching in this mesh, through synthetic intakes that become Sales leads and then Sales confirmation or eligibility checks.
Coaching producer events
The mesh should verify the Coaching-produced event currently wired in repo code:
coaching.lesson.confirmation_decided
That event should be emitted inside the same Prisma transaction as the Coaching audit row and should create a producer-local dispatcher_event row before local fanout delivers it to Sales.
Coaching should not emit coach.assigned; assignment is Delivery-owned per ADR-0008. If a future coach role lifecycle producer path is added for Platform identity role projection, the mesh should name it separately from the current confirmation decision path rather than inferring it from the Coach table.
Coaching consumer events
The current Coaching dispatcher inbox should be treated as wired for these consumer event families:
credit.reservedcredit.lockedcredit.releasedcredit.forfeitedlesson.scheduleddelivery.lesson-hold.createdcoach.assignedlesson.cancelledlesson.delivered
The mesh should assert that the credit events mutate coach_lesson_booking state when organization_id, coach_id, and lesson_id are present. It should assert that lesson scheduled, hold-created, and coach-assigned events seed or update booking rows with lesson window and location facts. It should assert that cancellation and delivered events update booking state without treating Coaching as the lesson owner.
The event registry also names lead.coach.confirmation.requested and delivery.lesson-hold.cancelled as Coaching-consumed surfaces, but the current local inbox switch does not project those events. Platform should treat them as known target or no-op paths unless Coaching wires them before the local mesh spec lands. The mesh should distinguish "registered contract consumer" from "currently wired inbox behavior" so the operator does not get a false pass.
Coaching should not subscribe to credit.funded or credit.consumed for the mesh. credit.funded is Revenue-internal for this projection, and consumed is terminal-past for Coaching's future availability surface.
Cron routes
Coaching has no Vercel cron routes in its current vercel.json. The local mesh should list Coaching as having no cron ticks until that file adds crons.
Coaching does have one-shot scripts and smoke tools, but they should remain explicit operator actions rather than cron-like background behavior. migrate:coach is a legacy Airtable migration and should not be part of the default mesh. smoke:inbox is useful for route-level HMAC and dedup validation, but its default URL needs to align with the mesh's Coaching port or be invoked with --url=http://localhost:3003. Existing e2e seed code should be considered stale if it still targets removed availability_window or projection_state tables.
Local setup constraints
Coaching can use the proposed fixed port 3003; the local command should be npm run dev -- --port 3003.
Coaching is on Prisma 7 with @prisma/adapter-pg. Runtime Prisma Client uses DATABASE_URL; Prisma CLI migrations use DIRECT_URL through prisma.config.ts. Both must point at a local or explicitly named dev database. Coaching models use @@schema("coaching"), so the mesh should not try to isolate local and production data by changing the schema name.
The repo now has a local-first env posture: .env.local is the intended localhost file, .env.local.example documents the safe shape, and npm run db:where prints the database host and database name without exposing credentials. The mesh runner should still set process env explicitly or verify npm run db:where before migrations, seed, backfill, rekey, or dispatcher smoke commands.
Recommended local bootstrap for Coaching is:
npm run db:where
npm run prisma:migrate:dev
npm run dev -- --port 3003
The dispatcher inbox route is POST /api/dispatcher/inbox and requires DISPATCHER_INBOX_SECRET. The local fanout helper should post to http://localhost:3003/api/dispatcher/inbox with the same HMAC shape used by the shared dispatcher SDK.
Objections and edge cases
Coaching has no objection to synthetic fixtures as the default. A sanitized production snapshot is not needed for core availability, eligibility, projection, confirmation, or dispatcher validation.
The only edge cases that may need a separate opt-in workflow are geography and travel-time investigations where the bug depends on real-world routing behavior, a live Platform geography catalog, or an external maps provider response. Even then, the workflow should use public or synthetic addresses, fake people, fake schedules, and fake payments. It should not copy customer, coach, guardian, lesson, note, payment, or business-sensitive snapshots into localhost.
References
- Proposal:
2026-05-22-platform-local-dev-mesh-seed-data-proposal - Coaching domain scope:
coordination/domains/coaching.md - Coach availability contract:
coordination/contracts/coach-availability/README.md - Dispatcher inbox route:
coaching/app/api/dispatcher/inbox/route.ts - Dispatcher inbox switch:
coaching/modules/dispatcher-inbox/schema.ts - Confirmation producer path:
coaching/modules/coaching-confirmation/repo.ts - Coaching env and local DB notes:
coaching/README.md - Coaching cron config:
coaching/vercel.json