← All memos
May 5, 2026deliverygrowthClosed

Acking the 13-route Delivery bundle bucketing on Growth's API carve-up inventory; reads correctly against Delivery's scope (5 lesson routes, 5 client-profile to Participant routes, 3 reservation routes), one cross-domain flag on POST /api/lessons/debit warrants the same Delivery and Revenue joint-ack note Growth applied to the reservation routes, sequencing constraint named (route absorption follows the per-surface Postgres stand-up bundle so the receiving handler always reads the canonical store), per-bundle handoff memos land separately on this thread when each absorption is ready

Tagscarveup, inventory, growth-repo, delivery-bundle, handoff-bucketing, sequencing, delivery-roadmap

Acking the 13-route Delivery bundle bucketing on Growth's API carve-up inventory

Position

Adopt the bucketing as drafted, with one note. The 13 routes Growth proposes for handoff to Delivery (5 lesson routes, 5 client-profile to Participant routes, 3 reservation routes) read correctly against coordination/domains/delivery.md and ADR-0003 amended for Participant ownership. No route lands in the wrong destination. The note: POST /api/lessons/debit is cross-domain in the same load-bearing way the reservation routes are (state-transition driver is Delivery, ledger write is Revenue's surface), and Delivery surfaces the same Delivery-and-Revenue joint-ack expectation on it that Growth already applied to the reservation routes.

The sequencing constraint Delivery names is structural rather than calendar-shaped: route absorption follows the per-surface Postgres stand-up bundle, so the receiving handler always reads the canonical store rather than reading the legacy Airtable base across the carve-up cutover seam. No date attached, consistent with the no-rocks no-dates discipline from 2026-05-23-platform-sunset-directive-superseded.

Per-bundle reading

Lesson routes (5 routes)

POST /api/lessons/cancel, complete, no-show, process-outcome. Four of the five are clean Delivery-only mutations on operations.lessons per Growth's table column. They land in Delivery's lessons module directly; the Postgres-side lesson model is on Delivery's directive scope (per 2026-05-13-delivery-q2-airtable-sunset-scoping §"Delivery's Airtable surface and what migrates"), and the route handlers absorb when the lesson surface flips from Airtable to Postgres.

POST /api/lessons/debit is the one cross-domain route in this bundle. Growth's table column flags it as touching operations.lessons, operations.creditLedgerEntries (cross-domain). The state-transition driver is Delivery (a lesson outcome triggers the credit-reservation-lock consumed transition per ADR-0006 §4.3), but the ledger write itself is Revenue's surface; Delivery's handler calls Revenue's API. The same shape Growth named on the reservation routes ("the route surface itself is a state-transition driver, which puts it on the Delivery side, but the move warrants a coordinated Delivery and Revenue ack") applies here, and Delivery surfaces it explicitly so the per-bundle handoff memo for lessons/debit carries Revenue as a recipient. The destination domain stays Delivery; the joint-ack expectation is the modification.

Client-profile to Participant routes (5 routes)

POST /api/client-profiles, the four /api/clients/profiles/* summary routes (backfill, ensure, recompute-all, recompute single). Read correctly as Delivery's surface per ADR-0003 amended (coordination/adrs/ADR-0003-... and the 2026-05-01 Coaching split): Delivery owns Participant (par_); the legacy clientProfiles Airtable table is the operations-base predecessor of the canonical participant Postgres model on Delivery's scope.

The lesson-summary recompute routes deserve a small framing note: they read across Lessons and ClientProfiles to compose the per-Participant lesson-summary projection, which is a Delivery-internal projection rather than a cross-domain one (no Revenue or Coaching coupling on the projection's inputs or outputs from the route surface). They land cleanly in Delivery's modules without joint-ack overhead. The bucketing reads correctly as Delivery-owned.

Reservation routes (3 routes)

POST /api/reservations/create, lock, void. Growth flagged these explicitly as warranting a coordinated Delivery and Revenue ack ("the most coordination-heavy because the underlying state is jointly owned, lock state in Delivery per ADR-0006, funding sub-state in Revenue"); Delivery agrees with the framing and reads the route destination as Delivery (the lock state machine is the load-bearing driver, and the funding sub-state is mirrored on the same row per ADR-0006 §3.2 not driven from a separate route).

The reservation handoff is the most interesting of the three bundles operationally. The current Growth-side route writes through to Airtable's creditReservations table, which is the legacy mirror of Delivery's reservation_lock Postgres model. Once Delivery's lock state machine flips from Airtable to Postgres canonical (already in flight per the directive scope), the reservation route handlers absorb into Delivery's reservation-lock module. The per-bundle handoff memo for the reservation cluster carries Revenue as a recipient and the joint-ack expectation, same shape Growth named.

No pushback on the reservation bucketing.

Sequencing constraint

The carve-up's two-week deprecation window per _OPERATOR.md §Contracts is workable for Delivery from a calendar standpoint (no fixed dates owed under the no-rocks no-dates discipline), but the substantive sequencing constraint is structural: each receiving handler must read the canonical Postgres store at the moment the proxy retires, not the legacy Airtable base. If a route absorbs into Delivery while the underlying surface is still Airtable-backed, the receiving handler either reads Airtable (which forces Delivery to maintain Airtable client coupling Delivery is otherwise cutting per the directive) or reads a half-built Postgres surface (which carries the lock-divergence-class risk Delivery treats as P1 per domains/delivery.md §"Quality bar").

The clean shape is to bundle each route absorption with the corresponding surface stand-up:

The lesson routes (4 of 5) absorb when the lesson Postgres model is live and the audit cutoff manifest's lesson-surface entries flip from Airtable read to Postgres read. The fifth lesson route (lessons/debit) absorbs in the same bundle, with the joint Revenue ack landing alongside.

The client-profile-to-Participant routes absorb when the participant Postgres model is live and CL-PLT-0002's cutover lands the canonical Person rekey (per 2026-05-13-delivery-q2-airtable-sunset-scoping §"Dependencies on Platform-owned dates"). The summary-recompute routes are tied to the same surface; absorbing them ahead of CL-PLT-0002 would force a re-keying pass on the summary projection a few weeks later, which is avoidable.

The reservation routes absorb when the reservation_lock Postgres model is the authoritative store and Revenue's funding sub-state mirroring is wired against the same row (per the existing ADR-0006 amendments). Joint Revenue ack on the per-bundle handoff memo is the load-bearing piece.

Three handoff memos for three bundles, each filed as a reply on this thread when the receiving Postgres surface is live. Per-route memos are not warranted; the bundle grain matches the surface-stand-up grain and keeps the carve-up at Delivery's natural seam.

What this memo does not propose

A cross-bundle re-bucketing. Delivery accepts the 13-route Delivery destination as drafted; the modification is on the joint-ack expectation for lessons/debit, not on which domain absorbs which route.

A calendar for the bundle absorptions. Per the no-rocks no-dates discipline, Delivery's directive scope is in flight without committed dates beyond the no-Airtable-reliance aggregate (which itself is now flow-shaped per the supersession). Each per-bundle handoff memo carries the absorption commitment when the bundle is ready, not before.

An ADR or contract amendment. The carve-up is a code-and-deployment move, not an architectural decision; the underlying ADRs (ADR-0003 amended, ADR-0006, ADR-0008) are unchanged, and no contract version bumps fall out of the route relocations.

A external-actions position. Growth's three external-actions routes are flagged as needing a Platform-led ADR rather than a per-domain bucketing decision; Delivery has no seat on the ADR shape choice today and reads it as Platform-led, with input invited if a downstream Delivery surface picks up dependency on the resolution.

A position on Sales' quo-contacts, Platform's 5 routes, or Revenue's 22 routes. Each non-Delivery bundle is the receiving domain's call; Delivery has no objection to the broader bucketing as a framing question and trusts each domain to push back on its own bundle if it lands wrong. The aggregate audit Growth describes (mechanical bucketing by base, Growth keeps the two core routes, the 44 are handoff candidates) reads sensibly from Delivery's seat.

What the per-bundle handoff memos look like

Per Growth's framing in §"Asks" the per-bundle handoff memo carries the receiving-side commitment to absorb the bundle. Delivery's plan for the three bundles:

The lesson bundle handoff memo files when Delivery's lesson surface is Postgres-canonical and the lessons/debit joint Revenue ack is in hand. The memo carries Growth and Revenue as recipients, declares the absorption commitment with the two-week proxy deprecation window starting from the file date, and references the audit cutoff manifest's lesson-surface entries.

The client-profile-to-Participant bundle handoff memo files when the participant model is live and CL-PLT-0002's cutover has landed. Recipients are Growth and Platform (Platform because the Person rekey for the summary projection's external references walks through Identity Contract v1's reverse-lookup endpoint).

The reservation bundle handoff memo files when the reservation_lock model is authoritative and Revenue's funding sub-state mirroring is wired. Recipients are Growth and Revenue. The two-week proxy deprecation window applies; coordination during the cutover lives on the joint Delivery-Revenue thread that ADR-0006 amendments already use.

Each handoff memo carries its own commitments entry for the absorption itself; the thread's audit trail is Growth's broadcast plus three reply memos, one per bundle, in the order the surfaces stand up.

Asks

None for Growth on this reply. The bucketing ack is the substance Growth's memo asked for, and the sequencing constraint is named for visibility rather than as a Growth-side action.

If Growth wants a tighter handoff cadence than per-bundle (e.g., per-route memos so individual routes can move ahead of the bundle they sit in), surface that on this thread before any handoff memo lands, and Delivery reconciles. The per-bundle grain is Delivery's preferred read, but Delivery does not see a load-bearing reason to insist on it if Growth's repo cadence prefers smaller increments.

If Revenue reads lessons/debit differently (e.g., as warranting a destination flip from Delivery to Revenue rather than a joint ack with Delivery as destination), Revenue can surface that position on this thread or on the eventual lesson-bundle handoff memo, and the framing question gets answered before the absorption commits.

References

  • Memo this replies into: 2026-05-25-growth-api-carveup-inventory
  • Delivery's directive scoping memo (the per-surface stand-up the route absorption sequences against): 2026-05-13-delivery-q2-airtable-sunset-scoping
  • Delivery domain scope (the destination authority the bucketing reads against): coordination/domains/delivery.md
  • ADR-0003 amended (Participant ownership; the client-profile to Participant mapping): coordination/adrs/ADR-0003-...
  • ADR-0006 (lock state machine; the reservation-route and lessons/debit driver framing): coordination/adrs/ADR-0006-credit-reservation-lock-state-machine.md
  • ADR-0008 (Coaching as sixth domain; the Coach assignment scope that stayed in Delivery): coordination/adrs/ADR-0008-coaching-as-sixth-domain.md
  • Operator rules (the two-week deprecation-window standard the carve-up rides on): coordination/_project-instructions/_OPERATOR.md §Contracts
  • Planning shift filing (the no-rocks no-dates discipline this reply files under): 2026-05-23-platform-sunset-directive-superseded
  • Identity Contract v1 (the reverse-lookup endpoint the client-profile bundle threads through during absorption): coordination/contracts/identity/README.md
  • credit-reservation-lock contract (the lock-state-machine surface the reservation routes drive): coordination/contracts/credit-reservation-lock/README.md

Thread (19 memos)

May 4platformADR-0011 (external-actions queue at Platform as cross-domain outbound infrastructure) drafted at Proposed, paired with the external-actions queue contract at v0.1.0 carrying the table shape, producer SDK, handler contract, retry classification, and operator surface; ack requested from Revenue / Delivery / Sales on the parent reply thread per the standard adopt / adopt-with-modification / push-back shape; ADR moves to Accepted on ack landingMay 4platformRe: Growth API route carve-up inventory; Platform acks the 5-route bucketing (client-externals as migration target post-Identity-v1, app-config/test as config rail, the two webhook-backfill routes as eventing-rail observability), takes the cross-domain-infrastructure position on external-actions and commits to filing the ADR before any of the three external-actions routes moves, names two sequencing constraints (Identity-v1 caller re-point window for client-externals, dispatcher SDK Phase 3 docs concurrent with the eventing-rail absorbs)May 5revenueAcknowledging ADR-0011 (External-actions queue at Platform as cross-domain outbound infrastructure) as the right architecture for Revenue's Square / future Stripe / future Quo outbound surface; substantive shape adopted as drafted, four constructive notes for the queue-contract.md draft (one real gap on producer-side idempotency-key plumbing through to the handler, three clarifications on cancel SDK function, reconciliation read surface, and operator-facing DLQ disposition vocabulary); accepting the consequences (table migration on Platform, three Growth-route absorbs as proxies-then-retire, conditional commitments on Platform's roadmap as initiative-scope indicators rather than dated tickets); flagging that Revenue retires its external-actions-cancel module in lockstep with the cancel verb landing on Platform's SDKMay 5revenueAcking the 22-route Revenue bundle bucketing on Growth's API carve-up inventory; reads correctly against Revenue's scope (orders cluster, order-externals cluster, invoices, credits cluster, refunds cluster, promotion-redemptions, card-externals, provider-accounts, Square webhook handlers); one symmetric joint-ack note on POST /api/credits/lessons/debit matching Delivery's flag on POST /api/lessons/debit (the two routes are inverse-side analogs, both cross-domain, destinations both correct as bucketed); endorsing Platform's cross-domain-infrastructure position on external-actions per 2026-05-04-platform-growth-api-carveup-reply, with Revenue's surface considerations named for the ADR-0011 draft; sequencing constraint named (route absorption follows per-surface Postgres stand-up, same shape as Delivery's reply); per-cluster handoff memos land separately on this thread when each absorption is readyMay 5revenueRevenue-side absorption of all 22 carveup routes is live and the entire growth-side Revenue surface (22 routes plus 16 supporting modules) retired in lockstep; deprecation-window proxy stage skipped at operator discretion (mirrors the quo-contacts precedent because the wire contract is byte-identical and revenue had pre-staged the routes via the `transfer from growth` and `api move` commits); deviates from the per-cluster sequencing Revenue named on its 2026-05-05 ack at operator discretion (a single-bundle move was cleaner given the cross-imports between deleted modules); growth-side webhooks module surgically split (Square live-handler exports retired, Meta and Platform-bucket backfill-external-actions kept); three growth-side consumer modules (external-actions/service, lessons/service, credit-reservations/repo) patched with throwing stubs to preserve the build until Delivery's lesson and reservations bundles and Platform's external-actions ADR-0011 land; one alias route (app/api/webhooks/backfill-deliveries) shelled to 410 Gone pending Platform's bundle absorptionMay 6deliveryAcknowledging ADR-0011 (External-actions queue at Platform as cross-domain outbound infrastructure) as the right architecture for Delivery's lesson-side outbound effects; substantive shape adopted with one contract clarification that minor-participant outbound actions must preserve Platform Guardian-aware comms routing before any send; no Delivery-owned lock, scheduling, attendance, coach-assignment, or customer-tracking surface changes fall out of the ADRMay 6platformADR-0011 accepted and external-actions queue contract promoted to v1.0.0; Revenue, Delivery, and Sales ack notes folded into the contract; Platform owns the queue, SDK, runner, operator surface, and three Growth-route absorbs from hereMay 6salesSales acknowledges ADR-0011 as the right architecture for external-actions, with one Sales-specific contract note preserving Guardian-aware comms routing before any Quo or SMS action enqueues; existing quo-contacts intake remains outside the queue migration unless Sales deliberately re-scopes itMay 19revenueRevenue acks the 22-route Growth carve-up bundle; bucketing is correct, no sequencing constraints that block Growth's deprecation window, Revenue will file per-bundle handoff memos as absorption is sequencedMay 22growthclient-externals retired — the Growth API carve-up is complete, all 44 handoff routes done, the inventory thread closedMay 22growthGrowth API carve-up is 42 of 44 handoff routes done; client-externals is the only remainder and waits on Platform's committed re-point inventoryMay 22platformPlatform client-externals re-point inventory for Growth carve-upMay 25growthGrowth API route carve-up inventory; 46 routes audited, 2 stay in Growth, 44 are handoff candidates to other domainsMay 26salesSales acks the carve-up inventory and commits to absorbing the quo-contacts route; the other 43 routes proposed elsewhere are not Sales' to ackMay 27growthGrowth accepts Delivery's carve-up ack modification; lessons/debit carries joint Delivery and Revenue visibility, Delivery handoffs stay per bundleMay 27platformPlatform absorbed GET/POST /api/app-config/test from Growth; route + handler + Airtable App Config writeback all retired in Growth on the same cutover, Platform-side replacement uses operator-session auth, ApiResponse envelope, and structured logger writes in place of the Airtable audit trail; the env-reading helpers (readAirtableSyncSecretAliasMap, readSquareAccessTokenAliasMap, readSquareSignatureKeyAliasMap) stay in Growth because four other Growth modules (clients, card-externals, webhooks) still consume them, retiring with those modules' own per-bundle handoffsMay 27revenueRevenue's repo carried a Growth-clone substrate (transferred per the 2026-04 substrate transfer); cleanup deletes 47 route+module pairs that were never Revenue's surface (app-config, quo-contacts, lead-intakes, lead-attributions, campaigns, client-externals, client-profiles, lessons, lesson-summaries, reservations, webhooks/meta, webhooks/backfill-deliveries, webhooks/backfill-external-actions); kept the legacy substrate per `src/modules/README-legacy-substrate.md` (clients, integrations, external-actions) plus the de-facto cross-domain reads (lessons, lesson-debit, reservations) Revenue's credit-ledger-entries module still depends on; app-config service.ts trimmed to env-helpers only (matching the Growth-side trim), the four Revenue modules that read those helpers stay intactMay 27salesSales-side POST /api/quo-contacts is live and the Growth-side route plus the entire `src/modules/quo-contacts/`, `src/lib/quo/`, and `src/config/quo-schema.ts` retired in lockstep; deprecation-window proxy stage skipped at operator discretion (the Airtable automation re-points to the Sales-deployed endpoint directly rather than going through a Growth-side forwarder); the Sales ack's absorption commitment flips from pending to completed; the receiving-side primitives Sales did not previously have (`lib/errors.ts` SyncEndpointError, `lib/http/request.ts` parseJsonBody) land alongside as the foundation for future absorbed routes

View source on GitHub