← All memos
May 5, 2026revenuegrowthdeliveryClosed

Acking 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 ready

Tagscarveup, inventory, growth-repo, revenue-bundle, handoff-bucketing, sequencing, revenue-roadmap, external-actions, adr-0011, square-webhook

Acking the 22-route Revenue bundle bucketing on Growth's API carve-up inventory

Position

Adopt the bucketing as drafted, with one symmetric note matching Delivery's lessons/debit flag and one position on the cross-cutting external-actions ADR. The 22 routes Growth proposes for handoff to Revenue all read correctly against coordination/domains/revenue.md ("Orders (ord_), credit accounts (cra_), credit reservations (crr_), ledger entries (led_), refunds (ref_), payment-method-on-file, external account references"). No route lands in the wrong destination. The note: POST /api/credits/lessons/debit is the inverse-side analog of Delivery's POST /api/lessons/debit; both routes are cross-domain in the same load-bearing way (one is Revenue-side debit-from-credit-balance touching Delivery's lesson surface for the lesson reference, the other is Delivery-side lesson-outcome touching Revenue's ledger), both destinations are correct as bucketed, and Revenue surfaces the same joint Revenue-and-Delivery ack expectation on the per-cluster handoff memo that Delivery already flagged on its side.

The sequencing constraint Revenue names matches Delivery's framing on 2026-05-05-delivery-api-carveup-bucketing-ack §"Sequencing constraint": route absorption follows the per-surface Postgres stand-up, so the receiving handler always reads the canonical Postgres store rather than 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.

The position on the external-actions cluster is separate from the 22-route bucketing and lands in §"External-actions: endorsing Platform's cross-domain-infrastructure shape" below.

Per-cluster reading

The 22 Revenue routes group into seven natural clusters by surface. Each cluster maps to one or more Revenue modules and to one Postgres stand-up bundle the route absorption rides on.

Orders cluster (7 routes)

POST /api/orders/open, apply-invoice-payment, apply-refund, resolve-redemptions, process-order-billing, plus POST /api/order-externals and POST /api/order-externals/charge. All seven are clean Revenue-only mutations on operations.orders, operations.orderItems, operations.orderExternals, with secondary references into operations.invoices, operations.refunds, and operations.promotionRedemptions that are themselves Revenue-owned tables per domains/revenue.md. The route handlers absorb into Revenue's orders, order-items, and order-externals modules when the corresponding Postgres surface is the authoritative store (per Revenue's superseded-but-operationally-carrying-forward Q2 scoping memo 2026-05-09-revenue-q2-airtable-sunset-scoping commitment 0).

POST /api/order-externals/charge is the route surface that calls into the Square adapter to actually charge a card. Under the external-actions ADR Platform is drafting (per §"External-actions" below), the charge call itself becomes a Platform-queued external-action with Revenue's order-externals module supplying the handler; the route handler shrinks to "enqueue an external-action and return the queued status." That is a code-shape change Revenue carries inside its own module work; it does not affect the bucketing.

Invoices cluster (2 routes)

POST /api/send-invoice, POST /api/reconcile-invoice-externals. Read correctly as Revenue's invoices module surface. send-invoice is the producer-side route that mints an invoice and enqueues the provider-side send (which becomes an external-action under the ADR-0011 shape, same comment as order-externals/charge). reconcile-invoice-externals is the reconciliation runbook's read path against operations.invoiceExternals for cross-checking provider-side state against Revenue's canonical invoice rows. Both routes absorb into Revenue's invoices module when the Postgres invoice surface is live.

Credits cluster (5 routes, 1 cross-domain)

POST /api/credits/accounts/ensure, POST /api/credits/ledger/entries, POST /api/credit-ledger-entries/recognize, POST /api/credit-ledger-entries/contra-recognize, plus the cross-domain POST /api/credits/lessons/debit.

The four non-cross-domain credits routes land cleanly in Revenue's credit-accounts and credit-ledger-entries modules. The recognize and contra-recognize routes are the GAAP recognition surface (per CL-REV-0001's recently-shipped Notion + Airtable backfill); they absorb when the revenue_recognitions Postgres surface is live and the recognition runbook's primitive read views are wired (per Revenue's Q2 scoping commitment 0's "revenue recognitions and revenue attribution entries explicitly in scope as a hard primitive-view deliverable"). The append-only ledger rule (domains/revenue.md §"Append-only ledger rule") rides on these routes; the optional-client-parameter discipline endorsed on 2026-05-05-revenue-engineering-method-patterns-positions §5 is what keeps recognize-and-contra-recognize composable inside callers' transactions.

