The Invariant
Every mutation is attributable and every artifact is verifiable without trusting the platform. Identity comes from authenticated sessions and manifest-declared roles; the audit chain is hash-linked per tenant; manifests, licenses, ingest batches and public verification payloads are Ed25519-signed — anyone holding the public key can check them.
The Contract
- RBAC engine —
rbac_engine.rolesandpermissionsin the manifest map roles → allowed triggers. Denial is fail-closed (403), enforced inside the action pipeline. - Audit chain — each audit row carries
prev_hash;GET /api/v1/audit/verify(edge) and…/tenant/audit/verify,…/admin/audit/verify(Control Plane) re-validate the chain. - Signing — production manifests and licenses are signed with
MANIFEST_PRIVATE_KEY/PLUGIN_PRIVATE_KEY(Ed25519). The edge verifies againstMANIFEST_PUBLIC_KEYS/PLUGIN_PUBLIC_KEYSbefore activation. HMAC fallback exists for development only —NODE_ENV=productionfails closed without Ed25519 keys. - Device identity — edge nodes sign ingest batches (
x-edge-signature) with the keypair issued at bootstrap claim.
The Flow
- An operator action hits the pipeline; RBAC checks the session roles against
rbac_engine.permissions. - On commit, the audit row is appended with the hash of the previous row — tampering any link invalidates the chain.
- The Control Plane publishes manifests after validating the signature; the edge verifies before swapping
is_active. - Sync batches arrive signed; the Control Plane re-verifies against the node’s registered pubkey and stores the batch as re-checkable evidence.
GET /api/v1/public/verify/event/:idlets a third party verify a committed event — no tenant credentials required.
Payload Example
# Verify the tenant audit chain end-to-end (Control Plane)
curl -s https://cp.axiom-trace.eu/api/v1/tenant/audit/verify \
-H "Authorization: Bearer $PORTAL_SESSION"
# → { "ok": true, "checked": 4811, "head": "9f2c…" }
# Public oracle — verify a single event's audit trail, no credentials
curl -s https://cp.axiom-trace.eu/api/v1/public/verify/event/$EVENT_ID
# → { "valid": true, "chain_depth": 12, … }
Known Failures
| Symptom | Cause |
|---|---|
403 on a legit operator |
Role not in permissions for that trigger — update the manifest, not the code |
| Manifest rejected at pull | Signature mismatch or non-monotonic version — re-sign with the current MANIFEST_PRIVATE_KEY |
verify reports a broken link |
Audit row deleted or rewritten — the chain is doing its job; investigate the gap |
| Edge refuses to start in prod | Ed25519 public keys missing — HMAC fallback is development-only |