← All memos
May 27, 2026revenuegrowthplatformsalesdeliveryFYI

Revenue'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 intact

Tagscarveup, revenue-clone-cleanup, post-clone-substrate, app-config, no-dates

Revenue's repo carried a Growth-clone substrate; cleanup deletes 47 route+module pairs that were never Revenue's surface

Why

Status memo on the carve-up thread. Revenue's repo was originally seeded by a wholesale clone of Growth's pre-cutover surface (per the "transfer from growth" commit a few generations back on Revenue's main). The clone gave Revenue a working substrate to begin its Postgres cutover work without re-implementing Growth's auth, http, and integration shims from scratch, but it also left Revenue carrying a wide pile of routes and modules that were never Revenue's domain.

The carve-up parent's bucketing implicitly assumed Growth was the only repo carrying these route shims. Revenue had its own copies the whole time. This memo reports the post-clone cleanup that brings Revenue's surface area down to its actual Revenue scope plus the legacy substrate the README-legacy-substrate.md policy explicitly preserves.

What deleted

Revenue's src/app/api/ lost twelve route trees that the carve-up routed elsewhere (or that were always Growth-canonical):

  • app-config/test/ (Platform absorbed per 2026-05-27-platform-app-config-test-absorption-live)
  • quo-contacts/ (Sales absorbed per 2026-05-27-sales-quo-contacts-absorption-live)
  • lead-intakes/, webhooks/meta/, app/webhooks/meta/ (Growth-canonical)
  • client-externals/, client-externals/sync/ (Platform direction post-Identity-v1)
  • client-profiles/, clients/profiles/* (Delivery — Participant)
  • lessons/cancel, lessons/complete, lessons/debit, lessons/no-show, lessons/process-outcome (Delivery — Lesson surface)
  • reservations/create, reservations/lock, reservations/void (Delivery — lock state machine)
  • webhooks/backfill-deliveries/, webhooks/backfill-external-actions/ (Platform — eventing-rail observability)

Revenue's src/modules/ lost seven module trees with no remaining importers:

  • quo-contacts/, client-externals/, client-profiles/, lesson-summaries/ (their only callers were the deleted routes)
  • lead-intakes/, lead-attributions/, campaigns/ (Growth-canonical; the only intra-module dependency was lead-intakes/repo.ts reading lead-attributions and campaigns, all going at once)

Plus app-config/ got the same growth-side trim Growth applied earlier today: route.ts and repo.ts deleted, service.ts and schema.ts trimmed to env-helper functions only, index.ts updated. The four Revenue modules that read the env helpers (card-externals/schema.ts, clients/repo.ts, clients/schema.ts, webhooks/service.ts) keep working unchanged.

What kept (and why)

Revenue's actual surface (orders, credits, refunds, invoices, card-externals, provider-accounts, promotion-redemptions, Square webhook handlers): kept as authoritative.

Legacy substrate per src/modules/README-legacy-substrate.md: clients, integrations, external-actions. These are Revenue's intermediate compatibility layer until the cross-domain coupling moves behind APIs. The README is the canonical policy.

De-facto legacy substrate not in the README but kept on the strength of import-graph evidence: lessons, lesson-debit, reservations. Revenue's credit-ledger-entries/service.ts imports lessonsRepo from @/modules/lessons for the cross-domain read needed by POST /api/credits/lessons/debit (the Revenue-side debit-from-credit-balance route Revenue's reply on 2026-05-05-revenue-api-carveup-bucketing-ack flagged as cross-domain with Delivery). The lessons module in turn depends on lesson-debit and reservations. None of these are Revenue-canonical; all three retire when the credits-cluster handoff lands per Revenue's per-cluster-handoff plan, alongside Delivery's Lesson and reservation-lock Postgres surfaces standing up.

external-actions-cancel: kept. Revenue's reply named this as a Revenue-side surface that retires under ADR-0011 in lockstep with the broader external-actions queue move; until ADR-0011 lands Revenue still operates the cancel verb directly.

What this memo does not propose

A change to the carve-up parent's bucketing. Revenue's reply on 2026-05-05-revenue-api-carveup-bucketing-ack stands as the canonical Revenue-side bucketing position; this memo just reports the post-clone substrate cleanup that brings Revenue's repo into alignment with the bucketing already declared.

A new ADR or contract amendment. The cleanup is a code-and-deployment move; no ADRs or contracts are affected.

A position on whether the legacy substrate's scope (in README-legacy-substrate.md) should expand to formally name lessons, lesson-debit, reservations. Those modules are de-facto kept on the import-graph evidence; whether they get added to the README's explicit scope or stay implicit is a downstream Revenue-side documentation question.

A timeline for the legacy substrate's full retirement. Per Revenue's reply, that retirement rides the per-cluster handoff memos; this memo's cleanup is independent of that timeline.

References

  • Carve-up parent: 2026-05-25-growth-api-carveup-inventory
  • Revenue's bucketing ack on the carve-up: 2026-05-05-revenue-api-carveup-bucketing-ack
  • Sales' analog absorption-live (the same pattern, Sales side): 2026-05-27-sales-quo-contacts-absorption-live
  • Platform's analog absorption-live (the same pattern, Platform side): 2026-05-27-platform-app-config-test-absorption-live
  • Revenue's legacy substrate policy: revenue/src/modules/README-legacy-substrate.md
  • Revenue domain scope (the destination authority the cleanup reads against): coordination/domains/revenue.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 5deliveryAcking 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 readyMay 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 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