6.8 KiB
Endpoint I/O
Each product NATS address: what it is for, who sends, who receives, how to attach.
Connect with a long-lived client (reconnect-per-message is the anti-pattern):
NATS_URL=nats://10.10.10.21:4222,nats://10.10.10.22:4222,nats://10.10.10.23:4222
Public edge (token in /etc/nats/public-edge.token on NS1): nats://<token>@70.88.205.138:4222. Do not put that URL in Zapier or in Verae.
verae.zapier.jobs.watch
| For | Work queue: “poll Verae until this jobId is terminal.” |
| In from | middleware enqueueWatch after POST /api/timestamp (or mock) returns jobId |
| Out to | job-poller worker (queue job-poller, durable on ZAPIER_JOBS) |
| Then | poller calls Verae GET /api/status/{jobId} over HTTPS, not NATS |
Payload: tenantId, veraeUserId, jobId, tokenRef, enqueuedAt, attempt, maxAttempts, intervalMs, traceId. JWT stays in middleware (tokenRef); never on Zapier.
Connect Verae-side: do not subscribe this from api.veraetime.net. The poller is the Verae HTTP client. To add another watcher, start another job-poller consumer in the same queue group.
verae.zapier.jobs.events
| For | Terminal outcomes: timestamp.completed / failed / timeout |
| In from | job-poller after Verae status is not pending |
| Out to | (1) middleware waitForJobEvent (wait HTTP); (2) webhook router → webhooks.deliver; (3) optional verae-jobs-events mailbox :3030 |
If JOBS_EVENTS_EXCLUSIVE=1, only verae-jobs-events is the durable consumer and republishes verae.internal.jobs.events. Default lab: middleware wait + webhook worker share the stream.
Payload: event, tenantId, jobId, status, traceId, emittedAt.
verae.zapier.webhooks.deliver
| For | HTTPS POST to hooks.zapier.com (REST Hook) |
| In from | webhook worker on completed/failed events |
| Out to | Zapier cloud HTTPS, never NATS |
Payload: hookId, tenantId, targetUrl, event, payload, attempt, traceId. Slow consumer: keep replica floors on the worker if you split it out of middleware.
verae.zapier.usage
| For | Optional meter of Zap actions on NATS (JetStream) |
| In from | designed: middleware / edge |
| Out to | designed: USAGE_WRITER → books |
| Running | stream exists; no writer; middleware uses local usage files |
Prepaid meter that is wired uses verae.billing.usage.recorded (core pub), not this stream. Finish: either publish here from recordUsage or drop the stream.
Billing (verae.billing.*) — account-balance source of truth
Request-reply unless noted. Queue account-balance. Not JetStream.
| Address | For | In from | Out to |
|---|---|---|---|
statement.get |
prepaid, credits, usage, payments | portal, CS, sales, accounting, access-web/api | reply to requester |
balance.get |
cents only | internal | reply |
balance.adjust |
CS credit or portal reload | CS, access-web (reload kind only) | books + reply |
usage.recorded |
meter pub | zappier-edge meter() onUsage when NATS_URL set |
account-balance subscriber (debits prepaid) |
payment.recorded |
reload/invoice pub | portal | books |
credit.applied |
goodwill pub | CS/admin | books |
customer.put |
upsert customer | edge ledger | books |
Authz must pass verae.access.authz.check before these from a public plane. Leaf plane cannot call billing (policy).
Middleware recordUsage still writes local tenant files and does not publish usage.recorded. Two meters until that is unified.
Access planes
| Address | For | In | Out |
|---|---|---|---|
verae.access.authz.check |
allow/deny { plane, subject, principal } |
every plane + edge billing-nats.ts |
{ allow, reason }; deny also pubs authz.deny |
verae.access.authz.deny |
audit | authz on deny | nowhere yet (no SIEM) |
verae.access.web.in / verae.access.web.billing.* |
browser portal | access-web HTTP | statement.get / balance.adjust kind=reload after authz |
verae.access.api.* |
customer x-api-key |
access-api | statement; HTTPS to middleware for jobs |
verae.access.zapier.* |
Zapier HTTPS only | access-zapier | jobs.watch via HTTP to middleware, not Zapier NATS; usage.recorded allowed by policy |
verae.access.leaf.in |
S2S { token, target, payload } |
remote leaf | archive + jobs after authz; never billing |
verae.access.staff.* |
CS/sales/accounting | access-staff | billing after authz |
Ingress mapping: accessAddress(plane, 'verae.billing.statement.get') → verae.access.<plane>.billing.statement.get.
Identity
| Address | For | In | Out |
|---|---|---|---|
verae.identity.bind |
bind email/customerId → veraeUserId |
portal / middleware | reply |
verae.identity.lookup |
lookup by customerId or veraeUserId | same | reply |
Queue identity. Fleet keepFloor.
Archive / tree
| Address | For | In | Out |
|---|---|---|---|
verae.archive.put |
WORM/tree write (kind: publicMeta / privateMeta / file / tree) |
splitter (in-process from middleware today) | every worm/tree (JS) |
verae.archive.query |
broadcast lookup | aggregator | all worm/tree, no queue group |
verae.archive.reply.<correlationId> |
bloom hit only | worm/tree | aggregator |
Silence = miss. Chain seal does not wait on archive. Bytes never go to the chain.
Template / unused
| Address | For | In | Out | Running |
|---|---|---|---|---|
verae.splitter.in |
future split-out splitter process | middleware | splitter | no |
verae.example.process.in |
template worker | any | example-process Q |
no |
verae.example.process.out |
template fan-out | template | peers | no |
verae.example.process.reply.<id> |
template reply | template | requester | no |
verae.internal.jobs.events |
exclusive mailbox republish | jobs-events | wait/webhook | no unless env |
How to connect Verae API to NATS
api.veraetime.net is HTTPS. It does not subscribe. The glue is middleware:
- Set
VERAE_API_BASE_URL=https://api.veraetime.netandMOCK_VERAE=false. - Middleware login (username/password) → JWT stored as
tokenRef. POST /api/timestamp→ 202{ jobId }.- Publish
verae.zapier.jobs.watch. - Poller
GET /api/status/{jobId}untilcompleted/failed. - Publish
verae.zapier.jobs.events. - Wait HTTP and/or REST Hook.
Do not point Verae at NATS_URL. Do not put NATS in Zapier env. A new worker that must see seals uses jobs.events or HTTP GET /zapier/v1/status/{jobId}.
Template for a new addressed process: clone verae-nats-process, rename verae.example.process.*, add the subject to verae-access-authz policy for the plane that may call it.