Governance (CITADEL)
CITADEL is the cryptographic governance engine for the opensecstack ecosystem. Every privileged action across all SIN platforms passes through CITADEL's 5-gate MARSHAL decision engine before execution, and every decision is recorded in an append-only WORM audit chain with cryptographic integrity guarantees.
CITADEL runs on port 8099. Licence: AGPL-3.0.
What is CITADEL?
CITADEL provides the audit and authorisation layer that every other platform depends on. Its four active components are:
- MARSHAL — the 5-gate decision engine that evaluates every governance request (Kerkese)
- WORM chain — the append-only audit log with TripleHash integrity and Ed25519 chain anchors
- NDS — cryptographic separation-of-duties enforcement
- AUGUR — behavioural heuristics for pre-emptive anomaly detection
A fifth component, VIGIL (ecosystem health monitor, GREEN / AMBER / RED), is in design-stage for v2.0.
MARSHAL 5-gate engine
Every governance request — called a Kerkese — flows through five sequential gates. A gate failure stops evaluation immediately and returns the appropriate verdict.
Request → Gate 1 (AuthN) → Gate 2 (AuthZ) → Gate 3 (NDS) → Gate 4 (AUGUR) → Gate 5 (WORM)
↓
Always logged| Gate | Name | Responsibility |
|---|---|---|
| 1 | AuthN | Ed25519 signature verification — confirms the request came from a registered platform |
| 2 | AuthZ | RBAC permission check — confirms the actor holds the required role for the action |
| 3 | NDS | Separation of Duties — actor.user_id ≠ verifier.user_id, enforced cryptographically |
| 4 | AUGUR | Behavioural heuristics — flags off-hours actions, high-frequency submissions, and DATA_EXPORT without an associated incident |
| 5 | WORM | Unconditional append to the immutable audit chain with TripleHash integrity — every request is logged regardless of verdict |
WORM audit chain
The WORM (Write Once, Read Many) chain is an append-only PostgreSQL table with an immutability trigger that rejects any UPDATE or DELETEstatement. Every entry is cryptographically linked to the previous entry.
TripleHash computes a 128-byte composite digest for each entry using three independent algorithms simultaneously:
"cm"># Per-entry integrity triple_hash = SHA-256(payload) || SHA-512(payload) || BLAKE3(payload) "cm"># 128 bytes "cm"># Chain linkage chain_hash_n = SHA-256(chain_hash_{n-1} || payload_bytes) "cm"># Ed25519 chain anchors — written every 100 entries anchor = Ed25519_sign(master_key, chain_hash_at_entry_n)
All three hash algorithms must be broken simultaneously to forge an entry — an attacker cannot selectively modify only one hash component. The Ed25519 anchor every 100 entries binds the chain to the CITADEL signing key, enabling external notarisation.
After any disaster recovery — even from the coldest backup — the restored log can be cryptographically verified against the original chain anchors. Tampered recovery is detectable.
NDS — separation of duties
Gate 3 (NDS) enforces the separation-of-duties protocol. The constraint is actor.user_id ≠ verifier.user_id and the actor and verifier must belong to different role groups (group_sig_operator vs group_sig_verifier). This is enforced at the cryptographic protocol level, not by policy — a stolen operator credential cannot self-approve a privileged action because it cannot also control the verifier account.
A violation of this constraint causes an immediate HARD_STOPverdict and triggers an automatic P1 incident.
AUGUR behavioural heuristics
Gate 4 (AUGUR) applies pre-emptive behavioural analysis before any action reaches the WORM log. AUGUR reads from a read-only mirror database and does not affect MARSHAL gate decisions itself — it emits advisories (AUG-001 through AUG-009) that surface anomalies before they become violations.
Examples of patterns AUGUR flags:
- Actions submitted outside normal operating hours
- High-frequency submissions from a single actor within a short window
DATA_EXPORTaction requested without a linked open incident
Verdicts
MARSHAL returns one of three verdicts for every Kerkese evaluation:
| Verdict | Meaning |
|---|---|
EXECUTE | All gates passed — the action is authorised and has been WORM-logged |
REFUSE | A gate check failed (e.g. insufficient role, AUGUR advisory) — action is denied and logged |
HARD_STOP | A critical violation detected (SoD breach, spoofing, contradictory evidence) — action denied, P1 incident auto-created, chain anchored immediately |
HARD_STOP verdict is irreversible. It locks the action context and creates an immutable incident record in the WORM chain. Operators must resolve the incident through normal governance channels — there is no administrative override.Benchmarks
Measured on Go 1.24.4, Intel Core i7-7600U. All benchmarks use an in-memory mock store unless noted.
| Operation | Result | Notes |
|---|---|---|
| TripleHash (100-byte payload) | 1.52 µs | SHA-256 + SHA-512 + BLAKE3 in parallel |
| WORM chain step | 427 ns, 0 allocations | SHA-256 linkage only, no DB |
| WORM append (PostgreSQL 16, sync) | 4.22 ms | Includes immutability trigger and fsync |
| MARSHAL 5-gate evaluation | 7.55 µs | In-memory mock store |
| Chain verification (1,000 entries) | 10.19 ms | Full TripleHash recomputation |
API reference
CITADEL exposes a minimal HTTP API on port 8099.
| Method | Path | Description |
|---|---|---|
GET | /api/v1/health | Server and database health check |
POST | /api/v1/marshal/evaluate | Evaluate a Kerkese through the 5 MARSHAL gates |
POST | /api/v1/worm/emit | Append an event to the WORM chain directly |
GET | /api/v1/worm/verify | Verify chain integrity from genesis to current head |
For how platforms connect to CITADEL, see the CITADEL Integration guide. All connector requests to CITADEL must include an X-Citadel-Signature HMAC-SHA256 header computed over key_id + timestamp + body_hash. Requests outside the ±300-second timestamp window are rejected.