Guardrail detectors — the inventory
Every detector this build registers, with its category, locality, phases, and version — with activation restrictions and categories without production coverage.
On this page
This page lists registered detector contracts and declared phases. Registration alone does not establish activation support or measured detection quality. The three companion pages answer “what will it miss?” in full: PII detectors and secrets & injection detectors and toxicity, topical, code & media detectors.
The registry
21 registered detectors across 7 categories: 17 embedded and 4 external, plus 1 drill stub that is listed and explicitly
not counted as coverage — it exercises the machinery, not a category.
pii — nine embedded detectors
| id | locality | phases | version |
|---|---|---|---|
pii.card |
embedded |
input, output, stream | pii.card-v1 |
pii.crypto |
embedded |
input, output, stream | pii.crypto-v1 |
pii.email |
embedded |
input, output, stream | pii.email-v1 |
pii.iban |
embedded |
input, output, stream | pii.iban-v1 |
pii.ip |
embedded |
input, output, stream | pii.ip-v1 |
pii.mac |
embedded |
input, output, stream | pii.mac-v1 |
pii.nationalid |
embedded |
input, output, stream | pii.nationalid-v1 |
pii.phone |
embedded |
input, output, stream | pii.phone-v1 |
pii.ssn |
embedded |
input, output, stream | pii.ssn-v1 |
sidecar.ner_pii |
sidecar |
input, output | sidecar.ner_pii-v1 |
The nine embedded ones cover structured formats only — a shape with a checksum or a fixed
grammar. Names, street addresses and organizations have no such shape; that is what
sidecar.ner_pii is intended to classify. Its stock activation is rejected pending runtime/model
qualification; this registration establishes no current NER efficacy.
Read each one’s gaps →
secrets, injection, toxicity, topical, code, multimodal
| id | category | locality | phases | version |
|---|---|---|---|---|
secrets.entropy |
secrets |
embedded |
input, output, stream* | secrets.entropy-v2 |
secrets.generic |
secrets |
embedded |
input, output, stream* | secrets.generic-v2+glb58d3f102cf3.… |
secrets.ruleset |
secrets |
embedded |
input, output, stream* | secrets.ruleset-v3+glb58d3f102cf3.… |
injection.heuristic |
injection |
embedded |
input, output | injection.heuristic-v1 |
injection.judge |
injection |
judge |
input | injection.judge-v1 |
sidecar.injection |
injection |
sidecar |
input | sidecar.injection-v1 |
toxicity.wordlist |
toxicity |
embedded |
input, output | toxicity.wordlist-v1 |
sidecar.safety |
toxicity |
sidecar |
input, output | sidecar.safety-v1 |
topical.keywords |
topical |
embedded |
input, output | topical.keywords-v1 |
code.patterns |
code |
embedded |
output only | code.patterns-v1 |
media.inventory |
multimodal |
embedded |
input only | media.inventory-v1 |
* The three secrets.* detectors declare the stream phase but implement no incremental
matcher. A stream binding naming one is accepted at boot, contributes no lane at run time,
discloses stream_unsupported, and applies the effective mode and failure posture. The stock
gateway rejects stream_fallback: buffer; acknowledged enforcing/closed withholds unreleased bytes.
Secrets & injection gaps → ·
toxicity, topical, code & media gaps →
The stub
| id | category | locality | phases | version |
|---|---|---|---|---|
drill.echo |
custom |
embedded |
input, output, stream* | drill.echo-v1 |
Categories without production coverage
custom has only the drill.echo test stub. A binding with an empty detector list is rejected,
and a binding’s category must match its registered detectors. Naming a vocabulary member does not
create a detector or establish coverage.
format registers one detector as a factory row, not a ready instance:
| id | category | locality | phases | version |
|---|---|---|---|---|
format.jsonschema |
format |
embedded |
output only | format.jsonschema-v1 (a live instance appends +cfg<sha7> over its schema bytes) |
It validates a response field against a JSON Schema document the workspace supplies on the
binding — there is no schema-less form, so guardrail.Detector(id) answers not-ok until a binding
configures one, and guardrails list (and so the count above) does not show it until it is
configured on at least one binding. Check a response against a JSON
schema is the configuration page and the limits that apply to
the schema itself.
Phases: refused at boot vs. degraded at run time
These are two different failures and operators regularly expect the wrong one.
| what you wrote | what happens |
|---|---|
A detector that does not declare the phase — code.patterns on stream, media.inventory on output |
Refused at boot. Config validation and guardrail.Compile both reject it. The process does not start, and no row is ever written to carry a fallback disclosure. |
A detector that declares the phase but implements no incremental matcher — any secrets.* on stream |
Accepted with supported fallback syntax, disclosed at run time. No incremental lane is available; stream_unsupported applies the selected mode/posture. Stock buffer activation is rejected; enforcing/closed withholds unreleased bytes. |
The first is the correct failure and not the one most operators expect: being told the wrong failure mode is what ships a config that will not boot. See Phases & streaming.
Locality — which detectors leave the box
| locality | what it is | leaves the process? |
|---|---|---|
embedded |
pure Go, in-process | no — ever. The subtree is import-restricted and swept by a test |
judge |
an LLM call to a configured judge model | yes |
sidecar |
an HTTP call to a model sidecar you run | yes |
Embedded detection makes no model call. Primary-provider traffic and other enabled services have their own network boundary; choosing embedded detectors alone does not prove process isolation.
Caveats that apply to a whole family
Rather than repeat these on nine detectors, they are stated once. Every one of them is printed
per detector by guardrails list.
The nine embedded pii.* detectors share these bounds
- Per field, not per document. A value split across a message boundary — halves in
messages[0]andmessages[1]— is never reassembled. Cross-message cases are misses and are reported as misses. - 128 KiB of inspected text in total. A document exceeding it is refused and disclosed as
detector_error, never silently truncated. - De-obfuscation is bounded. The invisible-character set is a Unicode property test (Cf and Mn) plus the variation-selector supplement plus a deliberately incomplete enumeration — an invisible rune outside those is a miss. The confusables fold is not a full TR39 skeleton: single-rune-to-single-byte mappings only, because multi-character mappings would break the byte correspondence the span contract rests on.
- Base64 payloads are decoded one level, when the encoded run is at least 12 characters. Hex, rot13, URL-encoding and nested double-encoding are not decoded.
- The streaming lane has three separate bounds and only one of them is about the value. See Phases & streaming for the measured ladder.
- A calibrated bound changes what
thresholdmeans. While an artifact licenses a detector version,thresholdandseverity_bandsread the licensed point instead of the raw signal — so the ladder collapses to one rung and the units change from signal strength to this version’s estimated precision. Four of the nine (pii.card,pii.crypto,pii.iban,pii.mac) never spend a calibrated bound at all, because every rule they carry is an exact match.
The three sidecar.* registrations share these limits
- Stock activation is unavailable. The reference protocol and synthetic transport tests do not qualify the model runtime or establish detector efficacy.
- A verdict is a raw model score, with
basis: reportedand no calibrated interval. - A field over 32 KiB refuses the scan, with a disclosed suspension instead of a verdict on a truncated prefix. The adapter sends decoded text, not media parts.
- In a custom Go embedding, unavailable calls produce failures whose consequences depend on mode and failure posture. An enforcing/closed policy can refuse; monitor preserves traffic.
- Model identity and operator license metadata do not verify model quality or license compliance.
How to read a measured figure here
Two further reading rules, both from the detectors’ own disclosures:
- A corpus its own author wrote certifies its own work.
code.patterns,toxicity.wordlistandtopical.keywordsare scored against fixtures written by the card that shipped them. That is exactly why their confidence basis staysreportedand is never minted asfixture. injectionnever carries an interval, at any basis. It is the one adversarial category in this build: attacker-chosen traffic is out-of-distribution by intent, so the exchangeability a conformal or binomial bound assumes is false for it. This is a rule, not a gap awaiting work.