Three-node NATS JetStream cluster on Proxmox LXC

This commit is contained in:
George Lambert 2026-09-11 23:48:02 -04:00
commit f8396325e4
72 changed files with 801 additions and 0 deletions

3
modules/overview/NATS.md Normal file
View file

@ -0,0 +1,3 @@
# NATS — overview
Documentation only. Describes the central 3-server cluster. Zapier never connects.

View file

@ -0,0 +1,3 @@
# overview
High-level system map, 3-node NATS cluster, uptime, network failure, address routing. Repo: `overview`.

View file

@ -0,0 +1,3 @@
# NATS — verae-access-api
Plane `api`. Statement and jobs.watch after authz. No credits, no archive.

View file

@ -0,0 +1,3 @@
# verae-access-api
Direct customer API (`x-api-key`). Separate from Zapier Platform.

View file

@ -0,0 +1,3 @@
# NATS — verae-access-authz
`verae.access.authz.check` request-reply. Queue `access-authz`. Fail closed.

View file

@ -0,0 +1,3 @@
# verae-access-authz
Default-deny authorization step on the NATS address path. Planes: zapier, web, api, leaf, staff.

View file

@ -0,0 +1,3 @@
# NATS — verae-access-leaf
`verae.access.leaf.in` → authz.check → `verae.archive.*` / jobs.*. Denied: billing.

View file

@ -0,0 +1,3 @@
# verae-access-leaf
Server-to-server NATS leaf ingress. Archive and jobs only. Never billing.

View file

@ -0,0 +1,3 @@
# NATS — verae-access-staff
Plane `staff`. Authz then billing statement/adjust.

View file

@ -0,0 +1,3 @@
# verae-access-staff
Staff plane for credits and statement review.

View file

@ -0,0 +1,3 @@
# NATS — verae-access-web
Plane `web`. Authz then `verae.billing.statement.get` / `balance.adjust` kind=reload.

View file

@ -0,0 +1,3 @@
# verae-access-web
Direct customer web plane. Not Zapier. Statement + reload only after authz.

View file

@ -0,0 +1,3 @@
# NATS — verae-access-zapier
Plane `zapier`. Authz then jobs.watch / usage.recorded. Zapier cloud never connects to NATS.

View file

@ -0,0 +1,3 @@
# verae-access-zapier
Zapier Platform HTTPS plane only. No portal, no admin, no leaf.

View file

@ -0,0 +1,10 @@
# NATS — verae-activate
This Zapier Platform app **does not use NATS**.
| Direction | Address | Peer | Body |
|-----------|---------|------|------|
| IN | Zapier UI / runtime | user Zap | `number1`, `number2`, `text`, `data` / `sha256` |
| OUT HTTPS (optional) | zappier-edge `/v1/add` or `/v1/timestamp` | only if `api_base` + `api_key` set | JSON |
Blank connection fields → local compute only.

View file

@ -0,0 +1,11 @@
# verae-activate (Zapier Platform app)
**Job:** Private Zapier integration you push first. Actions run in Zapier cloud.
**Expects:** User connection (API key optional).
**Sends:** nothing if fields blank (Add Numbers / Echo / SHA256 / Create Timestamp local mock). If `api_base` + `api_key`, HTTPS to zappier-edge.
**Does not** speak NATS.
**Test:** `npm test`; `zapier-platform validate`.

View file

@ -0,0 +1,8 @@
# NATS — verae-archive-aggregator
| Direction | Address | Peer | Body |
|-----------|---------|------|------|
| OUT | `verae.archive.query` | all WORM | `{ correlationId, sha256, tenantId, kinds[], traceId }` |
| IN | `verae.archive.reply.<correlationId>` | WORM hits | `{ archiveId, sha256, records[] }` |
Stop collecting at `WAIT_ARCHIVE_MS`. Silent archives are listed in `silent[]`, not errors.

View file

@ -0,0 +1,11 @@
# verae-archive-aggregator
**Job:** If `includeAttached`, fan out archive query and merge replies into the job JSON.
**Expects:** wait-path flag from middleware-http; replies on `verae.archive.reply.<correlationId>`.
**Sends:** `verae.archive.query` to all WORM nodes.
**Timeout:** missing archives omit slices; chain receipt still succeeds.
**Test:** `npm test` — one silent bloom miss + one hit; merge seal + metadata-attach.

View file

@ -0,0 +1,9 @@
# NATS — verae-archive-worm
| Direction | Address | From / to | Body |
|-----------|---------|-----------|------|
| IN | `verae.archive.put` | splitter | `{ sha256, tenantId, kind, record, traceId }` |
| IN | `verae.archive.query` | aggregator (broadcast) | `{ correlationId, sha256, tenantId, kinds[], traceId }` |
| OUT | `verae.archive.reply.<correlationId>` | aggregator | `{ archiveId, sha256, records[], traceId }` **only if bloom.mightHave(sha256)** |
Subscribe to query **without** a shared queue group so every archive sees every query.

View file

@ -0,0 +1,14 @@
# verae-archive-worm
**Job:** Append-only WORM store of metadata and files. Bloom filter: miss → stay silent on NATS.
**Expects:**
- `verae.archive.put` — append record, add sha256 to bloom
- `verae.archive.query` — `{ correlationId, sha256, tenantId, kinds[] }` (every node sees this; **not** a shared queue group)
**Sends:**
- `verae.archive.reply.<correlationId>` **only on bloom hit** — `{ archiveId, sha256, records[] }`
**Does not** write to the blockchain.
**Test:** `npm test` — miss is `null`; put then query returns records.

Some files were not shown because too many files have changed in this diff Show more