Add NATS account-balance SoT and statement review for customers, CS, and sales
Some checks are pending
offline / test (push) Waiting to run

Internal billing now uses verae.billing.* request-reply and pubs. zappier-account-balance tracks prepaid, credits, usage, and payments. Portal, admin, CS, and sales all review the same statement. Independent Forgejo repos stay split via push-module-repos.
This commit is contained in:
George Lambert 2026-09-11 15:35:37 -04:00
parent a1a5b957fd
commit ac38676645
135 changed files with 3078 additions and 130 deletions

View file

@ -2,14 +2,19 @@
Master map of every service in the Zapier ↔ middleware ↔ chain ↔ WORM-archive path.
Zapier cloud **never** connects to NATS. Only middleware workers and archives do.
Zapier cloud **never** connects to NATS. Internal services do: middleware workers, archives, account-balance, zappier-edge billing, CS, sales, and accounting.
## Who talks to whom (HTTPS vs NATS)
```text
[Zapier Platform app] HTTPS [zappier-edge] HTTPS [middleware-http]
|
NATS JetStream (NS1 loopback :4222) |
| | NATS verae.billing.* |
| v |
[customer portal] [account-balance] NATS JetStream
[CS :3011] queue account-balance (NS1 loopback :4222)
[sales :3012] ^ |
[accounting :3013] | request-reply |
+-------------------------------+
+------------------+------------------+-------------+
| | |
[job-poller] [webhook-deliver] [archive-aggregator]
@ -25,7 +30,11 @@ Zapier cloud **never** connects to NATS. Only middleware workers and archives do
| Module | Repo (Forgejo) | Runtime | Listens | Sends |
|--------|----------------|---------|---------|-------|
| zapier-platform-app | `verae-zapier-app` | Zapier cloud | User Zap steps | HTTPS to zappier-edge |
| zappier-edge | `zappier-edge` | Public HTTPS :3000 | Zapier, portal, admin | HTTPS to middleware |
| zappier-edge | `zappier-edge` | Public HTTPS :3000 | Zapier, portal, admin | HTTPS to middleware; NATS billing pub |
| account-balance | `zappier-account-balance` | :3010 + NATS | `verae.billing.*` | statement/adjust replies |
| customer-service | `zappier-customer-service` | :3011 | CS staff HTTP | NATS balance.adjust / statement.get |
| sales-pricing | `zappier-sales-pricing` | :3012 | Sales HTTP | NATS statement.get; HTTPS to edge for multipliers |
| accounting-export | `zappier-accounting-export` | :3013 | Accounting HTTP | reads invoices; NATS statement |
| middleware-http | `verae-middleware` | Public HTTPS :3100 | zappier-edge | NATS jobs.watch; HTTP to chain; wait on jobs.events |
| job-poller | `verae-job-poller` | Worker | `verae.zapier.jobs.watch` | `verae.zapier.jobs.events`; HTTP GET chain status |
| webhook-deliver | `verae-webhook-deliver` | Worker | `verae.zapier.webhooks.deliver` + events | HTTPS POST Zapier REST Hook |
@ -49,6 +58,11 @@ Zapier cloud **never** connects to NATS. Only middleware workers and archives do
| `verae.zapier.jobs.events` | JetStream events | `event` (`timestamp.completed\|failed\|timeout`), `tenantId`, `jobId`, `status`, `traceId`, `emittedAt` |
| `verae.zapier.webhooks.deliver` | JetStream work queue | `hookId`, `tenantId`, `targetUrl`, `event`, `payload`, `attempt`, `traceId` |
| `verae.zapier.usage` | optional | `tenantId`, `action`, `amount`, `at` |
| `verae.billing.statement.get` | request-reply | `customerId` → prepaid, credits, usage, payments |
| `verae.billing.balance.adjust` | request-reply | `customerId`, `cents`, `reason`, `agent` |
| `verae.billing.usage.recorded` | pub | meter events from zappier-edge |
| `verae.billing.payment.recorded` | pub | portal reload / invoice paid |
| `verae.billing.credit.applied` | pub | CS goodwill |
| `verae.archive.put` | JetStream | `sha256`, `tenantId`, `kind` (`publicMeta\|privateMeta\|file\|tree`), `record`, `traceId` |
| `verae.archive.query` | pub to **all** archives | `correlationId`, `sha256`, `tenantId`, `kinds[]`, `traceId` |
| `verae.archive.reply.<correlationId>` | replies | `archiveId`, `sha256`, `records[]`, `traceId` |

View file

@ -0,0 +1,12 @@
# NATS — zappier-account-balance
Queue group `account-balance`. This process is the source of truth for prepaid cents.
| Direction | Address | Kind | Body |
|-----------|---------|------|------|
| IN | `verae.billing.statement.get` | request-reply | `{ customerId }` → statement |
| IN | `verae.billing.balance.get` | request-reply | `{ customerId }` → statement |
| IN | `verae.billing.balance.adjust` | request-reply | `{ customerId, cents, reason, agent, kind }` |
| IN | `verae.billing.usage.recorded` | pub | `{ customerId, endpointId, cents, at }` (debits prepaid) |
`payment.recorded` and `credit.applied` are fan-out events from publishers; prepaid mutations go through `balance.adjust`.

View file

@ -0,0 +1,3 @@
# zappier-account-balance
NATS source of truth for prepaid balances, credits, usage events, and payments.

View file

@ -1,3 +1,7 @@
# zappier-accounting-export NATS
# NATS — zappier-accounting-export
None.
| Direction | Address | Kind |
|-----------|---------|------|
| OUT | `verae.billing.statement.get` | request-reply (review) |
IIF/CSV export remains HTTPS to zappier-edge admin.

View file

@ -1,3 +1,5 @@
# zappier-accounting-export
Exports zappier invoices to QuickBooks IIF and accounting CSV.
Accounting export of invoices to QuickBooks IIF and CSV, plus **review** of customer credits, balances, usage, and payments over NATS.
Forgejo: https://git.georgelambert.org/marchon/zappier-accounting-export

View file

@ -1,3 +1,8 @@
# zappier-customer-service NATS
# NATS — zappier-customer-service
None. HTTPS only to zappier-edge admin.
| Direction | Address | Kind |
|-----------|---------|------|
| OUT | `verae.billing.statement.get` | request-reply (review) |
| OUT | `verae.billing.balance.adjust` | request-reply (credits) |
HTTP fallback: `ACCOUNT_BALANCE_URL` then zappier-edge admin. Zapier cloud never connects here.

View file

@ -1,3 +1,7 @@
# zappier-customer-service
CS department API for prepaid credit additions. Writes `balanceCents` on zappier-edge.
CS department API and UI for prepaid credit additions and **review** of credits, balances, usage, and payments.
Internal path: NATS `verae.billing.statement.get` / `verae.billing.balance.adjust` → account-balance. HTTP fallback to `:3010` then zappier-edge admin.
Forgejo: https://git.georgelambert.org/marchon/zappier-customer-service

View file

@ -1,3 +1,7 @@
# zappier-sales-pricing NATS
# NATS — zappier-sales-pricing
None.
| Direction | Address | Kind |
|-----------|---------|------|
| OUT | `verae.billing.statement.get` | request-reply (review) |
Pricing writes remain HTTPS to zappier-edge admin.

View file

@ -1,3 +1,5 @@
# zappier-sales-pricing
Sales department per-customer tier and multiplier. Writes through zappier-edge `/admin/api/customers`.
Sales department API and UI for per-customer tier/multiplier and **review** of the same NATS statement as CS and the customer portal.
Forgejo: https://git.georgelambert.org/marchon/zappier-sales-pricing

View file

@ -1,10 +1,15 @@
# NATS — zappier-edge
This process **does not subscribe or publish** on NATS.
Zapier cloud still never connects to NATS. The edge process **does** publish and request on the private billing bus.
| Direction | Address | Peer | Body |
|-----------|---------|------|------|
| IN HTTPS | `/v1/*` | Zapier Platform app | JSON + `x-api-key` |
| OUT HTTPS | middleware `/zapier/v1/*` | verae-middleware | same tenant request |
| OUT NATS | `verae.billing.usage.recorded` | account-balance | meter event |
| OUT NATS | `verae.billing.payment.recorded` | account-balance / others | portal reload |
| OUT NATS | `verae.billing.credit.applied` | account-balance / others | admin/CS credit |
| OUT NATS | `verae.billing.statement.get` | account-balance | portal/admin review |
| OUT NATS | `verae.billing.balance.adjust` | account-balance | prepaid mutation |
NATS is private to middleware workers and archives.
Jobs, archive, and webhooks stay on middleware workers.