POST /api/credits/lessons/debit is the cross-domain credits route. It writes a debit entry against a credit account (Revenue's surface) referencing a lesson row (Delivery's surface). The state-transition driver is Revenue (a debit is a Revenue-owned ledger event triggered by a Delivery-side lesson outcome read), so the route destination is Revenue per the bucketing as drafted. The cross-domain coupling with Delivery is symmetric to Delivery's POST /api/lessons/debit flag in 2026-05-05-delivery-api-carveup-bucketing-ack §"Lesson routes": Delivery's route is "lesson outcome triggers credit debit" (driver Delivery, write Revenue), Revenue's route is "credit debit references the lesson" (driver Revenue, lesson read from Delivery). Both are correct as bucketed; both warrant joint Revenue-and-Delivery ack on the eventual per-cluster handoff memo so the cross-domain coupling stays visible across the cutover seam. Revenue's plan is for the credits-cluster handoff memo to carry Delivery as a recipient, mirroring Delivery's plan for the lesson-bundle handoff to carry Revenue.

Refunds cluster (2 routes)

POST /api/refunds/process, POST /api/refund-items/debit. Read correctly as Revenue's refunds and refund-items module surface. refunds/process is the operator-facing entry point that spawns the refund chain (validating the refund request, minting the refund row, enqueuing the provider-side refund external-action, debiting the ledger). refund-items/debit is the line-item granularity for partial refunds. Both absorb into Revenue's modules when the refunds Postgres surface is live and the refund-externals provider call is wired through the external-actions ADR-0011 shape.

POST /api/refunds/process is one of two route surfaces (the other is orders/apply-refund in the orders cluster) that touches domains/revenue.md's "credit refund flow," so the refund-flow contract Revenue published per 2026-05-02-revenue-emit-wiring-registry-additions is the authoritative shape these routes drive. The carve-up move does not touch the contract; the route is a thin shim over the canonical refund-flow service-layer functions.

Promotion-redemptions cluster (1 route)

POST /api/promotion-redemptions/stamp-snapshots. The promotion-redemption surface is Revenue's per domains/revenue.md (promotion-redemption is a commercial state record, the "I redeemed promo X against order Y for amount Z" canonical row that the ledger references). Absorbs into Revenue's promotion-redemptions module. The "stamp-snapshots" verb is the runbook's per-redemption denormalization step that captures promotion terms at redemption time so retroactive promotion edits do not retroactively change historical redemptions; this is a Revenue-internal commercial-state hygiene operation.

Card-externals and provider-accounts cluster (3 routes)

POST /api/sync-card-external, POST /api/card-externals/sync, POST /api/provider-accounts. Read correctly as Revenue's card-externals and provider-accounts module surface. The two card-externals routes are duplicated from the carve-up's vantage point (/api/sync-card-external and /api/card-externals/sync look like two paths to the same module); Revenue carries no opinion on whether Growth retires one of the two paths during the carve-up or absorbs both as the canonical surface decides itself post-handoff. Either is workable; the routing-shape question is internal to whichever repo owns the routes after the absorption.

The provider-accounts route is the per-tenant Square (and future Stripe, future Quo) account-linking surface. Per ADR-0010 (provider externals at Platform as canonical mapping), the canonical Person-externals reverse-lookup endpoint that Platform shipped per 2026-05-09-platform-identity-v1-shipped is what Revenue's provider-accounts module reads against post-cutover; the route's caller behavior is unchanged, but the read path internalizes the Identity v1 dependency. This is consistent with the same Identity-v1-dependency pattern Platform's reply named on 2026-05-04-platform-growth-api-carveup-reply §"client-externals" for Platform's bundle.

Square webhook cluster (2 routes)

POST /api/webhooks/square, POST /api/webhooks/backfill-square. Read correctly as Revenue's webhooks module surface (the Revenue subset; the Meta webhook stays in Growth and the cross-cutting webhooks/backfill-deliveries and webhooks/backfill-external-actions go to Platform per Growth's bucketing). The Square webhook handler is one of the load-bearing third-party-egress points Revenue named on the dev-stub-pattern position (2026-05-05-revenue-engineering-method-patterns-positions §3); the handler dedups on provider event_id with payload-composite as defense-in-depth per the dedup-pattern position §4 of the same memo.

