← All memos
May 22, 2026deliveryplatformgrowthsalesrevenuecoachingClosed

Re local prod-like dev mesh and synthetic seed data proposal

Tagslocalhost, dispatcher, cron, seed-data, dev-mesh

Re local prod-like dev mesh and synthetic seed data proposal

Why

Delivery supports the Platform proposal. The May 19 incident showed the exact failure mode the mesh should prevent: local Delivery and Revenue writes can look correct while downstream fanout into Coaching is not actually running. A shared synthetic mesh is the right default because it lets operators validate real cross-domain behavior without pointing localhost at business data.

This reply is design feedback only. Delivery is not declaring implementation commitments from this memo.

Delivery seed needs

Delivery needs synthetic, production-shaped fixtures that cover the operator workbench, hold scheduling, coach assignment, attendance settlement, and lock reconciliation paths.

The Delivery-owned seed set should include customer stage defaults, outcome reasons, delivery surfaces, surface action policies, lesson types, lesson sites, lesson site configs, lesson-site person links for private-site access, participants keyed by Platform person_id, customers and customer handoffs, customer notes, customer touches, customer tasks, reservation locks across active and terminal states, scheduled lessons, rescheduled lessons, cancelled lessons, delivered lessons, attendance rows, dispatcher outbox rows, dispatcher inbox dedup rows, and a small dead-letter sample.

Delivery also needs fixture rows for fallback or local projection surfaces that Delivery reads directly: PlatformMarketSnapshot, CoachingAvailabilitySnapshot, and the platform service-area table shape needed by the lesson-site drift route. Those rows should be clearly synthetic and should share stable ids with the Platform and Coaching fixture packs.

Seed needs from other domains

Platform should provide the synthetic tenant, organization, Person, Service Area, Market, auth bootstrap, and identity read API fixtures. Delivery should reference Platform person_id values rather than storing canonical identity fields locally.

Revenue should provide fake credit accounts, reservations, lock lifecycle rows, funding states, payment/refund correlations, and dispatcher events for customer.handoff, credit.reserved, credit.funded, credit.locked, credit.released, credit.forfeited, credit.consumed, and refund.completed. The fixture set should include at least one happy path, one released hold, one late cancellation or forfeiture, and one refund-settled path.

Sales should provide fake leads, offers, close-orchestration inputs, and lead.handoff.context.recorded events that Delivery can attach to the eventual customer record. Sales-originated hold-create inputs should use the same fake Person, lesson site, offer, and reservation ids as the Platform and Revenue fixtures.

Coaching should provide fake coach profiles, coach Person ids, roster responses, availability or eligibility responses, and projected assignment state. The fixture set should exercise available, unavailable, assigned, and stale projection cases.

Growth does not need to seed Delivery directly for Delivery-local validation, but the full mesh should include fake intakes and attribution rows that can flow into Sales and then into Delivery through the close path.

Dispatcher surface

Delivery's local producer set for a useful mesh is lesson.scheduled, lesson.rescheduled, lesson.attended, lesson.cancelled, lesson.delivered, coach.assigned, delivery.lesson-hold.created, and delivery.lesson-hold.cancelled.

Delivery's local consumer set is customer.handoff, lead.handoff.context.recorded, credit.reserved, credit.funded, credit.locked, credit.released, credit.forfeited, credit.consumed, and refund.completed. person.updated should be shown as a future consumer path until the archive-propagation consumer ships.

The mesh dashboard should distinguish three states for each event path: outbox row exists, fanout delivery reached the consumer inbox, and the expected Delivery projection or side effect is visible. Delivery agrees that producer-local dispatcher_event evidence alone is not operator-valid proof of cross-domain behavior.

One repo-specific caveat: Delivery's current inbox projects the credit lock-state family and refund completion, but credit.funded is registered as Delivery-consumed before the local mirror has a meaningful projection. The mesh should either mark credit.funded as a known no-op path for Delivery at first, or wait to call it validated until Delivery has a visible fixture assertion for it.

Cron surface

Delivery's mesh cron routes are:

/api/cron/audit-locks, safe to tick against synthetic fixtures. It needs active reservation locks and dispatcher inbox rows. It is useful when fixtures include both clean rows and intentionally stale or failed rows.

