Skip to content

Configuring Gates

Frank Yglesias Bertheau edited this page Jul 7, 2026 · 1 revision
<h1>ᚾ&nbsp;NornGate — Configuring Gates</h1>

Tune the five gates for a realm: timeouts, ingress limits, the approval budget, sandbox limits, and arbitration. You tune gates — you do not reorder or disable them. This guide extends the GateConfig schema into concrete tasks; field names are the derived config model — reconcile against your build's schema.


ᚨ Before you start

Four rules hold throughout:

  • Order is fixed. G0 → G4 always run in order; config changes their behavior, never their sequence or presence.
  • Changes are versioned. You bump a version (gatecfg_v14v15); the old one stays resolvable so historical decisions still replay.
  • Fail-closed extends to config. An invalid gate config is rejected at admission — it does not run. Always config validate before apply.
  • Every change is provable. The version in force is pinned to each decision, so after any change you confirm it in Urd, not by hope.

ᛁ Set timeouts

Timeouts are deny ceilings, not latency targets — a gate that exceeds its budget denies.

timeouts: { ingress: 5s, policy: 10s, approval: 30s, sandbox: 60s, arbitration: 10s }

Why it is safe to raise sandbox: a longer sandbox timeout does not slow a healthy allow — it only delays the deny for a genuinely stuck sandbox. You are moving the fail-closed ceiling, not adding latency to the happy path.

Verify: after apply, a fresh decision's record carries the new config snapshot ID.


ᚦ Configure each gate

G0 — Ingress

ingress:
  rateLimit: { unit: tenant, tokens: 1000, refillPerSecond: 100 }
  allowlist: ["10.0.0.0/8"]
  maxBodyBytes: 1048576

Why: G0 denials are the cheapest in the pipeline — every request stopped here is one the expensive gates (G2, G3) never pay for. Rate-limit and shape aggressively.

Verify: exceed the limit and confirm 429 records appear:

norngate-cli audit query --gate ingress --decision deny --from now-5m

G1 — Policy

The rules themselves live in a Policy resource (default-deny, deny-overrides). The gate-side lever here is the deliberation budget:

# BudgetConfig
deliberation: { perAgentPerRequest: 50000, unit: tokens }

Why: G1 is deterministic and has no LLM in the decision — so a "policy denial" is always reproducible. The deliberation budget caps how much context an agent may pull before the decision, bounding cost per request. Author rules per Gates & Attributes.

Verify: dry-run before shipping —

norngate-cli policy test --subject retrieval-agent --resource pii:user-record --action write

G2 — Approval

approval:
  riskThreshold: high              # actions at or above this risk require G2
  budget: { perTenantPerDay: 500 }
  autoConsent:
    - match: { action: read, resource.sensitivity: low }

Why: the approval budget is the lever that keeps human transits under ~5% of traffic. Raise riskThreshold and add autoConsent rules to route more low-risk actions through rule-based consent instead of a human — G2 stays reserved for what genuinely needs a person.

Verify: confirm the budget debits are landing:

norngate-cli audit query --gate approval --from now-1h

G3 — Sandbox

sandbox:
  runtime: firecracker
  limits: { cpu: "2", memory: 2Gi }
  egress: brokered-only
  warmPool: 16

Why egress: brokered-only: a sandbox that can open arbitrary outbound connections is an exfiltration channel. Brokering egress closes it. Why warmPool: G3 dominates end-to-end latency (~120ms warm); a warm pool avoids cold-start VM allocation on the hot path. Remember G3's fidelity limit — irreversible actions are prepared here and committed once at G4 (The Five Gates).

Verify: sandbox failures surface as 500:

norngate-cli audit query --gate sandbox --decision error --from now-15m

G4 — Arbitration

arbitration:
  shardBy: resourceKey
  lease: { ttl: 30s }
  fairness: aging

Why fairness: aging: a purely deterministic winner would let a hot resource starve the writers that keep losing. Aging keeps the choice deterministic and starvation-free — deterministic is not the same as fair, and G4 owes you both.

Verify: contention shows up as 409, and commits as outcome records:

norngate-cli audit query --gate arbitration --from now-15m

ᛟ Per-realm gates

Different realms want different gates. Target a realm with spec.realm and give each the budget its trust posture implies — a public Midgard gate rate-limits hard and sets a high approval threshold; an untrusted Jotunheim gate runs a longer sandbox and strict egress.