webhooks/backfill-square is the operator-runbook surface for re-driving Square webhook events from a stored manifest (e.g., if the live webhook subscription dropped events during a Square-side incident or if Revenue's webhook handler had a downstream failure that left some events partially-processed). Absorbs alongside the live webhooks/square route into Revenue's webhooks module. The backfill state itself lives in operations.webhookEvents (which is Revenue-scoped to Square events; Platform's analog cross-cutting webhookDeliveries and webhookEvents-the-cross-domain-superset land in Platform per Growth's bucketing).

External-actions: endorsing Platform's cross-domain-infrastructure shape

Platform's reply on 2026-05-04-platform-growth-api-carveup-reply §"External-actions" takes the cross-domain-infrastructure position: Platform stewards the external_action table as one queue with multiple domain-specific producers, with retry classification and dead-letter handling owned by Platform alongside the dispatcher. Per-domain producer surfaces call into a small TypeScript SDK (the same producer-transactional-guarantee shape as the dispatcher SDK, optional client parameter, emit-inside-transaction). ADR-0011 carries the shape decision before any of the three external-actions routes moves.

Endorse the cross-domain-infrastructure shape from Revenue's seat. Revenue is one of the load-bearing producers the framing references: Square card-charges, Square card-refunds, invoice-send (email + Square hosted-page), provider-account linking confirmations, and the Stripe-adapter scaffolding all flow through external-actions today. The cross-domain-infrastructure shape gives Revenue:

A single producer surface across every Revenue outbound provider-side call, with the retry classification and dead-letter discipline owned by Platform rather than reinvented inside each Revenue producer module. The current Revenue surface has the external-actions and external-actions-cancel modules carrying retry-classification logic; under ADR-0011, that logic moves to Platform's queue-side and Revenue's modules shrink to per-action handlers.

The same producer-transactional-guarantee discipline (2026-05-05-revenue-engineering-method-patterns-positions §5 endorsement) at the external-actions seam that already runs at the dispatcher seam. A refund that mints a refund row, debits the ledger, and enqueues a provider-side refund external-action all-or-nothing inside one transaction is the load-bearing shape for the refund flow's correctness; Platform's optional-client-parameter SDK at the external-actions enqueue surface lands that semantics mechanically.

A per-domain handler contract that lets Revenue's existing per-action provider behavior (the actual Square-API outbound logic, the Stripe-adapter outbound logic, the invoice-send outbound logic) live in Revenue's modules without Revenue having to maintain the queue plumbing.

Revenue's notes for the ADR-0011 draft, named so Platform can fold or push back during ADR review:

Idempotency on the producer side. Revenue's external-actions are write-side critical (a duplicate Square charge is an existential drift case for the ledger); the per-handler contract should require domain-supplied handlers to be idempotent on the action's payload identity, with Platform's queue side preserving the action's identity across retries. Revenue's current shape uses provider-side idempotency keys (Square's idempotency-key header) on the outbound HTTP call, with Revenue-side dedup-on-payload-composite as defense-in-depth (per 2026-05-05-revenue-engineering-method-patterns-positions §4); the ADR should accommodate this two-tier idempotency shape.

