Skip to main content

Policy & approvals

ZenVault runs a policy engine as the authorization boundary on every money-movement. It is evaluated before anything is signed or settled and resolves to one of:

  • allow — proceed as normal.
  • hold — park the transfer in state held for human approval; it is not signed (and reserves no nonce) until released.
  • reject — block it with 403 and a ZenVault-owned message.

Evaluation runs after screening, so screening signals feed the decision.

Rules

Rules are ordered (your workspace rules before ZenVault global defaults); the first match wins, and no match means allow. A rule matches on any combination of:

  • kindexternal, internal, contract_call, approve, eth_sign_transaction
  • asset / chain / destination type — allowlisted vs one-time vs contract
  • amount bounds — in asset units or USD
  • risk — KYT wallet risk score ≥ N, or sanctions hit
  • velocity — cumulative amount over a rolling window per asset

…and produces an action (allow / hold / reject).

Modes: shadow vs enforce

Each workspace has an enforcement mode:

  • shadow (default) — rules are evaluated and logged, but never block a transfer. Use it to validate rules safely against real traffic.
  • enforce — decisions take effect: holds park transfers, rejects block.

What integrators see

Policy is managed by admins in the console (rules + mode + the approvals queue). Through the API you only need to handle two effects:

EffectHow it appears
HeldA transfer create returns state held. It stays there until an approver releases it; watch transfer.* webhooks for the transition.
RejectedThe create call fails with 403 and "Transfer blocked by policy: <reason>". It is not retried automatically.

The policy decision is also recorded on the transfer's metadata.policy (action, rule name, reason) for auditability.

Approvals

Held transfers land in the console Approvals queue, where an approver-role user:

  • Releases — the transfer is submitted for signing (a fresh nonce and current fees are applied at release), moving it into the normal lifecycle.
  • Rejects — the transfer is cancelled (terminal) with a recorded reason.

Every decision is written to an audit trail.