Reference · BarzelVault · 2 September 2026
BarzelVault: what it decides, and how it tells you
Everything on this page is a property of the running server: the outcomes it can return, the inputs it scores, the sequences it watches for, and what lands in the audit chain. Read the docs home first for transport and connection.
Policy outcomes
Four outcomes, deterministic, and three of them are not “yes”
Given the same action, the same policy set and the same context, BarzelVault returns the same outcome every time. There is no model in the decision path. Handle all four — a client that only branches on success and failure will silently mishandle three of them.
| Outcome | Did the action happen? | What your client should do |
|---|---|---|
| allow | Yes, as requested | Proceed. The audit entry is already written. |
| deny | No | Stop. Do not retry identically — the decision is deterministic and the answer will not change. Surface the reason to the human. |
| dry-run | No — evaluated only | Nothing was executed downstream. Use it to test a policy change against real traffic shapes before you let the traffic through. |
| require approval | Not yet | Obtain the named approval, then call again. This is the outcome that pairs with an insufficient_scope challenge. Retrying it unchanged produces the same answer forever. |
Risk scoring
Seven inputs, and none of them is the prompt
Risk is computed from properties of the requested operation, not from how the request was phrased. That is what makes the score resistant to an injected instruction: rewording an action does not change its sensitivity, its value or where it sends data.
Trajectory detection: the sequence is the attack
Individually harmless calls become exfiltration when they arrive in order. BarzelVault scores sequences as well as calls, and two shapes are watched explicitly:
Tool families
Nine tools that are really nine families
Each of the nine tool names is a consolidated controller: one MCP tool that fronts many operations behind a single name. This is why the tool count is a floor on what the server does — and why tools/list plus each tool’s own schema tells you more than any count can. The full tool surface follows.
- authorize_actionAuthorize one exact action before execution and return the deterministic outcome; supports dry-run with zero side effects.
- execute_authorized_actionExecute exactly one previously authorized HTTPS action, consuming the grant atomically and never exposing the credential.
- manage_policiesAuthor, lint, shadow-test, version, activate and roll back deny-by-default policy as code.
- manage_approvalsRoute to a human, collect the verdict and record who decided, with separation of duties enforced.
- manage_credentialsStore, rotate, inspect and revoke execution credentials in a tenant-isolated vault; agents receive only opaque references.
- manage_limitsReserve per-principal velocity and spend budgets atomically, before a grant is issued.
- inspect_receiptsVerify signed grants and immutable action receipts, and prove the tenant hash chain is intact.
- get_firewall_statusReport enforcement mode, active policy hash, limits, pending approvals, live grants and isolated credentials.
- emergency_controlFail closed immediately, revoke a principal, grant or credential, and recover only under two-person control.
Tool surface
All 9 tool names, grouped by what they are for
Names are exact. Grouping is ours, to make the surface navigable. Several entries are consolidated controllers — one MCP tool that provides many operations behind a single name — so the tool count is a floor on what the server does, not a ceiling.
- authorize_action
- execute_authorized_action
- manage_policies
- manage_limits
- manage_approvals
- manage_credentials
- inspect_receipts
- get_firewall_status
- emergency_control
Worked example
A refund that gets held, and what your client does about it
Four calls: discover the policy set, request the action, read the outcome, verify the record. Tool names are exact. Argument names are illustrative — the authoritative schema for each tool is whatever tools/list returns on the server you are calling.
-
Call 01 See what you are being judged against
Zero arguments, so this one is safe to run first on any tenant. It tells you which policies exist before you trip one.
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "manage_policies", "arguments": {} } } -
Call 02 Request the action — do not execute it
The separation between authorize_action and execute_authorized_action is the whole design. Requesting gets you a decision; executing acts on one you already hold.
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "authorize_action", "arguments": { "action": "refund.issue", "amount": 4200, "currency": "USD", "destination": "customer_of_record", "record_count": 1 } } } -
Response Not an error. An outcome.
The call succeeded at the transport layer and returned require approval. Retrying it unchanged produces the same answer forever. The branch your client needs is “go get the approval”, not “back off and try again”.
outcome: require approval matched policy: refunds above 1,000 need a second pair of eyes action id: act_... ← carry this into the approval call audit: already written, before you read this
-
Call 03 & 04 Route to a human, then check the chain
A human resolves it through manage_approvals or manage_approvals — never the agent that requested it. Afterwards inspect_receipts confirms the record of all of it is intact, which is the call to run before an auditor asks rather than after.
tools/call manage_approvals { action_id, approver, note } tools/call execute_authorized_action { action_id } tools/call inspect_receipts { }
The shape generalises: discover, request, branch on the outcome, verify. Every governed Barzel server follows it, which is why a client written against one needs little work to speak to the next.
Audit integrity
Hash-chained events, signed receipts, tenant-scoped state
Audit events are append-only and hash-chained, so a removed or edited entry breaks the chain and is detectable rather than merely disallowed. Each decision can also be issued as a signed receipt you keep independently of us. State is held per tenant in tenant-scoped PostgreSQL — there is no shared table with a tenant column doing the work.
Note the limit honestly: hash chaining makes tampering detectable. It is not an external notary and we do not claim it is. Full posture on the security page.
Common questions
Questions developers ask first
What are the four policy outcomes in BarzelVault?
Allow, deny, dry-run and require approval. Each is deterministic: the same action, policy set and context produce the same outcome every time, because no model sits in the decision path. Only allow means the action ran as requested.
Should I retry a BarzelVault deny?
No. The decision is deterministic, so an identical retry produces an identical deny and a second audit event. Surface the reason to a human instead. This is the single most common client-side mistake — treating a governed refusal as a transient transport failure.
What does a dry-run outcome mean?
The action was evaluated against the real policy, approval, destination and limit path, and nothing was executed downstream. Read the returned decision: it tells you exactly what would have happened had you asked for real.
How many tools does BarzelVault expose?
9 tools, 12 static resources, 3 resource templates and 9 prompts as of 2 September 2026. Several are consolidated controllers — one tool name fronting many operations — so the count is a floor on what the server does. Call tools/list for the authoritative answer.
What inputs does BarzelVault use to score risk?
Seven: sensitivity, value, record count, destination, time, history and frequency. None of them is the prompt — risk is computed from properties of the requested operation, which is what makes the score resistant to an injected instruction. Rewording an action does not change its sensitivity or where it sends data.
Can BarzelVault audit logs be tampered with undetected?
Audit events are append-only and hash-chained, so an edited or removed entry breaks the chain and is detectable. That is a narrower claim than tamper-proof, and deliberately so: hash chaining is not an external notary and we do not present it as one. Chain verification is exposed through the inspect_receipts tool so you can check it yourself.