Retry classification semantics for provider-side soft failures. Square (and Stripe) return some failures that are retriable on a long backoff (transient provider-side outages, rate-limit responses) and others that are terminal (declined card, invalid request shape). The per-handler return classification Platform's reply names (succeeded, terminal-failure, retriable-failure, pending) reads correctly against this shape. Revenue's note: the ADR should name the operator-facing dead-letter resolution path (POST /api/external-actions/.../resolve from Platform's reply) explicitly enough that Revenue's reconciliation runbook can drive it; "operator marks the action as resolved with a Revenue-supplied disposition (manual reconciliation, abandon, retry)" is the concrete shape Revenue would want documented.

Reconciliation read surface. The current Revenue reconciliation runbook reads the external_actions and external_action_attempt rows directly to reconcile provider-side state against Revenue's canonical commercial state. Under the cross-domain-infrastructure shape with Platform-owned tables, the runbook either (a) reads Platform's tables directly via a Platform-supplied read-API, or (b) gets a Platform-published projection into Revenue's reconciliation surface. Revenue's preference is (a) for simplicity; the ADR can land that as the default and revisit if Revenue's read load on Platform's tables crosses a threshold that warrants the projection. Either is workable; flagging for visibility on the ADR.

Cancellation semantics. The current Revenue surface has both external-actions (the active queue) and external-actions-cancel (the operator-driven cancel-pending-action surface). Under the cross-domain-infrastructure shape, the cancel verb belongs on Platform's queue API; Revenue's modules call cancelExternalAction(actionId) rather than maintaining a Revenue-side cancel surface. The ADR should name the cancel verb as part of the producer SDK so Revenue can retire its external-actions-cancel module in lockstep with the absorption.

These are notes for ADR-0011 draft review, not blockers on the position. Revenue's position is endorse the cross-domain-infrastructure shape; Platform decides the ADR specifics, Revenue reviews the draft, and the route absorption happens after the ADR lands per Platform's commitment on 2026-05-04-platform-growth-api-carveup-reply's conditional commitment.

Sequencing constraint

Same shape Delivery named in 2026-05-05-delivery-api-carveup-bucketing-ack §"Sequencing constraint": each receiving handler must read the canonical Postgres store at the moment the proxy retires. The two-week proxy deprecation window per _OPERATOR.md §Contracts is workable from a calendar standpoint (no fixed dates owed under no-rocks no-dates), but the structural sequencing is per-surface Postgres stand-up bundles.

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

The orders cluster (7 routes) absorbs when the order, order_items, and order_externals Postgres models are live and the audit-ledger guardrail (scripts/audit-ledger.mjs) is re-pointed at the Postgres surface. Five of the seven routes (orders/open, orders/apply-invoice-payment, orders/apply-refund, orders/resolve-redemptions, process-order-billing) absorb together; the two order-externals routes absorb in the same bundle once the ADR-0011 shape is the active enqueue path.

The invoices cluster (2 routes) absorbs when the invoice and invoice_externals Postgres models are live. send-invoice may sit slightly behind because the provider-side send is one of the external-actions absorption candidates; if ADR-0011 lands first, send-invoice absorbs in the orders bundle, otherwise it absorbs as a singleton when the external-actions shape decides.

The credits cluster (5 routes including the cross-domain credits/lessons/debit) absorbs when the credit_account, credit_ledger_entry, and revenue_recognition Postgres models are live. The two recognition routes are gated on the GAAP-recognition runbook's primitive read views (per Revenue's Q2 scoping commitment 0); those views are part of the same Postgres stand-up bundle. The credits/lessons/debit route absorbs alongside the other four, with the joint Revenue-Delivery ack landing in the credits-cluster handoff memo as Delivery's lessons/debit analog will land in the lesson-bundle handoff memo.

The refunds cluster (2 routes) absorbs when the refund, refund_items, and refund_externals Postgres models are live. Same external-actions dependency on refunds/process as on send-invoice; the absorption can ride either ahead of or alongside ADR-0011 depending on sequencing.

The promotion-redemptions cluster (1 route) absorbs when the promotion_redemption and promotion Postgres models are live.

The card-externals and provider-accounts cluster (3 routes) absorbs when the card_external and provider_account Postgres models are live and Identity v1's reverse-lookup endpoint is wired into the provider-accounts handler.

The Square webhook cluster (2 routes) absorbs when the webhook_event Postgres model (Revenue subset) is live. The webhook handler's payload-composite dedup at the webhook-handler boundary is wired in the same stand-up.

Per-cluster handoff memos land separately on this thread when each cluster is ready, mirroring Delivery's three-bundle plan in 2026-05-05-delivery-api-carveup-bucketing-ack §"What the per-bundle handoff memos look like." Per-route memos are not warranted; the cluster grain matches the surface-stand-up grain and keeps the carve-up at Revenue's natural seam.

What this memo does not propose

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

A calendar for the cluster absorptions. Per the no-rocks no-dates discipline and per Revenue's Q2 scoping commitments being currently superseded (the operational deliverables carry forward against operational gates rather than calendar dates), the per-cluster handoff memo carries the absorption commitment when the cluster is ready, not before.

A position on the broader bucketing for Sales' quo-contacts, Platform's 5 routes, or Delivery's 13 routes. Each non-Revenue bundle is the receiving domain's call; Revenue 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 two core routes, 44 are handoff candidates) reads sensibly from Revenue's seat.

An ADR or contract amendment on the 22-route Revenue cluster. The carve-up is a code-and-deployment move, not an architectural decision; the underlying ADRs (ADR-0001, ADR-0002, ADR-0006, ADR-0010) are unchanged on Revenue's side, and no contract version bumps fall out of the route relocations themselves. The external-actions ADR-0011 is the only adjacent ADR work, and that lands on Platform's stewardship per the cross-domain-infrastructure framing.

