Add developer credentials: URLs, lab keys, NATS token, staff IAM, git
This commit is contained in:
commit
f850002f1c
1 changed files with 3364 additions and 0 deletions
154
02-endpoint-io.md
Normal file
154
02-endpoint-io.md
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
# 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):
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
1. Set `VERAE_API_BASE_URL=https://api.veraetime.net` and `MOCK_VERAE=false`.
|
||||
2. Middleware login (username/password) → JWT stored as `tokenRef`.
|
||||
3. `POST /api/timestamp` → 202 `{ jobId }`.
|
||||
4. Publish `verae.zapier.jobs.watch`.
|
||||
5. Poller `GET /api/status/{jobId}` until `completed` / `failed`.
|
||||
6. Publish `verae.zapier.jobs.events`.
|
||||
7. 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.
|
||||
Loading…
Reference in a new issue