@cendor/guardrails 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters.d.ts +150 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +393 -0
- package/dist/adapters.js.map +1 -0
- package/dist/decision.d.ts +45 -1
- package/dist/decision.d.ts.map +1 -1
- package/dist/decision.js +32 -2
- package/dist/decision.js.map +1 -1
- package/dist/index.d.ts +38 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +229 -40
- package/dist/index.js.map +1 -1
- package/dist/judge.d.ts +68 -0
- package/dist/judge.d.ts.map +1 -0
- package/dist/judge.js +115 -0
- package/dist/judge.js.map +1 -0
- package/dist/policy.d.ts +41 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +209 -0
- package/dist/policy.js.map +1 -0
- package/dist/redteam.d.ts +63 -0
- package/dist/redteam.d.ts.map +1 -0
- package/dist/redteam.js +154 -0
- package/dist/redteam.js.map +1 -0
- package/dist/rules.d.ts +17 -3
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +46 -6
- package/dist/rules.js.map +1 -1
- package/dist/semantic.d.ts +52 -0
- package/dist/semantic.d.ts.map +1 -0
- package/dist/semantic.js +100 -0
- package/dist/semantic.js.map +1 -0
- package/package.json +1 -1
package/dist/adapters.js
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in detection-tier adapters — beyond the deterministic tier-0 built-ins in `./rules`. The TS
|
|
3
|
+
* port of `cendor.guardrails.adapters`.
|
|
4
|
+
*
|
|
5
|
+
* These reach past regex/arithmetic to a **local ML classifier**, a **language detector**, a
|
|
6
|
+
* **hosted moderation endpoint**, and the three **hosted rails** (AWS Bedrock, Azure AI Content
|
|
7
|
+
* Safety, Google Model Armor) — the detection tier of docs/guardrails.md "Threat model". Each rides a
|
|
8
|
+
* **bring-your-own** dependency or client — never a hard dependency of this package: a classifier
|
|
9
|
+
* callable, a `detect` callable, or a provider client you pass in. They are re-exported through
|
|
10
|
+
* `./rules` (`rules.classifier` / `rules.language` / `rules.openaiModeration` /
|
|
11
|
+
* `rules.bedrockGuardrail` / `rules.azureContentSafety` / `rules.modelArmor`) and at the package root
|
|
12
|
+
* (`import { adapters } from '@cendor/guardrails'`).
|
|
13
|
+
*
|
|
14
|
+
* **Cloud check, local evidence.** The hosted rails call *your* cloud account (metered by the vendor
|
|
15
|
+
* — the base package stays local-first and free), but the verdict still runs through the same engine:
|
|
16
|
+
* every trip emits a local `GuardrailDecision` on the `@cendor/core` bus, so `@cendor/acttrace` chains
|
|
17
|
+
* it as tamper-evident evidence exactly like a deterministic rule. The reason records only which cloud
|
|
18
|
+
* policy fired — never the payload. The cloud clients are **duck-typed** (nothing here imports an AWS
|
|
19
|
+
* / Azure / Google SDK); construct the client and pass it in.
|
|
20
|
+
*
|
|
21
|
+
* **Honest claims.** There is **no jailbreak-detection claim** anywhere here. `classifier` is a
|
|
22
|
+
* generic, license-agnostic contract around a local classifier *you* supply (a prompt-injection
|
|
23
|
+
* classifier such as PromptGuard, an ONNX model, or a heuristic wires through it). Reproduce a
|
|
24
|
+
* model's public eval and publish the numbers before citing any detection rate — classifiers are
|
|
25
|
+
* beaten by mutation/obfuscation attacks, so layer them, don't trust one. See the "Threat model".
|
|
26
|
+
*
|
|
27
|
+
* This module imports only `./decision` and reuses `payloadText` from `./rules` (a hoisted function,
|
|
28
|
+
* so the `rules` ↔ `adapters` re-export cycle is safe at runtime).
|
|
29
|
+
*/
|
|
30
|
+
import { Verdict, defineGuardrail, } from './decision.js';
|
|
31
|
+
import { payloadText } from './rules.js';
|
|
32
|
+
/**
|
|
33
|
+
* Default the error policy from a guardrail's action: a `block` gate fails **closed**; a `flag`
|
|
34
|
+
* degrades to advisory (`fail_open`). An explicit `onError` always wins. (Same rule as `rules`.)
|
|
35
|
+
*/
|
|
36
|
+
function resolveOnError(action, onError) {
|
|
37
|
+
if (onError !== undefined)
|
|
38
|
+
return onError;
|
|
39
|
+
return action === 'flag' ? 'fail_open' : 'fail_closed';
|
|
40
|
+
}
|
|
41
|
+
/** Build an adapter's `Guardrail` via the leaf `defineGuardrail`, resolving the error policy. */
|
|
42
|
+
function mk(check, opts) {
|
|
43
|
+
return defineGuardrail(check, {
|
|
44
|
+
name: opts.name,
|
|
45
|
+
stage: opts.stage,
|
|
46
|
+
timeout: opts.timeout,
|
|
47
|
+
onError: resolveOnError(opts.action, opts.onError),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function get(obj, name, dflt = undefined) {
|
|
51
|
+
if (obj == null)
|
|
52
|
+
return dflt;
|
|
53
|
+
if (obj instanceof Map)
|
|
54
|
+
return obj.has(name) ? obj.get(name) : dflt;
|
|
55
|
+
if (typeof obj !== 'object' && typeof obj !== 'function')
|
|
56
|
+
return dflt;
|
|
57
|
+
const v = obj[name];
|
|
58
|
+
return v === undefined ? dflt : v;
|
|
59
|
+
}
|
|
60
|
+
// --------------------------------------------------------------------------- classifier
|
|
61
|
+
/** Normalise a classifier result (bool / number / `{label: score}`) to `[score, tripped]`. */
|
|
62
|
+
function score(result, label, threshold) {
|
|
63
|
+
if (typeof result === 'boolean')
|
|
64
|
+
return [result ? 1 : 0, result];
|
|
65
|
+
if (typeof result === 'number')
|
|
66
|
+
return [result, result >= threshold];
|
|
67
|
+
if (result !== null && typeof result === 'object') {
|
|
68
|
+
const rec = result;
|
|
69
|
+
let s;
|
|
70
|
+
if (label !== undefined) {
|
|
71
|
+
s = Number(rec[label] ?? 0);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const vals = Object.values(rec).map((v) => Number(v));
|
|
75
|
+
s = vals.length > 0 ? Math.max(...vals) : 0;
|
|
76
|
+
}
|
|
77
|
+
return [s, s >= threshold];
|
|
78
|
+
}
|
|
79
|
+
throw new TypeError(`classifier returned ${result === null ? 'null' : typeof result}; expected bool, number, or mapping`);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Wrap a **local classifier** as a guardrail — the generic, license-agnostic contract.
|
|
83
|
+
*
|
|
84
|
+
* `classify(text)` returns a float score in `[0, 1]`, a `{label: score}` mapping, or a bool. The
|
|
85
|
+
* guardrail trips when the (selected `label`'s, else the max) score `>= threshold` (or the bool is
|
|
86
|
+
* `true`). Bring **any** local classifier — an ONNX model, a transformers.js pipeline, a heuristic,
|
|
87
|
+
* or a prompt-injection classifier (PromptGuard-class). A remote classifier can hang, so set
|
|
88
|
+
* `timeout` / `onError` for it. No jailbreak-detection claim — see the module "Threat model" note.
|
|
89
|
+
*/
|
|
90
|
+
export function classifier(classify, opts = {}) {
|
|
91
|
+
const { threshold = 0.5, label, stage = 'input', action = 'block', name = 'classifier', reason, timeout, onError, } = opts;
|
|
92
|
+
const check = (payload, _ctx) => {
|
|
93
|
+
const [s, tripped] = score(classify(payloadText(payload)), label, threshold);
|
|
94
|
+
if (!tripped)
|
|
95
|
+
return null;
|
|
96
|
+
return new Verdict(action, reason ?? `${name}: score ${s.toFixed(2)} >= ${threshold}`);
|
|
97
|
+
};
|
|
98
|
+
return mk(check, { name, stage, action, timeout, onError });
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Trip when the payload's detected language is **not** in `allowed` (ISO codes; case-insensitive) —
|
|
102
|
+
* a guard against the language-switch bypass (smuggling disallowed content in another language). See
|
|
103
|
+
* the "Threat model".
|
|
104
|
+
*
|
|
105
|
+
* `detect(text) -> isoCode` is **bring-your-own**: the TS port bundles no language detector (adding
|
|
106
|
+
* one would be a heavy dependency), so `detect` is required. Without it the check throws a clear
|
|
107
|
+
* error, which the guardrail's `onError` policy turns into a block (default) or flag. Language ID on
|
|
108
|
+
* short/mixed text is unreliable — keep this advisory (`action: 'flag'`) unless you control the input.
|
|
109
|
+
*/
|
|
110
|
+
export function language(allowed, opts = {}) {
|
|
111
|
+
const { detect, stage = 'input', action = 'block', name = 'language', timeout, onError } = opts;
|
|
112
|
+
const allow = new Set([...allowed].map((a) => a.toLowerCase()));
|
|
113
|
+
const defaultDetect = (_text) => {
|
|
114
|
+
throw new Error('language() needs a detector: pass detect=(text) => isoCode. The TS port bundles no ' +
|
|
115
|
+
'language detector — wire your own (a small langid model, an ONNX/transformers.js classifier).');
|
|
116
|
+
};
|
|
117
|
+
const det = detect ?? defaultDetect;
|
|
118
|
+
const check = (payload, _ctx) => {
|
|
119
|
+
const text = payloadText(payload).trim();
|
|
120
|
+
if (!text)
|
|
121
|
+
return null;
|
|
122
|
+
const lang = det(text);
|
|
123
|
+
if (lang && !allow.has(lang.toLowerCase())) {
|
|
124
|
+
const listed = [...allow]
|
|
125
|
+
.sort()
|
|
126
|
+
.map((a) => `'${a}'`)
|
|
127
|
+
.join(', ');
|
|
128
|
+
return new Verdict(action, `language '${lang}' not in allowed [${listed}]`);
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
};
|
|
132
|
+
return mk(check, { name, stage, action, timeout, onError });
|
|
133
|
+
}
|
|
134
|
+
// --------------------------------------------------------------------------- openai_moderation
|
|
135
|
+
/** The category names an OpenAI moderation result flagged truthy (plain object or class instance). */
|
|
136
|
+
function flaggedCategories(categories) {
|
|
137
|
+
if (categories == null)
|
|
138
|
+
return [];
|
|
139
|
+
let entries;
|
|
140
|
+
if (categories instanceof Map) {
|
|
141
|
+
entries = [...categories.entries()];
|
|
142
|
+
}
|
|
143
|
+
else if (typeof categories === 'object') {
|
|
144
|
+
entries = Object.entries(categories);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
return entries
|
|
150
|
+
.filter(([, v]) => Boolean(v))
|
|
151
|
+
.map(([k]) => k)
|
|
152
|
+
.sort();
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Trip when OpenAI's **free, non-LLM** moderation endpoint flags the payload — the cheapest hosted
|
|
156
|
+
* tier. `client` is *your* OpenAI client (needs a key); this calls `client.moderations.create(...)`.
|
|
157
|
+
*
|
|
158
|
+
* Restrict to specific `categories` (e.g. `['violence', 'hate']`) or trip on any flag. It is a
|
|
159
|
+
* network call — bound it with `timeout` and pick an `onError` policy (fail-closed by default for a
|
|
160
|
+
* block gate). This library stores nothing; the request goes to OpenAI. The client/response are
|
|
161
|
+
* duck-typed, so any OpenAI-shaped client works.
|
|
162
|
+
*/
|
|
163
|
+
export function openaiModeration(client, opts = {}) {
|
|
164
|
+
const { model = 'omni-moderation-latest', categories, stage = 'input', action = 'block', name = 'openai_moderation', timeout, onError, } = opts;
|
|
165
|
+
const cats = categories ? new Set([...categories].map((c) => c.toLowerCase())) : null;
|
|
166
|
+
const check = async (payload, _ctx) => {
|
|
167
|
+
const moderations = get(client, 'moderations');
|
|
168
|
+
if (moderations == null || typeof moderations.create !== 'function') {
|
|
169
|
+
throw new TypeError('openaiModeration client has no moderations.create()');
|
|
170
|
+
}
|
|
171
|
+
const resp = await moderations.create({ model, input: payloadText(payload) });
|
|
172
|
+
const results = get(resp, 'results') ?? [];
|
|
173
|
+
if (results.length === 0)
|
|
174
|
+
return null;
|
|
175
|
+
const result = results[0];
|
|
176
|
+
const flagged = flaggedCategories(get(result, 'categories', {}));
|
|
177
|
+
if (cats !== null) {
|
|
178
|
+
const hit = flagged.filter((c) => cats.has(c.toLowerCase())).sort();
|
|
179
|
+
return hit.length > 0 ? new Verdict(action, `moderation flagged: ${hit.join(', ')}`) : null;
|
|
180
|
+
}
|
|
181
|
+
if (get(result, 'flagged', false)) {
|
|
182
|
+
const names = flagged.join(', ') || 'policy';
|
|
183
|
+
return new Verdict(action, `moderation flagged: ${names}`);
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
};
|
|
187
|
+
return mk(check, { name, stage, action, timeout, onError });
|
|
188
|
+
}
|
|
189
|
+
// --------------------------------------------------------------------------- hosted rails
|
|
190
|
+
//
|
|
191
|
+
// Each calls *your* cloud account (metered — cite the vendor's pricing page in the docs) and turns the
|
|
192
|
+
// vendor's verdict into a LOCAL GuardrailDecision → acttrace evidence: "cloud check, local evidence".
|
|
193
|
+
// The clients are duck-typed (no AWS/Azure/Google import here); the JS cloud SDKs are async, so these
|
|
194
|
+
// checks are async — use them via the SDK loop / evaluateAsync (the sync `install()` seam can't run them).
|
|
195
|
+
function uniq(items) {
|
|
196
|
+
const seen = [];
|
|
197
|
+
for (const x of items)
|
|
198
|
+
if (x && !seen.includes(x))
|
|
199
|
+
seen.push(x);
|
|
200
|
+
return seen;
|
|
201
|
+
}
|
|
202
|
+
function getList(obj, name) {
|
|
203
|
+
const v = get(obj, name);
|
|
204
|
+
return Array.isArray(v) ? v : [];
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* AWS Bedrock **`ApplyGuardrail`** as a guardrail — the flagship hosted rail: it evaluates any text
|
|
208
|
+
* against your pre-configured Bedrock guardrail **independently of any model**, so it works with any
|
|
209
|
+
* provider. `client` is duck-typed on `applyGuardrail(params) => Promise<resp>` (with aws-sdk v3, pass
|
|
210
|
+
* `{ applyGuardrail: (p) => client.send(new ApplyGuardrailCommand(p)) }`). `source` is chosen from the
|
|
211
|
+
* stage (`INPUT`/`OUTPUT`); `action: 'redact'` substitutes Bedrock's masked `outputs` text. Metered
|
|
212
|
+
* per text unit — set `timeout` / `onError`.
|
|
213
|
+
*/
|
|
214
|
+
export function bedrockGuardrail(client, guardrailId, opts = {}) {
|
|
215
|
+
const { stage = 'input', action = 'block', name = 'bedrock_guardrail', timeout, onError } = opts;
|
|
216
|
+
const check = async (payload, ctx) => {
|
|
217
|
+
const source = opts.source ?? (ctx.stage === 'output' || ctx.stage === 'tool_output' ? 'OUTPUT' : 'INPUT');
|
|
218
|
+
const apply = get(client, 'applyGuardrail');
|
|
219
|
+
if (typeof apply !== 'function') {
|
|
220
|
+
throw new TypeError('bedrockGuardrail client has no applyGuardrail(params) method');
|
|
221
|
+
}
|
|
222
|
+
const resp = await apply.call(client, {
|
|
223
|
+
guardrailIdentifier: guardrailId,
|
|
224
|
+
guardrailVersion: opts.guardrailVersion ?? 'DRAFT',
|
|
225
|
+
source,
|
|
226
|
+
content: [{ text: { text: payloadText(payload) } }],
|
|
227
|
+
});
|
|
228
|
+
if (get(resp, 'action') !== 'GUARDRAIL_INTERVENED')
|
|
229
|
+
return null;
|
|
230
|
+
const reason = bedrockReason(resp);
|
|
231
|
+
if (action === 'redact') {
|
|
232
|
+
const masked = bedrockMasked(resp);
|
|
233
|
+
if (masked != null)
|
|
234
|
+
return new Verdict('redact', reason, masked);
|
|
235
|
+
}
|
|
236
|
+
return new Verdict(action, reason);
|
|
237
|
+
};
|
|
238
|
+
return mk(check, { name, stage, action, timeout, onError });
|
|
239
|
+
}
|
|
240
|
+
function bedrockReason(resp) {
|
|
241
|
+
const actionReason = get(resp, 'actionReason');
|
|
242
|
+
if (typeof actionReason === 'string' && actionReason) {
|
|
243
|
+
return `Bedrock guardrail intervened: ${actionReason}`;
|
|
244
|
+
}
|
|
245
|
+
const labels = bedrockAssessmentLabels(resp);
|
|
246
|
+
return `Bedrock guardrail intervened: ${labels.length ? labels.join(', ') : 'policy'}`;
|
|
247
|
+
}
|
|
248
|
+
function bedrockAssessmentLabels(resp) {
|
|
249
|
+
const labels = [];
|
|
250
|
+
for (const a of getList(resp, 'assessments')) {
|
|
251
|
+
for (const t of getList(get(a, 'topicPolicy'), 'topics')) {
|
|
252
|
+
if (get(t, 'name'))
|
|
253
|
+
labels.push(`topic:${get(t, 'name')}`);
|
|
254
|
+
}
|
|
255
|
+
for (const f of getList(get(a, 'contentPolicy'), 'filters')) {
|
|
256
|
+
if (get(f, 'type'))
|
|
257
|
+
labels.push(`content:${get(f, 'type')}`);
|
|
258
|
+
}
|
|
259
|
+
const sp = get(a, 'sensitiveInformationPolicy');
|
|
260
|
+
for (const e of getList(sp, 'piiEntities')) {
|
|
261
|
+
if (get(e, 'type'))
|
|
262
|
+
labels.push(`pii:${get(e, 'type')}`);
|
|
263
|
+
}
|
|
264
|
+
for (const r of getList(sp, 'regexes')) {
|
|
265
|
+
if (get(r, 'name'))
|
|
266
|
+
labels.push(`regex:${get(r, 'name')}`);
|
|
267
|
+
}
|
|
268
|
+
const wp = get(a, 'wordPolicy');
|
|
269
|
+
if (getList(wp, 'customWords').length)
|
|
270
|
+
labels.push('word:custom');
|
|
271
|
+
for (const m of getList(wp, 'managedWordLists')) {
|
|
272
|
+
if (get(m, 'type'))
|
|
273
|
+
labels.push(`word:${get(m, 'type')}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return uniq(labels);
|
|
277
|
+
}
|
|
278
|
+
function bedrockMasked(resp) {
|
|
279
|
+
for (const o of getList(resp, 'outputs')) {
|
|
280
|
+
const t = get(o, 'text');
|
|
281
|
+
if (typeof t === 'string' && t)
|
|
282
|
+
return t;
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Azure AI Content Safety **Prompt Shields** as a guardrail — detects user-prompt/document
|
|
288
|
+
* injection & jailbreak attacks. `client` is duck-typed on
|
|
289
|
+
* `shieldPrompt({ userPrompt, documents }) => Promise<resp>` and trips when the response's
|
|
290
|
+
* `userPromptAnalysis.attackDetected` (or any `documentsAnalysis[].attackDetected`) is true — a binary
|
|
291
|
+
* signal, so `block` / `flag` are the meaningful actions. Metered per text record — set `timeout`.
|
|
292
|
+
*/
|
|
293
|
+
export function azureContentSafety(client, opts = {}) {
|
|
294
|
+
const { stage = 'input', action = 'block', name = 'azure_content_safety', timeout, onError, } = opts;
|
|
295
|
+
const documents = opts.documents ? [...opts.documents] : [];
|
|
296
|
+
const check = async (payload, _ctx) => {
|
|
297
|
+
const shield = get(client, 'shieldPrompt');
|
|
298
|
+
if (typeof shield !== 'function') {
|
|
299
|
+
throw new TypeError('azureContentSafety client has no shieldPrompt(options) method');
|
|
300
|
+
}
|
|
301
|
+
const resp = await shield.call(client, {
|
|
302
|
+
userPrompt: payloadText(payload),
|
|
303
|
+
documents,
|
|
304
|
+
});
|
|
305
|
+
const hits = azureAttacks(resp);
|
|
306
|
+
if (hits.length === 0)
|
|
307
|
+
return null;
|
|
308
|
+
return new Verdict(action, `Azure Prompt Shields: attack detected (${hits.join(', ')})`);
|
|
309
|
+
};
|
|
310
|
+
return mk(check, { name, stage, action, timeout, onError });
|
|
311
|
+
}
|
|
312
|
+
function azureAttacks(resp) {
|
|
313
|
+
const hits = [];
|
|
314
|
+
const upa = get(resp, 'userPromptAnalysis') ?? get(resp, 'user_prompt_analysis');
|
|
315
|
+
if (upa != null && (get(upa, 'attackDetected') || get(upa, 'attack_detected'))) {
|
|
316
|
+
hits.push('user prompt');
|
|
317
|
+
}
|
|
318
|
+
const da = get(resp, 'documentsAnalysis') ?? get(resp, 'documents_analysis');
|
|
319
|
+
if (Array.isArray(da)) {
|
|
320
|
+
da.forEach((d, i) => {
|
|
321
|
+
if (get(d, 'attackDetected') || get(d, 'attack_detected'))
|
|
322
|
+
hits.push(`document[${i}]`);
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
return hits;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Google Cloud **Model Armor** as a guardrail — screens prompts/responses against a template
|
|
329
|
+
* (prompt-injection & jailbreak, Sensitive Data Protection, malicious URIs, responsible-AI). `client`
|
|
330
|
+
* is duck-typed on `sanitizeUserPrompt(request)` / `sanitizeModelResponse(request)`; `template` is the
|
|
331
|
+
* full resource path `projects/{p}/locations/{l}/templates/{t}`. Trips when
|
|
332
|
+
* `sanitizationResult.filterMatchState` is `MATCH_FOUND`; the reason lists which filters matched.
|
|
333
|
+
* Metered per token — set `timeout`.
|
|
334
|
+
*/
|
|
335
|
+
export function modelArmor(client, template, opts = {}) {
|
|
336
|
+
const { stage = 'input', action = 'block', name = 'model_armor', timeout, onError } = opts;
|
|
337
|
+
const check = async (payload, ctx) => {
|
|
338
|
+
const text = payloadText(payload);
|
|
339
|
+
const isOutput = ctx.stage === 'output' || ctx.stage === 'tool_output';
|
|
340
|
+
const method = get(client, isOutput ? 'sanitizeModelResponse' : 'sanitizeUserPrompt');
|
|
341
|
+
if (typeof method !== 'function') {
|
|
342
|
+
throw new TypeError('modelArmor client is missing sanitizeUserPrompt/sanitizeModelResponse');
|
|
343
|
+
}
|
|
344
|
+
const request = isOutput
|
|
345
|
+
? { name: template, modelResponseData: { text } }
|
|
346
|
+
: { name: template, userPromptData: { text } };
|
|
347
|
+
const resp = await method.call(client, request);
|
|
348
|
+
const matched = modelArmorMatches(resp);
|
|
349
|
+
if (matched.length === 0)
|
|
350
|
+
return null;
|
|
351
|
+
return new Verdict(action, `Model Armor matched: ${matched.join(', ')}`);
|
|
352
|
+
};
|
|
353
|
+
return mk(check, { name, stage, action, timeout, onError });
|
|
354
|
+
}
|
|
355
|
+
const MATCH_FOUND = 'MATCH_FOUND';
|
|
356
|
+
function matchFound(state) {
|
|
357
|
+
const name = state?.name ?? (typeof state === 'string' ? state : undefined);
|
|
358
|
+
return name === MATCH_FOUND; // "NO_MATCH_FOUND" !== "MATCH_FOUND"
|
|
359
|
+
}
|
|
360
|
+
function modelArmorMatches(resp) {
|
|
361
|
+
const sr = get(resp, 'sanitizationResult') ?? get(resp, 'sanitization_result');
|
|
362
|
+
if (sr == null)
|
|
363
|
+
return [];
|
|
364
|
+
const top = get(sr, 'filterMatchState') ?? get(sr, 'filter_match_state');
|
|
365
|
+
if (!matchFound(top))
|
|
366
|
+
return [];
|
|
367
|
+
const fr = get(sr, 'filterResults') ?? get(sr, 'filter_results');
|
|
368
|
+
if (fr == null)
|
|
369
|
+
return ['filter'];
|
|
370
|
+
const entries = fr instanceof Map
|
|
371
|
+
? [...fr.entries()]
|
|
372
|
+
: typeof fr === 'object'
|
|
373
|
+
? Object.entries(fr)
|
|
374
|
+
: [];
|
|
375
|
+
const matched = entries.filter(([, v]) => containsMatch(v)).map(([k]) => String(k));
|
|
376
|
+
return matched.length ? matched : ['filter'];
|
|
377
|
+
}
|
|
378
|
+
function containsMatch(val, depth = 0) {
|
|
379
|
+
if (val == null || depth > 6)
|
|
380
|
+
return false;
|
|
381
|
+
const st = get(val, 'match_state') ?? get(val, 'matchState');
|
|
382
|
+
if (st != null && matchFound(st))
|
|
383
|
+
return true;
|
|
384
|
+
if (Array.isArray(val))
|
|
385
|
+
return val.some((v) => containsMatch(v, depth + 1));
|
|
386
|
+
if (val instanceof Map)
|
|
387
|
+
return [...val.values()].some((v) => containsMatch(v, depth + 1));
|
|
388
|
+
if (typeof val === 'object') {
|
|
389
|
+
return Object.values(val).some((v) => containsMatch(v, depth + 1));
|
|
390
|
+
}
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"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"}
|
package/dist/decision.d.ts
CHANGED
|
@@ -11,6 +11,16 @@ export type Stage = (typeof STAGES)[number];
|
|
|
11
11
|
/** What a tripped check does (mirrors acttrace's action vocabulary). */
|
|
12
12
|
export declare const ACTIONS: readonly ["block", "redact", "flag"];
|
|
13
13
|
export type Action = (typeof ACTIONS)[number];
|
|
14
|
+
/**
|
|
15
|
+
* What to do when a check *itself* errors or times out (as opposed to returning a verdict).
|
|
16
|
+
* `fail_closed` treats the error as a block (fail-safe — the default for a gate you rely on);
|
|
17
|
+
* `fail_open` records the failure as a `flag` and lets the call proceed (so a flaky tier-3/4 judge
|
|
18
|
+
* outage degrades to advisory rather than silently disabling the agent). Either way the failure is
|
|
19
|
+
* emitted as a `GuardrailDecision`, so the audit chain records that the check could not run —
|
|
20
|
+
* evidence, not a swallowed exception.
|
|
21
|
+
*/
|
|
22
|
+
export declare const ON_ERROR: readonly ["fail_closed", "fail_open"];
|
|
23
|
+
export type OnError = (typeof ON_ERROR)[number];
|
|
14
24
|
/** Coerce a stage spec (a single stage or a collection) to a validated array. */
|
|
15
25
|
export declare function normalizeStages(stage: string | readonly string[]): string[];
|
|
16
26
|
/**
|
|
@@ -40,14 +50,48 @@ export interface Guardrail {
|
|
|
40
50
|
name: string;
|
|
41
51
|
stages: string[];
|
|
42
52
|
check: Check;
|
|
53
|
+
/**
|
|
54
|
+
* Optional per-check wall-clock limit in **seconds**. Meant for slow tier-3/4 checks (an LLM
|
|
55
|
+
* judge, a hosted rail); deterministic built-ins run in microseconds and leave it `undefined`.
|
|
56
|
+
* Enforced on the **async** path only (`evaluateAsync`) — JS has no threads, so there is no true
|
|
57
|
+
* sync timeout (see `evaluate`). On the async path a coroutine check is bounded via
|
|
58
|
+
* `Promise.race`; on a throw/timeout the `onError` policy decides.
|
|
59
|
+
*/
|
|
60
|
+
timeout?: number;
|
|
61
|
+
/**
|
|
62
|
+
* What to do when the check *throws* or *times out*: `"fail_closed"` (default — treat it as a
|
|
63
|
+
* block) or `"fail_open"` (record a `flag` and proceed). Rule factories pick the safe default for
|
|
64
|
+
* their action; set it explicitly for a bring-your-own judge so an outage degrades to advisory
|
|
65
|
+
* instead of a hard stop (or vice-versa).
|
|
66
|
+
*/
|
|
67
|
+
onError?: OnError;
|
|
68
|
+
/**
|
|
69
|
+
* Static key/values merged into every `GuardrailDecision` this guardrail emits (under the caller's
|
|
70
|
+
* per-call `Context.metadata`, which wins a key clash). `loadPolicy` uses it to stamp
|
|
71
|
+
* `policy_hash` / `policy_version` so the audit chain proves which policy was active; also handy
|
|
72
|
+
* for a severity, owner, or ticket id. Keep values small and payload-free.
|
|
73
|
+
*/
|
|
74
|
+
metadata?: Record<string, unknown>;
|
|
43
75
|
}
|
|
44
76
|
export interface DefineGuardrailOptions {
|
|
45
77
|
stage?: string | readonly string[];
|
|
46
78
|
name?: string;
|
|
79
|
+
/** Per-check wall-clock limit in seconds (async path only); positive or `undefined`. */
|
|
80
|
+
timeout?: number;
|
|
81
|
+
/** Error/timeout policy (default `"fail_closed"`). */
|
|
82
|
+
onError?: OnError;
|
|
83
|
+
/** Static metadata merged into every decision this guardrail emits (see {@link Guardrail.metadata}). */
|
|
84
|
+
metadata?: Record<string, unknown>;
|
|
47
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Validate a guardrail's execution policy (mirrors Python's `Guardrail.__post_init__`). Throws on an
|
|
88
|
+
* unknown `onError` or a non-positive `timeout`.
|
|
89
|
+
*/
|
|
90
|
+
export declare function validateExecutionPolicy(timeout: number | undefined, onError: OnError): void;
|
|
48
91
|
/**
|
|
49
92
|
* Turn a `check(payload, ctx)` function into a `Guardrail` (the TS analogue of Python's
|
|
50
|
-
* `@guardrail` decorator — JS has no function decorators).
|
|
93
|
+
* `@guardrail` decorator — JS has no function decorators). `timeout` / `onError` set the per-check
|
|
94
|
+
* execution policy (see {@link Guardrail}).
|
|
51
95
|
*/
|
|
52
96
|
export declare function defineGuardrail(check: Check, opts?: DefineGuardrailOptions): Guardrail;
|
|
53
97
|
export interface GuardrailDecisionInit {
|
package/dist/decision.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,yDAAyD;AACzD,eAAO,MAAM,MAAM,0DAA2D,CAAC;AAC/E,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5C,wEAAwE;AACxE,eAAO,MAAM,OAAO,sCAAuC,CAAC;AAC5D,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAS3E;AAED;;;;GAIG;AACH,qBAAa,OAAO;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;gBAElB,MAAM,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,WAAW,GAAE,OAAc;CAUrE;AAED,+FAA+F;AAC/F,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,4GAA4G;AAC5G,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAEjG,sGAAsG;AACtG,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"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"}
|
package/dist/decision.js
CHANGED
|
@@ -9,6 +9,15 @@
|
|
|
9
9
|
export const STAGES = ['input', 'tool_call', 'tool_output', 'output'];
|
|
10
10
|
/** What a tripped check does (mirrors acttrace's action vocabulary). */
|
|
11
11
|
export const ACTIONS = ['block', 'redact', 'flag'];
|
|
12
|
+
/**
|
|
13
|
+
* What to do when a check *itself* errors or times out (as opposed to returning a verdict).
|
|
14
|
+
* `fail_closed` treats the error as a block (fail-safe — the default for a gate you rely on);
|
|
15
|
+
* `fail_open` records the failure as a `flag` and lets the call proceed (so a flaky tier-3/4 judge
|
|
16
|
+
* outage degrades to advisory rather than silently disabling the agent). Either way the failure is
|
|
17
|
+
* emitted as a `GuardrailDecision`, so the audit chain records that the check could not run —
|
|
18
|
+
* evidence, not a swallowed exception.
|
|
19
|
+
*/
|
|
20
|
+
export const ON_ERROR = ['fail_closed', 'fail_open'];
|
|
12
21
|
/** Coerce a stage spec (a single stage or a collection) to a validated array. */
|
|
13
22
|
export function normalizeStages(stage) {
|
|
14
23
|
const stages = typeof stage === 'string' ? [stage] : [...stage];
|
|
@@ -39,16 +48,37 @@ export class Verdict {
|
|
|
39
48
|
this.replacement = replacement;
|
|
40
49
|
}
|
|
41
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Validate a guardrail's execution policy (mirrors Python's `Guardrail.__post_init__`). Throws on an
|
|
53
|
+
* unknown `onError` or a non-positive `timeout`.
|
|
54
|
+
*/
|
|
55
|
+
export function validateExecutionPolicy(timeout, onError) {
|
|
56
|
+
if (!ON_ERROR.includes(onError)) {
|
|
57
|
+
throw new Error(`unknown onError ${JSON.stringify(onError)}; must be one of ${ON_ERROR.join(', ')}`);
|
|
58
|
+
}
|
|
59
|
+
if (timeout !== undefined && !(timeout > 0)) {
|
|
60
|
+
throw new Error(`timeout must be positive seconds or undefined, got ${JSON.stringify(timeout)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
42
63
|
/**
|
|
43
64
|
* Turn a `check(payload, ctx)` function into a `Guardrail` (the TS analogue of Python's
|
|
44
|
-
* `@guardrail` decorator — JS has no function decorators).
|
|
65
|
+
* `@guardrail` decorator — JS has no function decorators). `timeout` / `onError` set the per-check
|
|
66
|
+
* execution policy (see {@link Guardrail}).
|
|
45
67
|
*/
|
|
46
68
|
export function defineGuardrail(check, opts = {}) {
|
|
47
|
-
|
|
69
|
+
const onError = opts.onError ?? 'fail_closed';
|
|
70
|
+
validateExecutionPolicy(opts.timeout, onError);
|
|
71
|
+
const g = {
|
|
48
72
|
name: opts.name ?? (check.name || 'guardrail'),
|
|
49
73
|
stages: normalizeStages(opts.stage ?? 'input'),
|
|
50
74
|
check,
|
|
75
|
+
onError,
|
|
51
76
|
};
|
|
77
|
+
if (opts.timeout !== undefined)
|
|
78
|
+
g.timeout = opts.timeout;
|
|
79
|
+
if (opts.metadata !== undefined)
|
|
80
|
+
g.metadata = opts.metadata;
|
|
81
|
+
return g;
|
|
52
82
|
}
|
|
53
83
|
/**
|
|
54
84
|
* Evidence that a guardrail tripped or flagged — emitted on the `@cendor/core` bus. acttrace
|
package/dist/decision.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,yDAAyD;AACzD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAU,CAAC;AAG/E,wEAAwE;AACxE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC;AAG5D,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,KAAiC;IAC/D,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACzF,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAE,MAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,OAAO;IACT,MAAM,CAAS;IACf,MAAM,CAAS;IACf,WAAW,CAAU;IAE9B,YAAY,MAAc,EAAE,MAAM,GAAG,EAAE,EAAE,cAAuB,IAAI;QAClE,IAAI,CAAE,OAA6B,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CACb,kBAAkB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;
|
|
1
|
+
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../src/decision.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,9 +12,18 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { LLMCall } from '@cendor/core';
|
|
14
14
|
import { type Context, type Guardrail, GuardrailDecision } from './decision.js';
|
|
15
|
-
export { STAGES, ACTIONS, Verdict, GuardrailDecision, GuardrailTripped, defineGuardrail, normalizeStages, } from './decision.js';
|
|
16
|
-
export type { Stage, Action, Context, Check, Guardrail, DefineGuardrailOptions, } from './decision.js';
|
|
15
|
+
export { STAGES, ACTIONS, ON_ERROR, Verdict, GuardrailDecision, GuardrailTripped, defineGuardrail, normalizeStages, validateExecutionPolicy, } from './decision.js';
|
|
16
|
+
export type { Stage, Action, OnError, Context, Check, Guardrail, DefineGuardrailOptions, } from './decision.js';
|
|
17
17
|
export * as rules from './rules.js';
|
|
18
|
+
export * as judge from './judge.js';
|
|
19
|
+
export * as adapters from './adapters.js';
|
|
20
|
+
export * as semantic from './semantic.js';
|
|
21
|
+
export * as redteam from './redteam.js';
|
|
22
|
+
export { loadPolicy, POLICY_RULE_NAMES } from './policy.js';
|
|
23
|
+
export type { LoadedPolicy, LoadPolicyOptions } from './policy.js';
|
|
24
|
+
export type { Embed } from './semantic.js';
|
|
25
|
+
export { loadCorpus, runRedteam, runRedteamAsync, RedTeamReport } from './redteam.js';
|
|
26
|
+
export type { AttackCase, LoadCorpusOptions } from './redteam.js';
|
|
18
27
|
/** The result of evaluating a stage: the (possibly redacted) payload plus the recorded decisions. */
|
|
19
28
|
export interface EvalResult {
|
|
20
29
|
payload: unknown;
|
|
@@ -23,10 +32,15 @@ export interface EvalResult {
|
|
|
23
32
|
/**
|
|
24
33
|
* Run the `stage` guardrails over `payload` **synchronously**. Returns `{ payload, decisions }`
|
|
25
34
|
* with any redactions applied in order; throws `GuardrailTripped` on the first block. An `async`
|
|
26
|
-
* check throws here — use {@link evaluateAsync}.
|
|
35
|
+
* check throws here — use {@link evaluateAsync}. A *throwing* sync check honours its `onError`
|
|
36
|
+
* policy; `timeout` applies to the async path only (no sync threads in JS).
|
|
27
37
|
*/
|
|
28
38
|
export declare function evaluate(guardrails: readonly Guardrail[], stage: string, payload: unknown, ctx?: Context): EvalResult;
|
|
29
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Async counterpart of {@link evaluate}: awaits `async` checks (bounded by each guardrail's
|
|
41
|
+
* `timeout`), calls sync ones directly, and applies each guardrail's `onError` policy on a
|
|
42
|
+
* throw/timeout.
|
|
43
|
+
*/
|
|
30
44
|
export declare function evaluateAsync(guardrails: readonly Guardrail[], stage: string, payload: unknown, ctx?: Context): Promise<EvalResult>;
|
|
31
45
|
/** Gate `payload` and return the recorded decisions (throws `GuardrailTripped` on a block). */
|
|
32
46
|
export declare function apply(guardrails: readonly Guardrail[], stage: string, payload: unknown, ctx?: Context): GuardrailDecision[];
|
|
@@ -38,11 +52,30 @@ export declare function applyAsync(guardrails: readonly Guardrail[], stage: stri
|
|
|
38
52
|
* cleaned messages, a pass declines. tool_call: a block raises; else record + proceed (tools have
|
|
39
53
|
* no message-rewrite seam). Output: a bus subscriber raises **post-flight** on a block (same
|
|
40
54
|
* overshoot semantics as tokenguard's `onExceed:"raise"`). Runs sync checks only. Call
|
|
41
|
-
* {@link uninstall} to remove.
|
|
55
|
+
* {@link uninstall} to remove. `install()` is **process-global** — for a concurrent server that
|
|
56
|
+
* varies guardrails per request, use {@link scoped} instead.
|
|
42
57
|
*/
|
|
43
58
|
export declare function install(guardrails: readonly Guardrail[]): void;
|
|
44
59
|
/** Remove the interceptor + output subscriber registered by {@link install} (idempotent). */
|
|
45
60
|
export declare function uninstall(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Gate every instrumented call for the duration of `fn` — like {@link install}, but **scoped to the
|
|
63
|
+
* current execution context** rather than process-global. Runs `fn` with `guardrails` active and
|
|
64
|
+
* returns its result (sync or a `Promise`); the previous scope is restored on exit.
|
|
65
|
+
*
|
|
66
|
+
* With a real `AsyncLocalStorage` (auto-installed on Node), a concurrent server (async tasks) can
|
|
67
|
+
* vary guardrails per request without one request's set leaking into another. On edge/browser the
|
|
68
|
+
* fallback is a save/restore module variable — correct for sequential/nested use, **not**
|
|
69
|
+
* concurrency-safe. Nest freely — an inner `scoped` replaces the set for its block. Runs sync checks
|
|
70
|
+
* only (the seam is sync).
|
|
71
|
+
*
|
|
72
|
+
* ```ts
|
|
73
|
+
* await scoped([rules.keywordDeny(['secret'], { action: 'block' })], async () => {
|
|
74
|
+
* await client.chat.completions.create(...); // gated here
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function scoped<T>(guardrails: readonly Guardrail[], fn: () => T | Promise<T>): T | Promise<T>;
|
|
46
79
|
/** Best-effort assistant text off a completed LLMCall for the standalone output stage. */
|
|
47
80
|
export declare function responseText(call: LLMCall): string | null;
|
|
48
81
|
//# sourceMappingURL=index.d.ts.map
|