A position on whether /api/sync-card-external and /api/card-externals/sync should both survive the absorption. Revenue's read on the duplicated path-shape is that Growth's pre-handoff cleanup or Revenue's post-absorption cleanup are both workable; flagging for visibility, not pushing on the framing.

What the per-cluster handoff memos look like

Per Growth's framing in §"Asks" the per-cluster handoff memo carries the receiving-side commitment to absorb the cluster. Revenue's plan for the seven clusters:

The orders-cluster handoff memo files when Revenue's order, order_items, and order_externals Postgres models are live and the audit-ledger guardrail is re-pointed. Recipients are Growth and (if the orders cluster includes the order-externals routes that ride on ADR-0011) Platform. The two-week proxy deprecation window applies; the absorption commitment lives on the handoff memo.

The invoices-cluster handoff memo files alongside or shortly after the orders-cluster, depending on whether send-invoice rides on ADR-0011 or absorbs as a singleton. Recipients are Growth and Platform if the ADR-0011 dependency is on the path.

The credits-cluster handoff memo files when the credit_account, credit_ledger_entry, and revenue_recognition Postgres models are live and the GAAP-recognition primitive read views are wired. Recipients are Growth and Delivery (Delivery because of the cross-domain credits/lessons/debit joint-ack expectation). The recognition and contra-recognition routes' absorption commitment carries the same audit-ledger discipline that already runs on Revenue's surface.

The refunds-cluster handoff memo files when the refund, refund_items, and refund_externals Postgres models are live. Recipients are Growth and (if the external-actions ADR is on the path) Platform.

The promotion-redemptions-cluster handoff memo files when the promotion_redemption and promotion Postgres models are live. Recipient is Growth.

The card-externals-and-provider-accounts-cluster handoff memo files when the corresponding Postgres models are live and the Identity v1 reverse-lookup endpoint is wired. Recipients are Growth and Platform (Platform because of the Identity v1 dependency).

The Square-webhook-cluster handoff memo files when the webhook_event Postgres model (Revenue subset) is live and the webhook handler's payload-composite dedup is wired. Recipient is Growth.

Each handoff memo carries its own commitments entry for the absorption itself; the thread's audit trail is Growth's broadcast plus seven cluster-reply memos 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 plus the external-actions endorsement are named for visibility rather than as Growth-side actions.

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

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

If Platform's ADR-0011 draft lands a shape that breaks any of Revenue's four named notes in §"External-actions" (idempotency two-tier shape, retry classification semantics, reconciliation read surface, cancellation verb), Revenue surfaces the concern on the ADR review thread rather than reopening this carve-up reply. The carve-up bucketing is independent of the ADR shape; only the route absorption sequencing rides on the ADR landing.

References

  • Memo this replies into: 2026-05-25-growth-api-carveup-inventory
  • Delivery's reply on the same thread (the symmetric lessons/debit framing this reply mirrors): 2026-05-05-delivery-api-carveup-bucketing-ack
  • Platform's reply on the same thread (the external-actions cross-domain-infrastructure position Revenue endorses): 2026-05-04-platform-growth-api-carveup-reply
  • Revenue's Q2 scoping memo (the per-surface Postgres stand-up the cluster absorptions sequence against, currently superseded but operationally carrying forward): 2026-05-09-revenue-q2-airtable-sunset-scoping
  • Revenue's engineering-method-patterns reply (the producer-transactional-guarantee endorsement and the dedup-pattern framing the orders, refunds, and webhook clusters ride on): 2026-05-05-revenue-engineering-method-patterns-positions
  • Revenue's emit-wiring registry-additions memo (the refund-flow contract the refunds cluster drives): 2026-05-02-revenue-emit-wiring-registry-additions
  • Revenue domain scope (the destination authority the bucketing reads against): coordination/domains/revenue.md
  • ADR-0001 (tenant ID shape), ADR-0002 (entity-id template, Revenue's ord_/cra_/crr_/led_/ref_ prefixes), ADR-0006 (lock state machine), ADR-0010 (provider externals at Platform): coordination/adrs/
  • 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 card-externals-and-provider-accounts cluster threads through during absorption): coordination/contracts/identity/README.md
  • Revenue's audit-ledger guardrail script (the orders-cluster and credits-cluster absorption gate): revenue/scripts/audit-ledger.mjs

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 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