Every artifact — manifest, migrations, plugin licenses, tenant contract — follows the same three-phase lifecycle. No node is ever updated by pushing code: artifacts flow through a signed, verifiable channel and activate hot.
1 · Publish (Control Plane)
An admin (console or API client) publishes a new manifest version:
POST /api/v1/admin/tenants/:id/manifests
Authorization: Bearer <admin-session>
{ "manifest": { ... }, "migrations": [ { "name": "001_init.sql", "sql": "..." } ] }
What the Control Plane does, in one transaction:
- Validation — JSON Schema +
meta.versionstrictly greater than the currently active version (monotonic, no rollbacks by publish). - Packaging — manifest and SQL migrations are bundled; the package is the unit of distribution.
- Signature — the package is signed Ed25519 with the Control Plane’s private key. The private key never leaves the cloud; edges only know the public key.
- Activation —
is_activeswaps atomically to the new version; previous versions stay stored for audit.
A subscription in canceled state cannot publish: ingest and sync keep working, manifest pull returns the last valid state. The contract state is itself distributed as a signed tenant license.
2 · Pull (Edge node)
Every edge runs a periodic sync cycle — every 30 seconds:
GET /api/v1/sync/manifest → latest active manifest + signature
GET /api/v1/sync/licenses → plugin licenses + tenant contract license
Authorization: Bearer <edge api_key> (+ tenant_id)
The same cycle drains the CDC outbox (POST /api/v1/sync/ingest) and doubles as the fleet heartbeat: the Control Plane records last_poll_at on each authenticated call. An edge that goes quiet is visible in the fleet console within a minute.
Offline by design: if the Control Plane is unreachable, the circuit breaker opens, events stay in the local outbox, and the edge keeps running the last verified manifest. Nothing is dropped — sync resumes on its own.
3 · Verify & activate (Edge node)
Before anything executes, the edge verifies:
- Signature — Ed25519 check against the pinned public key. Invalid signature → package rejected, fail-closed, current manifest keeps running.
- Version — must be greater than the installed one.
- Snapshot — an automatic pre-migration snapshot of the affected tables is taken (
snap_*schemas), so a bad migration is reversible. - Migrations — applied in a transaction; any error rolls everything back.
- Hot swap —
kernel.setManifestreplaces the live manifest on the same process. No restart, no downtime, no lost session.
The tenant contract license is persisted locally (sys_tenant_license) so the edge enforces the right behavior — including the offline grace period — even while disconnected.
The full picture
Dev/admin ──publish──▶ Control Plane ──sign──▶ signed package
│
edge ◀──pull every 30s── TLS channel ◀───────────────┘
│
├─ verify signature (Ed25519) ──fail──▶ reject, keep running
├─ snapshot → migrations (tx) ──fail──▶ rollback
└─ hot swap manifest ──▶ new version live, zero downtime
Two reference verticals — a retail POS and a field-service work-order app — run today on the same engine through exactly this cycle.