A map of the remaining build, pieced together from the context docs and a pass
over the code on master. Two asks: does this ordering look
right, and which pieces should I pick up — especially
on the testing / actually-using-the-API side.
Every "exists / missing" claim below was checked against the code as of today. Happy to be corrected on anything — this is me building a picture, not asserting one.
The docs describe one pipeline: a contract edit fans out through the outbox to OpenMeter (subscription → usage → invoice), which drives billing status and kicks off settlement in Modern Treasury. Here's the state of each link:
contract.created is ever writtenOrdered by dependency: 1–2 unblock everything downstream, 3–4 finish the contract→billing seam, 5–7 close the gaps in the payout path. 5–7 don't depend on 1–4 and could be picked up in parallel.
The outbox table is written to but nothing reads it — no poller, no
scheduler dependency, nothing ever sets published_at. A relay that reads
unpublished rows in order, dispatches to subscribers, and marks rows published only
when downstream effects succeed (idempotent retries keyed on event_id).
Why first: every downstream projection (OpenMeter sync, invoice handling) waits on this. It's the first background process in the API.
Only contract.created exists today. Product add/remove and status
transitions have TODO markers where events should be emitted, and a
ContractUpdatedEvent class exists but is never used. Payloads need enough
state (product/pricing deltas) for subscription sync.
Pairs with #1 — the relay is useless with nothing to relay, and vice versa. No dependency between them; could be one person's first two PRs or two people in parallel.
Provisioning already landed: activating a contract creates the OM subscription synchronously and stores the provider refs. What's missing: syncing anything after activation (product/pricing changes, suspend/terminate → subscription update/cancel), moving the projection onto the relay instead of an inline call, and retry on provisioning failure (currently just logged).
Depends on: #1 and #2.
Consume the invoice lifecycle (issued / paid / past-due) to drive the contract's
billing_status machine — today it's an inert free-form string. On paid,
hand off to settlement kickoff.
Step 2 of the documented payout happy path. The disbursement currently drains the
buyer's AVAILABLE balance directly; the COMMITTED /
COMMITTED_DOWNPAYMENT accounts are provisioned but nothing ever posts to
them. Add the commit recipe and release from COMMITTED in the journey.
Seller funds are supposed to sit in Pay-In Holding for a seasoning period; 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. Small task, real correctness win.
Payout creation works standalone (step 7 of the happy path), but it isn't stitched into the disbursement journey after holding release. Needs a small design choice: automatic cash-out on release vs. seller-initiated.
The doc specifies an event-sourced edit log; today it's snapshot-based, with only
4 of ~16 operations implemented (no financing, no bitemporality, no auto-renew
scheduler, service_status inert). Needs an architecture decision:
build the edit log, or amend the doc.
Partner/referral splits, tax, hosting fees + funding requests, free trials (NOTIONAL accounts), downtime credits, crypto slippage — everything in the funds-flow doc beyond bank pay-in and the seller-disbursement happy path.
Not started — enum members are commented out across the schema. Card pay-ins and the one accrual flow (settlement receivable). Deferred until the bank path is solid.
Device-health events → availability log → metering and downtime credits. Blocked on a design pass — depends on what Brokkr exposes.
ACH returns, failed payment orders, and settlement anomalies currently just alert Sentry ("no reconciliation pipeline yet" in two places). Auto-matching, retries, and a manual-review queue. Cross-cutting; grows with the flows.
You mentioned the team needs help testing / really exercising the API. Here's what I've done so far and where I think that effort is most useful next:
An internal client app (apps/testing-ui) that drives the API as a
platform operator: customer onboarding, wallets, settlements (with leg polling), and
payouts.
Honest question: is this shape useful to the team, or should the effort go into scripted journeys instead? Happy to hear "kill it" too.
As each item above lands, write the end-to-end journey that proves it — the way
hurl/ covers onboard→fund and settle→payout today. E.g. once #5–7 land:
one journey doing fund → commit → settle → season → cash out, asserting ledger
balances at each step.
Per-actor flows that run against a local API and could run in CI against sandbox. Immediate candidates: a journey for the OpenMeter path (activate → usage → subscription), failure-path journeys (ACH return, failed payout), and idempotency checks.
Rough edges, API ergonomics, missing validations, doc gaps — filed as small focused PRs or notes rather than a pile of complaints. Testing is only useful if the findings land somewhere.