Commerce / proposed Linear issues
draft · 2 Jul 2026

Twelve issues to get the ball rolling

The open Commerce projects in the Launch-v1 initiative currently have scope descriptions but no issues. These are concrete, code-grounded issues I'd propose opening under them — each sized to be one person's next PR or two, sequenced by dependency. Nothing here invents scope: every issue traces to a project description, the context docs, or a gap verified in the code.

Priorities are suggestions. Issues marked could take this are ones I'd volunteer for.

Commerce: Billing (Subscriptions)

backlog lead David · target was May 25 open in Linear ↗

The contract→OpenMeter seam. Subscription provisioning on activation already landed; these four finish the pipeline so a contract change reliably becomes an invoice.

1

Build the outbox relay / publisher

urgent

The outbox table is written but nothing consumes it: the dispatch hook is commented out, the unpublished-rows index has no reader, and published_at is never set. Add a relay (poller via @nestjs/schedule — not currently a dependency) that reads unpublished rows in insertion order, dispatches to subscribers, and marks rows published only when all downstream effects succeed.

  • Idempotent retries keyed on event_id; multiple independent subscribers.
  • First background process in the API — factor it so tests can drive one tick.
Blocks: #3, #4 · Depends on: nothing
2

Emit outbox events from every contract mutation

urgent

Only contract.created is emitted today. Product add/remove and status transitions have TODO markers where events belong, and a ContractUpdatedEvent class exists but is never used. Emit typed events (product_added, product_removed, status_changed, pricing changes) with payloads carrying enough delta for subscription sync.

Blocks: #3 · Pairs with: #1 (independent, parallelizable)
3

Relay-driven OpenMeter subscription sync (post-activation)

high

Provisioning-on-activation landed, but it's a synchronous inline call with no retry (failures are only logged), and nothing syncs changes after activation — product or pricing changes, suspend, terminate. Move projection onto the relay: consume contract.* events, create/update/cancel the OM subscription, retry on failure.

Depends on: #1, #2
4

Ingest OpenMeter invoice lifecycle → billing_status

high

OM cuts the usage invoice at cycle close; nothing in Commerce hears about it. Add the OM webhook handler (only the MT handler exists; wire OPENMETER_WEBHOOK_SECRET) and implement the billing_status state machine — pending → active → past_due → collections → closed — which today is an inert free-form string. On paid, hand off to settlement kickoff.

Depends on: #3 · Feeds: #5, settlement

Commerce: E-Invoicing

backlog lead David · target was Jun 1 open in Linear ↗

The MT-backed invoices module and the email module both landed recently — the foundation exists, but it's floating: no contract linkage, no dunning, no notifications.

5

Link e-invoices to contracts; generate from the OM usage invoice

high

The invoices module (create/finalize/void, line items, status sync) has no reference to contracts and no connection to OpenMeter. Add the contract linkage, and generate the customer-facing MT e-invoice (detail + payment page) from the OM invoice at cycle close — the bridge between "usage was billed" and "customer can pay".

Depends on: #4 (can start on contract linkage immediately)
6

Invoice notifications + dunning / overdue handling

medium

Email on invoice issued / due / overdue using the landed email module; escalate overdue invoices (drives billing_statuspast_due / collections). Scope per the project description's "Dunning/Overdue Invoice Handling".

Depends on: #5

Commerce: Balances (Wallets)

backlog lead David · target was Jun 8 open in Linear ↗
7

Committed-balance ledger step (AVAILABLE → COMMITTED)

high

The committed balance is the risk mechanism for untrusted buyers, and the project description names all three balance types — but the COMMITTED / COMMITTED_DOWNPAYMENT accounts are write-dead: provisioned, read in balance queries, never posted to. Every ledger recipe touches only AVAILABLE, and the disbursement journey drains AVAILABLE directly.

  • Add the commit recipe (earmark on contract commitment).
  • Release from COMMITTED, not AVAILABLE, in the settlement journey.
Depends on: nothing — parallelizable with #1–4

Commerce: Payouts

backlog lead David · target was Jun 16 open in Linear ↗
8

Seasoning window for holding release

medium could take this

Seller funds should sit in Pay-In Holding for a seasoning period before becoming spendable; today the release fires immediately (notBefore: new Date(), marked "follow up" in the code). The delayed-release machinery already honors notBefore — only the delay value is stubbed. Decide the source of the delay (per-contract term vs. config) and set it. Small, high correctness value; first brick of the project's "payout engine" (frequency / risk controls).

Depends on: nothing
9

Wire seller cash-out into the settlement journey

high could take this

Payout creation (wire/ACH payment order) works standalone but isn't stitched into the disbursement journey after holding release. Add the cash-out leg or trigger, including the design decision the project owns: automatic on release vs. seller-initiated ("how often / how you get paid out").

Depends on: #8 (loosely — order of legs)

Commerce: Unoriginated Pay-Ins

backlog lead David · target was Jun 10 open in Linear ↗
10

Expected-Payment flow: credit balances on inbound funds

high

RTP, wire, and stablecoin pay-ins are pushed by the buyer — we can't originate them. Build the Expected Payment flow: create the EP, reconcile the inbound MT transaction, credit the party's AVAILABLE on arrival (today's recipes only cover originated ACH), and expose account details so a customer knows where to push. Overdue EPs (expected_payment.overdue) surface for manual review.

Depends on: nothing · Feeds: stablecoin rails later

Needs a home — no matching project yet

proposal

Two pieces of work with no obvious project. Options: park under an existing project, or spin up a small project each — your call.

11

Reconciliation v0: returns, failed payment orders, overdue EPs

medium

Two places in the code literally say "no reconciliation pipeline yet" — ACH returns / failed POs and settlement-leg anomalies currently only alert Sentry. A v0: automated retry with backoff where safe, a manual-review queue for the rest. Grows with the funds flows; worth an early skeleton so anomalies have somewhere to land.

Candidate home: Payouts, or a new "Commerce: Reconciliation" project
12

End-to-end funds-flow journey suite (hurl)

medium could take this

Scripted journeys already cover onboard→fund and settle→payout. Grow this into the e2e proof of the flagship flow — fund → commit → settle → season → cash out — asserting ledger balances at every step, plus failure paths (ACH return, failed payout) and idempotency checks. Each issue above gets a journey as it lands; this is also how the "everyone actually uses the thing" goal gets teeth.

Candidate home: Observability and Monitoring, or Billing (Subscriptions)
Not proposed, deliberately: anything under Metering (in progress — Tristan's, would sync with him first), Reporting / Dashboards (parked until the money path works), Brokkr-side UI work (different codebase/team), and Airwallex (absent from the initiative — pending your confirmation that MT-native rails replaced it).

How I'd use this

If this list looks right, I'll open the issues under their projects with these descriptions (adjusted per your edits) and take #8, #9, and #12 as my starting assignments — small, independent, and each gives me a new flow to exercise end to end. #1 and #2 are the highest-leverage items for whoever knows the outbox design best.