apiVersion: norngate.io/v1
kind: GateConfig
metadata: { name: midgard, version: gatecfg_v15 }
spec:
  realm: midgard
  timeouts: { ingress: 5s, policy: 10s, approval: 30s, sandbox: 60s, arbitration: 10s }
  ingress: { rateLimit: { unit: tenant, tokens: 1000, refillPerSecond: 100 } }
  approval: { riskThreshold: high, budget: { perTenantPerDay: 500 } }
  sandbox: { runtime: firecracker, limits: { cpu: "2", memory: 2Gi }, egress: brokered-only }
  arbitration: { shardBy: resourceKey, lease: { ttl: 30s }, fairness: aging }

ᛒ Apply, verify, roll back

The workflow is the same for any gate change:

# 1. validate (admission dry-run — fail-closed)
norngate-cli config validate midgard-gates.yaml

2. apply (new version)

norngate-cli config apply midgard-gates.yaml

3. verify — watch the decision shift, confirm the new version is pinned

norngate-cli audit query --realm midgard --from now-15m

4. roll back if wrong — re-pin the previous version

norngate-cli config apply --pin gatecfg_v14

Why this always works: if a change misbehaves, norngate-cli config diff gatecfg_v14 gatecfg_v15 shows exactly what moved, and the previous version is still resolvable — rollback is re-pinning, not reconstruction.


ᚱ Next steps


Iconography

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
Ansuz the word, instruction before you start
Isa ice, fixed ceilings timeouts
Thurisaz thorn, gateway configuring each gate
Othala enclosed estate, boundary per-realm gates
Berkanan growth, the change made apply / verify / roll back
Raidō the ride, the road next steps

References. Token-bucket rate limiting; NIST SP 800-162 + OASIS XACML (policy, per Gates & Attributes); Firecracker (G3 sandbox). Config model and CLI: Configuration, CLI Tools. Naming doctrine: Prose Edda / Poetic Edda, per Norse Cosmology & Platform Design.

ᚾ NornGate — Configuring Gates

