-
Notifications
You must be signed in to change notification settings - Fork 0
Urd Ledger
Urd is the system's memory of what was: every gate decision and every committed outcome is written here, once, in order. Named for Urðr, the Norn who keeps the past, the ledger is the audit record, the replay source, and the billing basis — the same three jobs, one log.
Urd is a centralized, append-only, tamper-evident ledger — a single authoritative, operator-run log. It is deliberately not distributed-consensus or on-chain: centralization buys low write latency and simple operations, and the integrity properties are supplied cryptographically rather than by a quorum.
Two kinds of record land here:
- Decision records — one per gate verdict (allow / deny / timeout), for every gate a request touches.
-
Outcome records — written at G4 commit; these carry
billable: trueand anchor per-outcome billing.
Every record is small, structured, and free of raw personal data in the chained portion. Anything human-readable that could contain PII (a denial reason, a payload) is stored by reference, not inline.
{
"id": "audit_7f3a2b",
"kind": "decision",
"gate": "policy",
"decision": "deny",
"reason_ref": "payload:9f2c",
"requestId": "req_abc123",
"trace": "9f3c2a",
"snapshot": { "policy": "pol_20260706_01", "state": "st_88f2", "config": "gatecfg_v14" },
"prev_hash": "sha256:6a1e",
"sig": "ed25519:3b9f",
"timestamp": "2026-07-06T10:32:00Z"
}
The snapshot IDs are what make a record replayable — load the same pinned inputs, re-run the gate, get the same verdict (Deterministic Execution). The reason_ref points into the erasable payload store (see GDPR).
Two mechanisms make the log tamper-evident:
-
Hash chain — each record carries
prev_hash = sha256(previous_record). Any insert, delete, or edit breaks the chain from that point forward. - Ed25519 signatures — each record (and each checkpoint) is signed. The signing key lives in an HSM in Asgard, in a trust domain distinct from workers, so a compromised Midgard or Jotunheim node can produce records but cannot sign them.
Tamper-evident is not tamper-proof. A centralized ledger is only as trustworthy as its signing key — that is exactly why the key is off the worker path and in hardware. If you later need non-repudiation against NornGate-the-operator, publishing the signed chain-head to an external anchor is an additive step, not a redesign.
Verification walks the chain from a signed checkpoint, not from genesis:
verify(record R, pubkey K, checkpoint C):
assert ed25519_verify(K, R.sig, canonical(R without sig))
assert R.prev_hash == sha256(canonical(R.previous))
... walk back to C ...
assert ed25519_verify(K, C.sig, canonical(C)) # trusted chain-head
Periodic signed checkpoints (the current chain-head hash) double as the recovery seed for the Ragnarök drill — recovery restores to a checkpoint and validates the chain forward before resuming.
Each G4-verified outcome emits a signed receipt the tenant can verify independently against Urd's public key — without trusting NornGate's word, and without NornGate trusting theirs.
{
"id": "audit_9a2f",
"kind": "outcome",
"gate": "arbitration",
"decision": "commit",
"requestId": "req_abc123",
"resource": "user-record:4471",
"idempotencyKey": "idem_abc123",
"billable": true,
"prev_hash": "sha256:7c4d",
"sig": "ed25519:a12e",
"timestamp": "2026-07-06T10:32:02Z"
}
Why it matters: the invoice basis is the set of billable outcome records for a tenant over a period. Because each is signed and chained, the customer can reconcile the bill against receipts they verified themselves — per-outcome billing becomes auditable by both sides, which is the point of charging per verified outcome rather than per token. Integrity bar: Kaman's signed, hash-chained action records.
- Hot — an append-only Kafka log, partitioned per realm, for recent records.
- Cold — durable backup in S3 / Niflheim, long retention, immutable after write.
- Tiered — records age from hot to cold; checkpoints bridge the two.
Write access is Asgard-only; the signing HSM is the sole issuer of valid signatures. This is one authoritative ledger, not a replicated quorum — the trust model is cryptographic, and the storage is ordinary durable infrastructure.
Urd is queryable over GET /v1/audit, filtered by gate, decision, request, tenant, and time window.
GET /v1/audit?gate=policy&decision=deny&from=2026-07-06T00:00:00Z&to=2026-07-06T23:59:59Z
The response is an array of records (payloads returned by reference, resolved through the payload store only for authorized readers). Reading the audit log is itself an audited action — there is no unobserved read of the record of record.
An append-only ledger and the right to erasure (GDPR Art. 17) only conflict if the same store holds both proof and personal data. Urd splits them:
- Chain store — hashes, gate, decision, timestamps, snapshot IDs. No personal data. Immutable.
-
Payload store — PII-bearing fields (the
reason, request bodies), encrypted per data-subject with a data-encryption key (DEK) wrapped by a KMS key.
The chain commits to the ciphertext (its hash), never the plaintext — so erasing the plaintext does not break verification, and the hash is not a plaintext oracle.
erase(subject S):
delete DEK(S) in KMS # crypto-shred: S's payloads are now unrecoverable
# chain untouched: it commits to ciphertext, not plaintext
# records still verify; reason_ref resolves to a tombstone
So Urd is immutable as a proof structure and erasable as a data store — the two claims describe different layers, not a contradiction. See Security & Fail-closed.
- Gates & Attributes — what each decision record captures.
- Deterministic Execution — replay from recorded snapshots.
- Security & Fail-closed — key custody and the threat model.
- The Five Gates — where records are produced.
Section glyphs are Elder Futhark runes (Unicode Runic block, U+16A0–U+16FF) — semantic, not emoji. Full set on Home:
| Rune | Name | Gloss | Marks |
|---|---|---|---|
| ᚾ | Nauðiz | need, constraint | the platform mark |
| ᛈ | Perthro | the well of Urd, the record of fate | overview |
| ᚨ | Ansuz | the word, the written record | the record |
| ᛉ | Algiz | protection, warding | integrity |
| ᚷ | Gebo | the proof of exchange | verifiable receipts |
| ᛚ | Laguz | water, the deep, cold storage | storage & retention |
| ᚲ | Kenaz | the torch, looking into the record | query |
| ᚺ | Hagalaz | hail, controlled destruction | GDPR erasure |
| ᚱ | Raidō | the ride, the road | next steps |
References. Ed25519 / RFC 8032 (signatures); Certificate Transparency / RFC 6962 (signed append-only log with Merkle checkpoints — the design lineage); GDPR Art. 17 (right to erasure) via crypto-shredding; Kafka (append log); KMS envelope encryption. Signed, hash-chained records — Kaman. Naming doctrine: Prose Edda / Poetic Edda, per Norse Cosmology & Platform Design.
Urd is the system's memory of what was: every gate decision and every committed outcome is written here, once, in order. Named for Urðr, the Norn who keeps the past, the ledger is the audit record, the replay source, and the billing basis — the same three jobs, one log.
Urd is a centralized, append-only, tamper-evident ledger — a single authoritative, operator-run log. It is deliberately not distributed-consensus or on-chain: centralization buys low write latency and simple operations, and the integrity properties are supplied cryptographically rather than by a quorum.
Two kinds of record land here:
- Decision records — one per gate verdict (allow / deny / timeout), for every gate a request touches.
-
Outcome records — written at G4 commit; these carry
billable: trueand anchor per-outcome billing.
Every record is small, structured, and free of raw personal data in the chained portion. Anything human-readable that could contain PII (a denial reason, a payload) is stored by reference, not inline.
{
"id": "audit_7f3a2b",
"kind": "decision",
"gate": "policy",
"decision": "deny",
"reason_ref": "payload:9f2c",
"requestId": "req_abc123",
"trace": "9f3c2a",
"snapshot": { "policy": "pol_20260706_01", "state": "st_88f2", "config": "gatecfg_v14" },
"prev_hash": "sha256:6a1e",
"sig": "ed25519:3b9f",
"timestamp": "2026-07-06T10:32:00Z"
}The snapshot IDs are what make a record replayable — load the same pinned inputs, re-run the gate, get the same verdict ([Deterministic Execution](Deterministic-Execution)). The reason_ref points into the erasable payload store (see GDPR).
Two mechanisms make the log tamper-evident:
-
Hash chain — each record carries
prev_hash = sha256(previous_record). Any insert, delete, or edit breaks the chain from that point forward. - Ed25519 signatures — each record (and each checkpoint) is signed. The signing key lives in an HSM in Asgard, in a trust domain distinct from workers, so a compromised Midgard or Jotunheim node can produce records but cannot sign them.
Tamper-evident is not tamper-proof. A centralized ledger is only as trustworthy as its signing key — that is exactly why the key is off the worker path and in hardware. If you later need non-repudiation against NornGate-the-operator, publishing the signed chain-head to an external anchor is an additive step, not a redesign.
Verification walks the chain from a signed checkpoint, not from genesis:
verify(record R, pubkey K, checkpoint C):
assert ed25519_verify(K, R.sig, canonical(R without sig))
assert R.prev_hash == sha256(canonical(R.previous))
... walk back to C ...
assert ed25519_verify(K, C.sig, canonical(C)) # trusted chain-head
Periodic signed checkpoints (the current chain-head hash) double as the recovery seed for the Ragnarök drill — recovery restores to a checkpoint and validates the chain forward before resuming.
Each G4-verified outcome emits a signed receipt the tenant can verify independently against Urd's public key — without trusting NornGate's word, and without NornGate trusting theirs.
{
"id": "audit_9a2f",
"kind": "outcome",
"gate": "arbitration",
"decision": "commit",
"requestId": "req_abc123",
"resource": "user-record:4471",
"idempotencyKey": "idem_abc123",
"billable": true,
"prev_hash": "sha256:7c4d",
"sig": "ed25519:a12e",
"timestamp": "2026-07-06T10:32:02Z"
}Why it matters: the invoice basis is the set of billable outcome records for a tenant over a period. Because each is signed and chained, the customer can reconcile the bill against receipts they verified themselves — per-outcome billing becomes auditable by both sides, which is the point of charging per verified outcome rather than per token. Integrity bar: Kaman's signed, hash-chained action records.
- Hot — an append-only Kafka log, partitioned per realm, for recent records.
- Cold — durable backup in S3 / Niflheim, long retention, immutable after write.
- Tiered — records age from hot to cold; checkpoints bridge the two.
Write access is Asgard-only; the signing HSM is the sole issuer of valid signatures. This is one authoritative ledger, not a replicated quorum — the trust model is cryptographic, and the storage is ordinary durable infrastructure.
Urd is queryable over GET /v1/audit, filtered by gate, decision, request, tenant, and time window.
GET /v1/audit?gate=policy&decision=deny&from=2026-07-06T00:00:00Z&to=2026-07-06T23:59:59ZThe response is an array of records (payloads returned by reference, resolved through the payload store only for authorized readers). Reading the audit log is itself an audited action — there is no unobserved read of the record of record.
An append-only ledger and the right to erasure (GDPR Art. 17) only conflict if the same store holds both proof and personal data. Urd splits them:
- Chain store — hashes, gate, decision, timestamps, snapshot IDs. No personal data. Immutable.
-
Payload store — PII-bearing fields (the
reason, request bodies), encrypted per data-subject with a data-encryption key (DEK) wrapped by a KMS key.
The chain commits to the ciphertext (its hash), never the plaintext — so erasing the plaintext does not break verification, and the hash is not a plaintext oracle.
erase(subject S):
delete DEK(S) in KMS # crypto-shred: S's payloads are now unrecoverable
# chain untouched: it commits to ciphertext, not plaintext
# records still verify; reason_ref resolves to a tombstone
So Urd is immutable as a proof structure and erasable as a data store — the two claims describe different layers, not a contradiction. See [Security & Fail-closed](Security-and-Fail-Closed).
- [Gates & Attributes](Gates-and-Attributes) — what each decision record captures.
- [Deterministic Execution](Deterministic-Execution) — replay from recorded snapshots.
- [Security & Fail-closed](Security-and-Fail-Closed) — key custody and the threat model.
- [The Five Gates](The-Five-Gates) — where records are produced.
Section glyphs are Elder Futhark runes (Unicode Runic block, U+16A0–U+16FF) — semantic, not emoji. Full set on [Home](Home#iconography):
| Rune | Name | Gloss | Marks |
|---|---|---|---|
| ᚾ | Nauðiz | need, constraint | the platform mark |
| ᛈ | Perthro | the well of Urd, the record of fate | overview |
| ᚨ | Ansuz | the word, the written record | the record |
| ᛉ | Algiz | protection, warding | integrity |
| ᚷ | Gebo | the proof of exchange | verifiable receipts |
| ᛚ | Laguz | water, the deep, cold storage | storage & retention |
| ᚲ | Kenaz | the torch, looking into the record | query |
| ᚺ | Hagalaz | hail, controlled destruction | GDPR erasure |
| ᚱ | Raidō | the ride, the road | next steps |
References. [Ed25519 / RFC 8032](https://www.rfc-editor.org/rfc/rfc8032) (signatures); [Certificate Transparency / RFC 6962](https://www.rfc-editor.org/rfc/rfc6962) (signed append-only log with Merkle checkpoints — the design lineage); [GDPR Art. 17](https://gdpr-info.eu/art-17-gdpr/) (right to erasure) via crypto-shredding; Kafka (append log); KMS envelope encryption. Signed, hash-chained records — Kaman. Naming doctrine: Prose Edda / Poetic Edda, per [Norse Cosmology & Platform Design](Norse-Cosmology-and-Platform-Design).
Welcome
Getting Started
Core Concepts
Guides
- Guides
- Configuring Gates
- Setting Up Subdomains (Realms)
- Integrating AI Agents
- Monitoring & Observability
- Disaster Recovery (Ragnarök Drill)
- Custom Domains & TLS
Reference
Silence means no.