Vanzik Policy Configuration Reference
vanzik v2.0updated view on github
This document is the reference for the non-rule keys in a Vanzik policy YAML file — the proxy: and notifications: server-side tunables — with each key's default, validation rules, and runtime effect. Rule-level fields (scope, allow, deny, require_approval, pattern, paths, domain, action, conditions, rate_limit, limits, tool_scope_map) are covered in POLICY_REFERENCE.md and the examples under configs/.
Every key listed here is optional — each unset key falls back to a compile-time default, so a policy file needs none of them. version and name are still required: a file without them fails to load (policy missing required 'version' field). TUNING.md covers when to change these; this file covers what they do.
Quick reference#
version: "1"
name: my-policy
# Server-side tunables.
proxy:
session:
ttl: "1h" # duration; default 1h
request:
max_body_bytes: 1048576 # bytes; default 1048576 (1 MiB)
audit:
default_limit: 100 # rows returned when ?limit is omitted; default 100
max_limit: 1000 # hard ceiling on ?limit; default 1000
# Notification dispatcher tunables.
notifications:
dispatch_timeout: "10s" # default timeout for webhook/slack; default 10s
approval_required:
- type: webhook
url: "https://hooks.example/approval"
timeout: "5s" # optional per-target override
proxy#
Server-side tunables that apply to the HTTP surface itself — not to policy evaluation. All fields are optional.
proxy.session.ttl#
| Type | duration (Go time.ParseDuration) |
| Default | 1h |
| Affects | Dashboard session cookie lifetime |
| Validation | Must parse cleanly and be > 0. Invalid values fail at policy load. |
Controls how long an vanzik_session cookie stays valid after /auth/login succeeds. Shorter values force dashboard operators to re-authenticate more often; longer values reduce login friction but extend the window where a stolen laptop can act on approvals. The vanzik_csrf companion cookie is issued with the same expiry.
proxy.request.max_body_bytes#
| Type | integer (bytes) |
| Default | 1048576 (1 MiB) |
| Affects | POST /v1/check body acceptance |
| Validation | 0 (or unset) means the default; a negative value fails at policy load. |
Caps the size of /v1/check request bodies. Requests larger than this receive HTTP 413 Request Entity Too Large, a warning log line including the source, Content-Length, and the effective limit, and an increment on the Prometheus counter vanzik_request_rejected_total{reason="body_too_large"}. Tune down in hostile environments where a small request surface is part of the threat model; tune up only if a legitimate agent produces genuinely large meta payloads.
proxy.audit.default_limit#
| Type | integer (row count) |
| Default | 100 |
| Affects | GET /v1/audit when ?limit= is omitted |
| Validation | 0 (or unset) means the default; a negative value fails at policy load. Must be <= proxy.audit.max_limit. |
The row count returned by /v1/audit when the caller does not pass ?limit=. It only affects callers that omit ?limit=, such as a plain curl: the dashboard always sends limit=200, vanzik audit always sends its --limit (default 50), and the SDKs don't call /v1/audit.
proxy.audit.max_limit#
| Type | integer (row count) |
| Default | 1000 |
| Affects | GET /v1/audit ceiling on ?limit= |
| Validation | 0 (or unset) means the default; a negative value fails at policy load. Must be >= proxy.audit.default_limit. |
Hard ceiling on ?limit=. Clients requesting more than this receive this many rows (silently clamped, not rejected). The ceiling exists so a caller cannot pass ?limit=2147483647 and cause an unbounded scan of the audit file.
notifications#
Besides approval_required, on_deny and redaction (POLICY_REFERENCE § Notifications), the notifications section takes these timeouts.
notifications.dispatch_timeout#
| Type | duration |
| Default | 10s |
| Affects | http.Client.Timeout used by webhook and Slack notifiers |
| Validation | Must parse cleanly and be > 0. |
Default per-notification HTTP timeout for webhook and Slack targets. Console and log notifiers ignore it — they are synchronous and local. Lower it so a slow webhook can't hold dispatcher workers for the full 10s.
notifications.approval_required[].timeout, notifications.on_deny[].timeout#
| Type | duration |
| Default | inherits notifications.dispatch_timeout |
| Affects | That specific target's http.Client.Timeout |
| Validation | If present, must parse cleanly and be > 0. |
Per-target override. Use this when you run one webhook that is consistently slow but reliable and another that should fail fast.
Interaction with hot reload#
Policy hot reload (always on; --watch only adds a log line per reload) re-parses the file and swaps the policy.Engine's policy pointer. Runtime tunables resolved at startup do not change on reload — proxy.session.ttl and proxy.request.max_body_bytes are latched into the Server struct, and the notify dispatcher's per-notifier http.Client.Timeout is set when each client is constructed. Change these in the policy file and the new values apply on the next process restart.
Rule-level keys (allow/deny/require_approval, rate limits, cost limits) reload live.
Validation errors#
vanzik validate <policy.yaml> and vanzik server both run the same validators. A failure prints the offending YAML path:
INVALID: proxy.session.ttl: time: unknown unit "hr" in duration "1hr"
INVALID: proxy.audit.max_limit (50) must be >= proxy.audit.default_limit (200)
INVALID: notifications.dispatch_timeout: must be > 0, got "0s"
Operators can run vanzik validate in CI to reject bad configs before they reach a server.
Defaults, at a glance#
| Key | Default | Default is defined in |
|---|---|---|
proxy.session.ttl |
1h |
policy.DefaultSessionTTL |
proxy.request.max_body_bytes |
1048576 |
policy.DefaultMaxRequestBodyBytes |
proxy.audit.default_limit |
100 |
policy.DefaultAuditDefaultLimit |
proxy.audit.max_limit |
1000 |
policy.DefaultAuditMaxLimit |
notifications.dispatch_timeout |
10s |
policy.DefaultNotifyDispatchTimeout |
These constants live in pkg/policy/engine.go and are exported so tests and external callers can reference the same values without re-hardcoding them.