guardrails
A fail-closed guard around every model call, PII redaction (mask, hash, or tokenize), a swappable moderator, and an unconditional secret-shape gate.
@caisson/guardrails is the chokepoint between your app and a model call. guardInput
moderates then redacts PII on the way in; guardOutput moderates on the way out. Either leg
throws a GuardrailError (422) on a block, a moderator outage never silently lets content
through.
What it does
- Fail-closed by default: a moderator timeout or outage blocks the call unless the policy
explicitly sets
failOpen: true. - An unconditional secret-shape gate: before either leg reaches a moderator,
guard.tsrunslooksLikeSecret(text)and blocks category"secret"with no policy field and no opt-out. A leaked credential never becomes a moderation call, live or not. - A swappable
Moderatorport:localModeratoris a zero-network regex blocklist;providerModeratorwraps an injected async check for a real vendor call;customModeratorhooks in your own function. - A PII engine:
detectPiifinds email, SSN, Luhn-validated credit card, and phone spans.redactPiireplaces them irreversibly (mask→[EMAIL],hash→[EMAIL:ab12…]);tokenizePiiinstead seals the original via@caisson/field-cryptoand swaps in an opaque placeholder thatdetokenizePiican restore. - An FTC "4 Ps" dark-pattern evaluator:
evaluateFtc4Pscores marketing/UI copy across prominence, presentation, placement, and proximity; wrap it as a moderator withftc4pModeratorto gateguardOutputon your own copy. - A metadata-only blocked event: every block emits
guardrail.blockedto the kernelEventSinkwithblockId,stage,category,policy, andfailClosed: never the flagged text.
Install
bun add @caisson/guardrailsQuickstart
import { guardInput, guardOutput, localModerator } from "@caisson/guardrails";
const policy = {
policyName: "default",
moderator: localModerator(["forbidden phrase"]),
};
const runtime = { tenantId: accountId, sink: eventSink };
const { text: safeInput, tokens } = await guardInput(userText, policy, runtime);
// ... send safeInput to the model ...
await guardOutput(modelReply, policy, runtime); // throws GuardrailError if the reply is flaggedPII redaction modes
import { detectPii, redactPii, tokenizePii, detokenizePii } from "@caisson/guardrails";
const matches = detectPii(text); // email, ssn, credit_card, phone spans
const { text: masked } = redactPii(text, "mask"); // "[EMAIL]" — irreversible
const { text: hashed } = redactPii(text, "hash"); // "[EMAIL:ab12…]" — irreversible, correlatable
// tokenize seals the original via field-crypto; detokenizePii restores it under the same context.
const { text: tokenized, tokens } = tokenizePii(text, ctx);
const restored = detokenizePii(tokenized, tokens, ctx);Configuration
A GuardPolicy carries the moderator, an optional failOpen (default false), a
timeoutMs deadline (2000ms default) for moderateWithDeadline, an always-on cheapDeny
regex pre-screen, and an optional pii mode for the input leg. GuardRuntime carries the
tenantId and the kernel EventSink the block event emits to.
Composition
Guardrails is a base primitive, it never imports an edition. It composes @caisson/kernel
for the EventSink/looksLikeSecret primitives and @caisson/field-crypto for reversible
PII tokenization; the AI-Production bundle's metered gateway wires guardInput/guardOutput
around its infer()/embed() calls.
Entitlement
Guardrails ships inside the AI-Production bundle (with ai-meter and prompt-registry) or standalone.
ai-evals
A regression gate for prompt and model changes, defineEval() scores a dataset through a grader taxonomy, gateAgainstBaseline() fails the build on a real score drop, all offline and deterministic.
prompt-registry
Append-only prompt versioning with name@version and name@alias addressing, a mutable alias pointer for zero-redeploy promotion, and injection-safe rendering.