Tune the five gates for a realm: timeouts, ingress limits, the approval budget, sandbox limits, and arbitration. You tune gates — you do not reorder or disable them. This guide extends the [GateConfig](https://claude.ai/chat/Configuration) schema into concrete tasks; field names are the derived config model — reconcile against your build's schema.


ᚨ Before you start

Four rules hold throughout:

  • Order is fixed. G0 → G4 always run in order; config changes their behavior, never their sequence or presence.
  • Changes are versioned. You bump a version (gatecfg_v14v15); the old one stays resolvable so historical decisions still replay.
  • Fail-closed extends to config. An invalid gate config is rejected at admission — it does not run. Always config validate before apply.
  • Every change is provable. The version in force is pinned to each decision, so after any change you confirm it in [Urd](Urd-Ledger), not by hope.

ᛁ Set timeouts

Timeouts are deny ceilings, not latency targets — a gate that exceeds its budget denies.

timeouts: { ingress: 5s, policy: 10s, approval: 30s, sandbox: 60s, arbitration: 10s }

Why it is safe to raise sandbox: a longer sandbox timeout does not slow a healthy allow — it only delays the deny for a genuinely stuck sandbox. You are moving the fail-closed ceiling, not adding latency to the happy path.

Verify: after apply, a fresh decision's record carries the new config snapshot ID.


ᚦ Configure each gate

G0 — Ingress

ingress:
  rateLimit: { unit: tenant, tokens: 1000, refillPerSecond: 100 }
  allowlist: ["10.0.0.0/8"]
  maxBodyBytes: 1048576

Why: G0 denials are the cheapest in the pipeline — every request stopped here is one the expensive gates (G2, G3) never pay for. Rate-limit and shape aggressively.

Verify: exceed the limit and confirm 429 records appear:

norngate-cli audit query --gate ingress --decision deny --from now-5m

G1 — Policy

The rules themselves live in a Policy resource (default-deny, deny-overrides). The gate-side lever here is the deliberation budget:

# BudgetConfig
deliberation: { perAgentPerRequest: 50000, unit: tokens }

Why: G1 is deterministic and has no LLM in the decision — so a "policy denial" is always reproducible. The deliberation budget caps how much context an agent may pull before the decision, bounding cost per request. Author rules per [Gates & Attributes](Gates-and-Attributes).

Verify: dry-run before shipping —

norngate-cli policy test --subject retrieval-agent --resource pii:user-record --action write

G2 — Approval

approval:
  riskThreshold: high              # actions at or above this risk require G2
  budget: { perTenantPerDay: 500 }
  autoConsent:
    - match: { action: read, resource.sensitivity: low }

Why: the approval budget is the lever that keeps human transits under ~5% of traffic. Raise riskThreshold and add autoConsent rules to route more low-risk actions through rule-based consent instead of a human — G2 stays reserved for what genuinely needs a person.

Verify: confirm the budget debits are landing:

norngate-cli audit query --gate approval --from now-1h

G3 — Sandbox

sandbox:
  runtime: firecracker
  limits: { cpu: "2", memory: 2Gi }
  egress: brokered-only
  warmPool: 16

Why egress: brokered-only: a sandbox that can open arbitrary outbound connections is an exfiltration channel. Brokering egress closes it. Why warmPool: G3 dominates end-to-end latency (~120ms warm); a warm pool avoids cold-start VM allocation on the hot path. Remember G3's fidelity limit — irreversible actions are prepared here and committed once at G4 ([The Five Gates](The-Five-Gates)).

Verify: sandbox failures surface as 500:

norngate-cli audit query --gate sandbox --decision error --from now-15m

G4 — Arbitration

arbitration:
  shardBy: resourceKey
  lease: { ttl: 30s }
  fairness: aging

Why fairness: aging: a purely deterministic winner would let a hot resource starve the writers that keep losing. Aging keeps the choice deterministic and starvation-free — deterministic is not the same as fair, and G4 owes you both.

Verify: contention shows up as 409, and commits as outcome records:

norngate-cli audit query --gate arbitration --from now-15m

ᛟ Per-realm gates

Different realms want different gates. Target a realm with spec.realm and give each the budget its trust posture implies — a public Midgard gate rate-limits hard and sets a high approval threshold; an untrusted Jotunheim gate runs a longer sandbox and strict egress.

apiVersion: norngate.io/v1
kind: GateConfig
metadata: { name: midgard, version: gatecfg_v15 }
spec:
  realm: midgard
  timeouts: { ingress: 5s, policy: 10s, approval: 30s, sandbox: 60s, arbitration: 10s }
  ingress: { rateLimit: { unit: tenant, tokens: 1000, refillPerSecond: 100 } }
  approval: { riskThreshold: high, budget: { perTenantPerDay: 500 } }
  sandbox: { runtime: firecracker, limits: { cpu: "2", memory: 2Gi }, egress: brokered-only }
  arbitration: { shardBy: resourceKey, lease: { ttl: 30s }, fairness: aging }

ᛒ Apply, verify, roll back

The workflow is the same for any gate change:

# 1. validate (admission dry-run — fail-closed)
norngate-cli config validate midgard-gates.yaml

# 2. apply (new version)
norngate-cli config apply midgard-gates.yaml

# 3. verify — watch the decision shift, confirm the new version is pinned
norngate-cli audit query --realm midgard --from now-15m

# 4. roll back if wrong — re-pin the previous version
norngate-cli config apply --pin gatecfg_v14

Why this always works: if a change misbehaves, norngate-cli config diff gatecfg_v14 gatecfg_v15 shows exactly what moved, and the previous version is still resolvable — rollback is re-pinning, not reconstruction.


ᚱ Next steps


Iconography

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
Ansuz the word, instruction before you start
Isa ice, fixed ceilings timeouts
Thurisaz thorn, gateway configuring each gate
Othala enclosed estate, boundary per-realm gates
Berkanan growth, the change made apply / verify / roll back
Raidō the ride, the road next steps

References. Token-bucket rate limiting; [NIST SP 800-162](https://csrc.nist.gov/pubs/sp/800/162/final) + OASIS XACML (policy, per [Gates & Attributes](Gates-and-Attributes)); Firecracker (G3 sandbox). Config model and CLI: [Configuration](Configuration), [CLI Tools](CLI-Tools). Naming doctrine: Prose Edda / Poetic Edda, per [Norse Cosmology & Platform Design](Norse-Cosmology-and-Platform-Design).

Clone this wiki locally