Guardrail Rules
Rules you configure per app, evaluated against every request, response and tool call.
Rule Types
| Type | Description | Plans |
|---|---|---|
| contains_pii | Personal data: email addresses, phone numbers, US social security numbers, payment card numbers, bank account numbers (IBAN), IP addresses, dates of birth, Nordic personal identity numbers, EU national identity and tax numbers, EU VAT numbers, Swiss social security numbers (AHV), UK National Insurance numbers, and UK NHS numbers. See PII detection for each identifier and how a match is confirmed. | All |
| contains_secret | Provider keys (OpenAI, Anthropic), GitHub and Slack tokens, AWS and GCP keys, Stripe keys, JWTs, database URLs, Azure connection strings, and high-entropy strings. No configuration. | All |
| token_limit_exceeded | Caps estimated prompt tokens per request | All |
| model_allowlist | Restricts which models may be used | Growth |
| keyword_blocklist | Matches whole words from a list you supply, case-insensitively | Growth |
| regex_match | Your own regular expression, with a label for the dashboard | Growth |
| prompt_injection | Pattern matching for instruction overrides, role switching and system-prompt extraction; strict sensitivity adds encoding tricks and delimiter injection. Like any pattern-based injection detector this is a heuristic — expect misses and false positives, and treat it as defence in depth rather than a boundary. | Growth |
Actions
| Action | Behavior |
|---|---|
| allow | Log the violation but allow the request |
| warn | Log a warning and allow the request |
| block | Block the request entirely |
| redact | Replace matched spans before storage: [REDACTED:pii] for contains_pii, [REDACTED:secret] for contains_secret, and [REDACTED] for keyword_blocklist and regex_match. The other three types report no match positions, so redact on them drops the stored prompt without masking anything — the dashboard does not offer it for them. The original text is never persisted. Via the SDK, redaction applies to what SignalVault stores: the request proceeds as your application sent it and you receive the decision. Via the proxy, the request is forwarded to your provider with the matched values masked, and is refused when it cannot be masked cleanly. |
How Redaction Works
Redaction happens inside the ingest layer, before encryption — raw text never reaches the database.
- The
redactionsarray in the API response lists the rule types that redacted content and how many matches each removed, for example[{"type": "contains_pii", "count": 2}]. It does not report locations — SignalVault redacts what it stores, so there is nothing for your application to apply. - The dashboard prompt/response viewer shows the redacted version because the encrypted field stores the already-redacted text.
- Redaction applies to both
ai.requestprompts andai.responseoutputs. - When redaction fires, the raw
messages/outputkeys are also removed from the stored JSONB payload. - The placeholder names the rule that matched:
[REDACTED:pii],[REDACTED:secret], or plain[REDACTED]forkeyword_blocklistandregex_match. token_limit_exceeded,model_allowlistandprompt_injectionmatch a whole request rather than a span of text, so there is nothing for them to mask. The dashboard does not offerredactfor them.- Through an SDK a redacted request reaches your provider as your application sent it. Through the
proxy a
redactmatch is forwarded with the matched values masked, in message text, the Anthropicsystemfield, tool inputs and results, and tool-call arguments. Tool inputs and tool-call arguments are read by string value for both OpenAI and Anthropic; keys and numbers inside tool inputs and tool-call arguments are not evaluated. See the proxy page for the cases where the request is refused instead.
Decision Hierarchy
When multiple rules fire, the strictest action wins: block > redact > warn > allow.
What a new app starts with
Every new app is created with a set of default rules already enabled, scoped to all environments.
Most of them warn rather than block, so your first requests are
logged and flagged without being rejected. If you are evaluating SignalVault and expect a request to be
blocked, check this table first — a warn
decision means the guardrail fired and allowed the request through, which is working as intended.
| Rule | Default action | Plans |
|---|---|---|
| contains_pii | warn | All |
| contains_secret | warn | All |
| token_limit_exceeded | block | All — 8 000 estimated tokens |
Secret detection starts as warn deliberately: a first
request that trips the entropy filter should show up as a violation to investigate, not as a failure that
looks like a broken integration.
These defaults are seeded once, when the app is created — which is always before it has
a subscription. Subscribing later does not change them and does not add rules, so
contains_secret stays on
warn until you change it. If you want secrets blocked in
production, set the action yourself in the Rules tab.
prompt_injection is seeded only for an app created while
the organization is on Growth or Compliance; otherwise you create it yourself. Every default can be edited, disabled or deleted.
How the token limit is measured
token_limit_exceeded compares its limit against an estimate of
roughly four characters per token, not a provider tokenizer, so treat it as a guard against runaway
prompts rather than an exact accounting limit. In practice it only fires on the
ai.request: the estimate is made there, and no token count is
available at response time even for a rule that targets both. A rule created without an explicit limit
falls back to 4 000 tokens; the seeded default sets 8 000.
Managing Rules
Rules are managed per-app in the dashboard under the Rules tab. You can create, edit, enable/disable, and delete rules.
Each rule can be scoped to a specific environment or applied to all environments, and a rule can target
the prompt, the response or both. Rules run in priority then severity order, and evaluation stops at the
first block.
Some limits are worth knowing. A prompt over 200 KB is blocked outright, by a built-in rule reported as
input_size_guard, because scanning it reliably is not
possible in the request path. The string values inside tool inputs and tool-call arguments are evaluated on
a request, for OpenAI and Anthropic alike, and count toward that limit. An arguments string that is not valid
JSON is evaluated as raw text with its escape sequences as written, so a value that
directly follows one may not match. A tool input or arguments string that repeats a key is read by value,
with every copy of the key included. And each scan has a 200 ms budget: if a scan exceeds it, SignalVault fails
open — the content is not scanned and the request proceeds. Through the proxy, a request that matches a
redact rule can be refused rather than forwarded when a scan did not finish. Bodies over 4 MB are rejected before
reaching the rules at all.