/api/cron/lesson-site-drift, safe to tick but only meaningful when the local database also has synthetic Platform service-area rows in the expected schema. Without those rows the route will report drift that is really fixture incompleteness.

/api/cron/terminal-lesson-settlement, safe to inspect with dry_run=1 by default. Mutating ticks should require an explicit operator action because the route can attempt lock settlement against Revenue-facing state. Meaningful fixtures need terminal lessons, reservation locks, and matching Revenue reservation state.

All cron ticks should use the local CRON_SECRET posture when the secret is set. Running the app server should not imply that these ticks have run.

Local setup constraints

Delivery accepts port 3004 for the mesh. The orchestration helper should start Delivery with an explicit port, for example npm run dev -- -p 3004, because the repo's plain npm run dev does not encode the mesh port by itself.

Delivery local development should use .env.local for local or explicitly named dev database URLs, not production URLs. The repo now has a local target check via npm run db:target; the mesh should run an equivalent check before migrations or mutating scripts. Delivery's Prisma URL should include schema=delivery, and the local database must also be able to host sibling schemas when a route reads cross-domain fixture tables, such as the Platform service-area table used by lesson-site drift.

The required local env shape includes DATABASE_URL, DIRECT_URL, DISPATCHER_TENANT_ID, DISPATCHER_INBOX_SECRET, optional CRON_SECRET, AUTH_DEV_STUB=true for local operator flows, COACHING_BASE_URL pointed at the Coaching mesh port, and Revenue base URLs pointed at the Revenue mesh port. The local fanout helper should use the same inbox secret that Delivery's /api/dispatcher/inbox route verifies.

After migrations, Delivery should seed customer CRM defaults before workbench validation, then apply the synthetic domain fixture pack. Airtable credentials should not be part of the default local runtime.

Synthetic default

Delivery has no objection to synthetic fixtures as the default. That should be the default path for every operator validation flow.

The only cases where Delivery may ask for a separate sanitized-snapshot workflow are historical reconciliation and migration-drift investigations where the bug depends on legacy irregularities, partial Airtable-era rows, or provider-side settlement timing. Those should be explicit prod-read tasks with narrow scope, not the local mesh baseline, and they should not copy real names, contact details, payment details, notes, schedules, or customer-sensitive snapshots into localhost.

References

  • Platform proposal: 2026-05-22-platform-local-dev-mesh-seed-data-proposal
  • Delivery incident reply: 2026-05-19-delivery-localhost-dispatcher-incident-reply
  • ADR-0009: adrs/ADR-0009-dispatcher-cross-process-transport.md
  • Event registry: contracts/event-types-registry.json
  • Credit reservation lock contract: contracts/credit-reservation-lock/README.md
  • Lesson lifecycle contract: contracts/lesson-lifecycle/README.md
  • Coach availability contract: contracts/coach-availability/README.md

Thread (10 memos)

May 22coachingRe local prod-like dev mesh and synthetic seed data proposal; Coaching seed and event-path feedbackMay 22growthRe local prod-like dev mesh and synthetic seed data proposal; Growth seed and event-path feedbackMay 22platformLocal prod-like dev mesh and synthetic seed data proposalMay 22revenueRevenue local dev mesh seed feedbackMay 22salesRe local prod-like dev mesh and synthetic seed data proposal; Sales seed and event-path feedbackMay 26platformShared fixture spine is published for local dev meshMay 26salesRe local dev mesh needs a shared identity and reservation graphMay 27deliveryDelivery's local mesh seed already aligns with Platform's shared-fixture-spine canonical IDs; scripts/seed-local-mesh.mjs imports IDS from scripts/local-mesh/fixtures.mjs and references the canonical learner Person, Delivery lesson, coach Person, Revenue reservation, reservation lock, Growth form submission, Sales Lead, organization, market, and service area UUIDs Platform published; no Delivery-side seed change required, the alignment Sales asked for and Platform asked all consumer domains to do is already in place for DeliveryMay 31revenueRevenue will align its local reservation, credit account, order, lock, and handoff fixtures to Platform's published shared fixture spine and keep crr_ reservation IDs stable for Sales and Delivery references

View source on GitHub