Appearance
Monetization Broker Live Smoke
This smoke is the opt-in runtime proof for the Phase 16 monetization broker path. It exercises native service APIs directly; it does not promote any gateway route and does not edit deploy/gateway/routes.json.
Run the local monetization stack in NATS mode first:
bash
MONETIZATION_EVENT_TRANSPORT=nats docker compose -f deploy/docker-compose.yml up -d \
nats postgres-local payment-service wallet-service billing-service usage-serviceThen run the smoke:
bash
MONETIZATION_EVENT_TRANSPORT=nats \
MONETIZATION_BROKER_SMOKE_CONFIRM=broker-runtime \
make test-monetization-broker-liveThe default endpoints are:
| Service | URL |
|---|---|
| payment-service | http://localhost:8096 |
| wallet-service | http://localhost:8097 |
| billing-service | http://localhost:8098 |
| usage-service | http://localhost:8099 |
The script also defaults to the owner-service Postgres DSNs exposed by local Compose on port 5433. Override PAYMENT_DATABASE_URL or BILLING_DATABASE_URL only when the local stack uses different connection settings.
What It Proves
payment-servicecreates a disposableSUBSCRIPTIONorder and records a SePay provider webhook that persistspayment.order.paid.v1.- The payment outbox publishes through NATS JetStream and reaches
DELIVEREDin the payment owner database. billing-serviceconsumes the payment event, activates the subscription, persistsbilling.subscription.activated.v1andbilling.entitlements.updated.v1, and delivers those billing outbox rows.usage-servicematerializes the billing entitlement update and allows acredits_monthlyusage check.wallet-servicereceives the billing subscription activation and credits the subscription monthly grant.- A second disposable
WALLET_TOP_UPpayment verifies direct payment-to-wallet broker delivery. - Replaying the same subscription provider webhook returns a replay response without another payment transaction, billing activation/entitlement pair, or subscription credit grant.
Artifacts
Live runs write request, response, outbox, and summary JSON under:
text
output/qa/monetization-broker-live-smoke-<timestamp>/The summary records the run id, disposable account and organization ids, subscription id, payment paid event ids, expected wallet credits, and the fact that the smoke was invoked with MONETIZATION_EVENT_TRANSPORT=nats.
Latest Local Evidence
Captured on 2026-07-14 against a fresh isolated local Compose NATS stack:
text
output/qa/monetization-broker-live-smoke-20260714-075522/Summary:
| Check | Evidence |
|---|---|
| Subscription payment event | payevt_b5389ccdbae67b1c025eb635 delivered in payment outbox |
| Wallet top-up payment event | payevt_b0f218cd5ed29effc7b3aef8 delivered in payment outbox |
| Billing activation event | bevt_8d717d451add8a76714f0108 delivered with sourcePaymentEventId=payevt_b5389ccdbae67b1c025eb635 |
| Billing entitlement event | bevt_8d717d451add8a76714f0108_entitlements delivered from the linked subscription activation event |
| Usage check | credits_monthly allowed with limit 1200 and remaining 1199 |
| Wallet balance | 1977 available credits after 1200 subscription credits plus 777 top-up credits |
| Duplicate provider webhook | replay=true; one payment transaction, one delivered billing activation/entitlement pair, and wallet unchanged at 1200 before top-up |
Guardrails
MONETIZATION_BROKER_SMOKE_CONFIRM=broker-runtimeis required before the script writes native monetization records.MONETIZATION_EVENT_TRANSPORT=natsis required so HTTP fallback runs are not mistaken for broker proof.- The script reads payment and billing outbox state only through
tools/monetization-outbox, using the selected owner-service database DSN. - It does not read wallet or usage databases and does not perform cross-service database joins.
- Native monetization APIs do not currently expose delete endpoints, so cleanup is limited to unique disposable smoke account and organization identifiers plus the artifact bundle.
Use the cheap parser/self-test in regular checks:
bash
MONETIZATION_BROKER_SMOKE_SELF_TEST=1 bash scripts/test/monetization-broker-live-smoke.sh