🚸 Warden

A policy decision point for LLM traffic: classify, decide, reserve budget, and record the decision in a tamper-evident hash chain.

Returns a decision only. The text is never stored — the ledger keeps the SHA-256 of the normalized text and nothing more.

Classification evidence

Detected spans, highlighted in place. A classification you cannot inspect is a classification you cannot challenge.

No decision yet.

decide response

You call the model. Warden does not relay anything.

Call commit once the real usage is known, or release if the call failed. A reservation that receives neither is released automatically after the TTL ( seconds). A commit that arrives after that sweep still records the real usage, with a warning — otherwise any caller slower than the TTL would never be charged at all.

Deciding the rules is a human responsibility. Always validate before saving. Validation warns about duplicate IDs, references to undefined destinations, and rules that can never fire.

For a review board: replay past traffic against a candidate policy and compute, for every row, how many of last month's calls it would have blocked. It touches neither the ledger nor the budget counters.

CSV columns: subject, text or summary, and optionally destination, purpose, tokens.

Breakdown

The ledger never stores your text. What remains is sha256(normalized text) and a hash chain that includes the previous record's hash:

hash = sha256("|".join(json.dumps(v) for v in
       [seq, timestamp, subject, level, destination, verdict, rule_id, content_hash, prev_hash]))

Verification runs in three layers: (1) the head traces back to GENESIS, (2) every record's hash and prev_hash reconcile, (3) with an externally retained anchor, the tip must equal it. Layer 3 is not optional in real use — layers 1 and 2 are computed from the file itself, so a forger who can rewrite the whole file can satisfy both.

Verification / import result

Verdict mix, spend, rule firings, dead rules and latency, in one place.

Summary

Verify the design guarantees right here, right now.

Plus a fail-open regression suite pinning every loophole found in review, and a brute-force check that the indexed rule evaluation agrees with a naive linear scan across randomized policies. The index is an optimization; it must never change a decision.

What Warden does not promise

Warden does not guarantee legal or regulatory compliance. All it can do is apply the rules you declared, consistently, and leave a record you can verify. Deciding what the rules ought to be is a human responsibility. The value of this tool lies in the consistency of its decisions and the verifiability of its records — nothing more.

The policy shipped here is an example. The destinations are fictional, the sensitive vocabulary is a starting list, and the budgets are placeholders. Replace all three before any real use.

This build versus the server build

 Browser build (this page)Server build (Gradio Space)
Classifier, rule engine, budget arithmeticIdenticalIdentical
Ledger hash chainIdentical — and byte-compatible: a ledger exported here verifies with the server build's standalone Python snippetIdentical
Where the ledger livesThis browser tab. Not shared, lost on reload unless exportedServer memory, shared by every caller, lost when the Space sleeps unless exported
Budget countersPer tab — they constrain nobody but youShared across callers within one Space process
HTTP APINonedecide, commit, ... via gradio_client and curl
Your textNever leaves this tab — there is no network request on the decision path, which the G1 self-test checksSent to the Space, classified there, never stored

The browser build is therefore an honest demonstration and a usable single-operator tool, but it is not a shared control point. Budget limits you cannot enforce on other callers are not budget limits. If you need the enforcement story, run the server build.

Fail-closed

When a decision fails, the answer is deny. Never fail-open. Every public function is wrapped so that no exception escapes; on failure the response is {"ok": false, "verdict": "deny", "error": {...}} and the reason is always stated in error. This covers classifier faults, malformed policy, budget subsystem errors and anything unforeseen. A hard budget overrun also degrades to deny.

Related repositories

Verifying a ledger without Warden

An exported ledger can be checked with nothing but the Python standard library. The full snippet is in the repositories above; the essential part is that each field is JSON-quoted before being joined, so a literal | inside a value cannot forge a different field split.

Service state


Apache-2.0. Warden is a decision point, not a relay.