@kindgi/guardrails 0.0.0-bootstrap.0 → 0.1.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/LICENSE +201 -0
- package/README.md +78 -1
- package/dist/action-handler.d.ts +82 -0
- package/dist/action-handler.d.ts.map +1 -0
- package/dist/action-handler.js +120 -0
- package/dist/action-handler.js.map +1 -0
- package/dist/checks.d.ts +9 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +235 -0
- package/dist/checks.js.map +1 -0
- package/dist/define-check.d.ts +93 -0
- package/dist/define-check.d.ts.map +1 -0
- package/dist/define-check.js +110 -0
- package/dist/define-check.js.map +1 -0
- package/dist/define.d.ts +27 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +126 -0
- package/dist/define.js.map +1 -0
- package/dist/engine.d.ts +49 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +198 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +91 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/execution-strategy.d.ts +80 -0
- package/dist/execution-strategy.d.ts.map +1 -0
- package/dist/execution-strategy.js +96 -0
- package/dist/execution-strategy.js.map +1 -0
- package/dist/guardrail.schema.json +261 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/judge.d.ts +31 -0
- package/dist/judge.d.ts.map +1 -0
- package/dist/judge.js +171 -0
- package/dist/judge.js.map +1 -0
- package/dist/types.d.ts +407 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -4
- package/src/action-handler.ts +179 -0
- package/src/checks.ts +236 -0
- package/src/define-check.ts +207 -0
- package/src/define.ts +146 -0
- package/src/engine.ts +271 -0
- package/src/errors.ts +107 -0
- package/src/execution-strategy.ts +184 -0
- package/src/guardrail.schema.json +261 -0
- package/src/index.ts +79 -0
- package/src/judge.ts +221 -0
- package/src/types.ts +455 -0
package/dist/checks.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* Built-in check library. Every entry is `kind: 'zero-llm'` — pure
|
|
5
|
+
* functions over the run trace, no external calls, deterministic. See
|
|
6
|
+
* `judge.ts` for LLM-judge evaluation.
|
|
7
|
+
*
|
|
8
|
+
* Adding a new built-in check: implement the function, add it to
|
|
9
|
+
* `BUILT_IN_CHECKS`, document its `config` schema in the JSDoc block.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* `must-cite`: assistant output must include at least N matches of the
|
|
13
|
+
* citation pattern. Config:
|
|
14
|
+
* `{ minCitations?: number /* default 1 *\/, sourcePattern?: string /* regex *\/ }`
|
|
15
|
+
*
|
|
16
|
+
* Default `sourcePattern` matches `[<name>]`-style citations; override for
|
|
17
|
+
* verticals with different citation conventions.
|
|
18
|
+
*/
|
|
19
|
+
const mustCite = async (config, trace) => {
|
|
20
|
+
const minCitations = typeof config.minCitations === 'number' ? config.minCitations : 1;
|
|
21
|
+
const sourcePattern = typeof config.sourcePattern === 'string' ? config.sourcePattern : '\\[[^\\]]+\\]';
|
|
22
|
+
if (trace.output === undefined || trace.output.length === 0) {
|
|
23
|
+
return { passed: false, reason: 'output empty; nothing to cite' };
|
|
24
|
+
}
|
|
25
|
+
const re = new RegExp(sourcePattern, 'g');
|
|
26
|
+
const matches = trace.output.match(re) ?? [];
|
|
27
|
+
if (matches.length >= minCitations) {
|
|
28
|
+
return { passed: true, attributes: { citationCount: matches.length } };
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
passed: false,
|
|
32
|
+
reason: `expected >= ${minCitations} citations, found ${matches.length}`,
|
|
33
|
+
attributes: { citationCount: matches.length },
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* `never-call-tool`: fail if any of the listed tools were invoked.
|
|
38
|
+
* Config: `{ tools: string[] }` — tool ids or names to forbid.
|
|
39
|
+
*/
|
|
40
|
+
const neverCallTool = async (config, trace) => {
|
|
41
|
+
// Accept both tool id / name strings and ToolRef objects
|
|
42
|
+
// ({ id, version }) — pack config authors may use either.
|
|
43
|
+
const rawTools = Array.isArray(config.tools) ? config.tools : [];
|
|
44
|
+
const forbidden = new Set();
|
|
45
|
+
for (const entry of rawTools) {
|
|
46
|
+
if (typeof entry === 'string') {
|
|
47
|
+
forbidden.add(entry);
|
|
48
|
+
}
|
|
49
|
+
else if (entry !== null &&
|
|
50
|
+
typeof entry === 'object' &&
|
|
51
|
+
'id' in entry &&
|
|
52
|
+
typeof entry.id === 'string') {
|
|
53
|
+
forbidden.add(entry.id);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const violations = [];
|
|
57
|
+
for (const call of trace.toolCalls) {
|
|
58
|
+
if (forbidden.has(call.toolId) || forbidden.has(call.toolName)) {
|
|
59
|
+
violations.push(call.toolName);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (violations.length === 0)
|
|
63
|
+
return { passed: true };
|
|
64
|
+
return {
|
|
65
|
+
passed: false,
|
|
66
|
+
reason: `forbidden tool(s) invoked: ${[...new Set(violations)].join(', ')}`,
|
|
67
|
+
attributes: { violatingTools: [...new Set(violations)] },
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* `max-tool-calls`: cap total tool invocations. Config: `{ max?: number }` (default 10).
|
|
72
|
+
* Guards against runaway agents.
|
|
73
|
+
*/
|
|
74
|
+
const maxToolCalls = async (config, trace) => {
|
|
75
|
+
const max = typeof config.max === 'number' ? config.max : 10;
|
|
76
|
+
if (trace.toolCalls.length <= max) {
|
|
77
|
+
return { passed: true, attributes: { toolCallCount: trace.toolCalls.length } };
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
passed: false,
|
|
81
|
+
reason: `expected <= ${max} tool calls, saw ${trace.toolCalls.length}`,
|
|
82
|
+
attributes: { toolCallCount: trace.toolCalls.length },
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* `output-matches`: final assistant output must match a regex (or fail
|
|
87
|
+
* if `negate: true`). Config: `{ pattern: string, flags?: string, negate?: boolean }`.
|
|
88
|
+
*/
|
|
89
|
+
const outputMatches = async (config, trace) => {
|
|
90
|
+
const pattern = typeof config.pattern === 'string' ? config.pattern : '';
|
|
91
|
+
const flags = typeof config.flags === 'string' ? config.flags : '';
|
|
92
|
+
const negate = config.negate === true;
|
|
93
|
+
if (pattern.length === 0) {
|
|
94
|
+
return { passed: false, reason: 'pattern config is required' };
|
|
95
|
+
}
|
|
96
|
+
const re = new RegExp(pattern, flags);
|
|
97
|
+
const output = trace.output ?? '';
|
|
98
|
+
const matched = re.test(output);
|
|
99
|
+
const passed = negate ? !matched : matched;
|
|
100
|
+
return passed
|
|
101
|
+
? { passed: true }
|
|
102
|
+
: {
|
|
103
|
+
passed: false,
|
|
104
|
+
reason: negate
|
|
105
|
+
? `output matched forbidden pattern /${pattern}/`
|
|
106
|
+
: `output did not match /${pattern}/`,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* `tool-order`: tool calls must appear in a specified order. Config:
|
|
111
|
+
* `{ sequence: string[] }` — tool names in expected order (subsequence).
|
|
112
|
+
* Non-listed tools are allowed to appear anywhere; the sequence must exist
|
|
113
|
+
* as a subsequence of the actual call order.
|
|
114
|
+
*/
|
|
115
|
+
const toolOrder = async (config, trace) => {
|
|
116
|
+
const sequence = Array.isArray(config.sequence) ? config.sequence : [];
|
|
117
|
+
if (sequence.length === 0)
|
|
118
|
+
return { passed: true };
|
|
119
|
+
let seqIndex = 0;
|
|
120
|
+
for (const call of trace.toolCalls) {
|
|
121
|
+
if (call.toolName === sequence[seqIndex])
|
|
122
|
+
seqIndex += 1;
|
|
123
|
+
if (seqIndex === sequence.length)
|
|
124
|
+
return { passed: true };
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
passed: false,
|
|
128
|
+
reason: `expected tool-call subsequence [${sequence.join(', ')}] not observed`,
|
|
129
|
+
attributes: { matchedPrefix: sequence.slice(0, seqIndex) },
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* `required-substring`: `trace.output` must contain EVERY listed pattern.
|
|
134
|
+
* Config: `{ patterns: string[], caseSensitive?: boolean }`.
|
|
135
|
+
*
|
|
136
|
+
* Mirror of `forbidden-substring` — enables "output must include the
|
|
137
|
+
* standard legal disclaimer / required attribution / policy footer"
|
|
138
|
+
* without needing an llm-judge.
|
|
139
|
+
*
|
|
140
|
+
* Empty `patterns` array passes vacuously. Missing `output` on the
|
|
141
|
+
* trace fails (nothing can contain the required text).
|
|
142
|
+
*/
|
|
143
|
+
const requiredSubstring = async (config, trace) => {
|
|
144
|
+
const patternsRaw = Array.isArray(config.patterns) ? config.patterns : [];
|
|
145
|
+
const patterns = patternsRaw.filter((p) => typeof p === 'string' && p.length > 0);
|
|
146
|
+
if (patterns.length === 0)
|
|
147
|
+
return { passed: true };
|
|
148
|
+
if (trace.output === undefined || trace.output.length === 0) {
|
|
149
|
+
return {
|
|
150
|
+
passed: false,
|
|
151
|
+
reason: `output empty; ${patterns.length} required pattern(s) not satisfied`,
|
|
152
|
+
attributes: { missing: patterns },
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const caseSensitive = config.caseSensitive === true;
|
|
156
|
+
const haystack = caseSensitive ? trace.output : trace.output.toLowerCase();
|
|
157
|
+
const missing = [];
|
|
158
|
+
for (const p of patterns) {
|
|
159
|
+
const needle = caseSensitive ? p : p.toLowerCase();
|
|
160
|
+
if (!haystack.includes(needle))
|
|
161
|
+
missing.push(p);
|
|
162
|
+
}
|
|
163
|
+
if (missing.length === 0)
|
|
164
|
+
return { passed: true };
|
|
165
|
+
return {
|
|
166
|
+
passed: false,
|
|
167
|
+
reason: `output missing required pattern(s): ${missing.join(', ')}`,
|
|
168
|
+
attributes: { missing },
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* `forbidden-substring`: `trace.output` must NOT contain any listed pattern.
|
|
173
|
+
* Config: `{ patterns: string[], caseSensitive?: boolean }`.
|
|
174
|
+
*
|
|
175
|
+
* Symmetric to `required-substring`. Enables "output must not contain
|
|
176
|
+
* PII markers / off-limits phrases / policy trigger words" without an
|
|
177
|
+
* llm-judge.
|
|
178
|
+
*/
|
|
179
|
+
const forbiddenSubstring = async (config, trace) => {
|
|
180
|
+
const patternsRaw = Array.isArray(config.patterns) ? config.patterns : [];
|
|
181
|
+
const patterns = patternsRaw.filter((p) => typeof p === 'string' && p.length > 0);
|
|
182
|
+
if (patterns.length === 0)
|
|
183
|
+
return { passed: true };
|
|
184
|
+
if (trace.output === undefined || trace.output.length === 0)
|
|
185
|
+
return { passed: true };
|
|
186
|
+
const caseSensitive = config.caseSensitive === true;
|
|
187
|
+
const haystack = caseSensitive ? trace.output : trace.output.toLowerCase();
|
|
188
|
+
const violated = [];
|
|
189
|
+
for (const p of patterns) {
|
|
190
|
+
const needle = caseSensitive ? p : p.toLowerCase();
|
|
191
|
+
if (haystack.includes(needle))
|
|
192
|
+
violated.push(p);
|
|
193
|
+
}
|
|
194
|
+
if (violated.length === 0)
|
|
195
|
+
return { passed: true };
|
|
196
|
+
return {
|
|
197
|
+
passed: false,
|
|
198
|
+
reason: `output contains forbidden pattern(s): ${violated.join(', ')}`,
|
|
199
|
+
attributes: { violated },
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const BUILT_IN_CHECKS = [
|
|
203
|
+
{ id: 'must-cite', kind: 'zero-llm', evaluate: mustCite },
|
|
204
|
+
{ id: 'never-call-tool', kind: 'zero-llm', evaluate: neverCallTool },
|
|
205
|
+
{ id: 'max-tool-calls', kind: 'zero-llm', evaluate: maxToolCalls },
|
|
206
|
+
{ id: 'output-matches', kind: 'zero-llm', evaluate: outputMatches },
|
|
207
|
+
{ id: 'tool-order', kind: 'zero-llm', evaluate: toolOrder },
|
|
208
|
+
{ id: 'required-substring', kind: 'zero-llm', evaluate: requiredSubstring },
|
|
209
|
+
{ id: 'forbidden-substring', kind: 'zero-llm', evaluate: forbiddenSubstring },
|
|
210
|
+
];
|
|
211
|
+
/**
|
|
212
|
+
* Create a fresh CheckRegistry pre-populated with built-in checks.
|
|
213
|
+
* Consumers register custom checks at pack init.
|
|
214
|
+
*/
|
|
215
|
+
export function createCheckRegistry(seed = []) {
|
|
216
|
+
const checks = new Map();
|
|
217
|
+
for (const c of BUILT_IN_CHECKS)
|
|
218
|
+
checks.set(c.id, c);
|
|
219
|
+
for (const c of seed)
|
|
220
|
+
checks.set(c.id, c);
|
|
221
|
+
return {
|
|
222
|
+
register(check) {
|
|
223
|
+
checks.set(check.id, check);
|
|
224
|
+
},
|
|
225
|
+
get(id) {
|
|
226
|
+
return checks.get(id);
|
|
227
|
+
},
|
|
228
|
+
list() {
|
|
229
|
+
return [...checks.values()];
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/** Exported for tests + downstream introspection. */
|
|
234
|
+
export const BUILT_IN_CHECK_IDS = BUILT_IN_CHECKS.map((c) => c.id);
|
|
235
|
+
//# sourceMappingURL=checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { AnySchema, ZodLikeSchema } from '@kindgi/schema';
|
|
2
|
+
import type { CheckFunction, GuardrailKind, RegisteredCheck } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Author-time inference from a Zod schema's `_zod.output`. Non-Zod
|
|
5
|
+
* schemas fall through to `Readonly<Record<string, unknown>>` — the
|
|
6
|
+
* same type that `Guardrail.config` already carries.
|
|
7
|
+
*/
|
|
8
|
+
export type InferCheckConfig<T> = T extends {
|
|
9
|
+
readonly _zod: {
|
|
10
|
+
readonly output: infer O;
|
|
11
|
+
};
|
|
12
|
+
} ? O : Readonly<Record<string, unknown>>;
|
|
13
|
+
/**
|
|
14
|
+
* The author-facing spec accepted by `defineCheck`. Extends
|
|
15
|
+
* `RegisteredCheck` with an optional `configSchema` slot that can be
|
|
16
|
+
* either a JSON Schema object or a Zod v4 schema. When set,
|
|
17
|
+
* `defineCheck` derives `validateConfig` from the schema — authors
|
|
18
|
+
* don't have to write it separately.
|
|
19
|
+
*
|
|
20
|
+
* `evaluate` is typed against the schema-inferred config for Zod-
|
|
21
|
+
* authored checks; JSON-Schema-authored checks fall back to
|
|
22
|
+
* `Readonly<Record<string, unknown>>`.
|
|
23
|
+
*/
|
|
24
|
+
export interface DefineCheckSpec<TConfigSchema extends AnySchema> {
|
|
25
|
+
/**
|
|
26
|
+
* Check identifier. Referenced by `Guardrail.check` on the wire.
|
|
27
|
+
* Convention: dot-namespaced for pack-authored checks (e.g.
|
|
28
|
+
* `'acme.max-citations'`); framework-shipped checks use stable ids
|
|
29
|
+
* like `'must-cite'` / `'never-call-tool'`.
|
|
30
|
+
*/
|
|
31
|
+
readonly id: string;
|
|
32
|
+
/**
|
|
33
|
+
* `'zero-llm'` — pure function over the trace (fast, deterministic,
|
|
34
|
+
* default). `'llm-judge'` — uses a model (opt-in, costs money;
|
|
35
|
+
* needs `bindings.providerRegistry` or `bindings.judgeProvider`).
|
|
36
|
+
* `'external'` — evaluated by a caller-registered strategy.
|
|
37
|
+
*/
|
|
38
|
+
readonly kind: GuardrailKind;
|
|
39
|
+
/**
|
|
40
|
+
* Config schema — Zod v4 or JSON Schema. When present, `defineCheck`
|
|
41
|
+
* derives `RegisteredCheck.validateConfig` from it, and
|
|
42
|
+
* `defineGuardrail` runs that against each `Guardrail.config`.
|
|
43
|
+
* Zod authors get schema-inferred config types on `evaluate`'s first
|
|
44
|
+
* parameter.
|
|
45
|
+
*/
|
|
46
|
+
readonly configSchema?: TConfigSchema;
|
|
47
|
+
/**
|
|
48
|
+
* The check function. Signature: `(config, trace, bindings) => Promise<CheckResult>`.
|
|
49
|
+
* `config` is the guardrail's declared config (typed via `configSchema`
|
|
50
|
+
* when Zod-authored). `trace` is the accumulated `RunTrace` from the
|
|
51
|
+
* agent turn. `bindings` is the `EvaluationBindings` the caller
|
|
52
|
+
* passed to the engine (`{}` when none).
|
|
53
|
+
* Return `{passed: true}` or `{passed: false, reason: string, ...}`.
|
|
54
|
+
*/
|
|
55
|
+
readonly evaluate: (config: InferCheckConfig<TConfigSchema>, trace: Parameters<CheckFunction>[1], bindings: Parameters<CheckFunction>[2]) => ReturnType<CheckFunction>;
|
|
56
|
+
/**
|
|
57
|
+
* Optional custom config validator. When `configSchema` is also set,
|
|
58
|
+
* both run — `configSchema` first, then this. `undefined` return means
|
|
59
|
+
* "config is valid"; non-undefined string is the error message.
|
|
60
|
+
*/
|
|
61
|
+
readonly validateConfig?: (config: unknown) => string | undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The concrete RegisteredCheck returned by `defineCheck`. When the
|
|
65
|
+
* author provided a Zod schema at `configSchema`, `configZod` is
|
|
66
|
+
* present so TS callers can `z.infer<typeof check.configZod>` for
|
|
67
|
+
* static types.
|
|
68
|
+
*/
|
|
69
|
+
export type DefinedCheck<TConfigSchema extends AnySchema> = RegisteredCheck & {
|
|
70
|
+
readonly configZod: TConfigSchema extends ZodLikeSchema ? TConfigSchema : undefined;
|
|
71
|
+
readonly configJsonSchema?: Readonly<Record<string, unknown>>;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Build a `RegisteredCheck` with optional schema-derived config
|
|
75
|
+
* validation. Two authoring surfaces coexist:
|
|
76
|
+
* 1. JSON Schema Draft 2020-12 objects — compiled at author time
|
|
77
|
+
* via Ajv; the check's `validateConfig` is derived from the
|
|
78
|
+
* compiled validator.
|
|
79
|
+
* 2. Zod v4 schemas — converted via `z.toJSONSchema()` (peer dep),
|
|
80
|
+
* then compiled the same way. TS callers get `z.infer<typeof
|
|
81
|
+
* check.configZod>` for static config typing.
|
|
82
|
+
*
|
|
83
|
+
* When `configSchema` is omitted, this behaves as a passthrough:
|
|
84
|
+
* returns the check with the caller's `validateConfig` (or undefined).
|
|
85
|
+
*
|
|
86
|
+
* Failures at author time (Zod conversion or Ajv compile) surface via
|
|
87
|
+
* throw — same failure mode as construction of a bad
|
|
88
|
+
* `RegisteredCheck` object literal. Consumers catch at pack-init;
|
|
89
|
+
* downstream `defineGuardrail` runs the derived `validateConfig` at
|
|
90
|
+
* spec-registration time and reports via `Result`.
|
|
91
|
+
*/
|
|
92
|
+
export declare function defineCheck<TConfigSchema extends AnySchema = AnySchema>(spec: DefineCheckSpec<TConfigSchema>): DefinedCheck<TConfigSchema>;
|
|
93
|
+
//# sourceMappingURL=define-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-check.d.ts","sourceRoot":"","sources":["../src/define-check.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/D,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAShF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;CAAE,GACvF,CAAC,GACD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe,CAAC,aAAa,SAAS,SAAS;IAC9D;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;IACtC;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,CACjB,MAAM,EAAE,gBAAgB,CAAC,aAAa,CAAC,EACvC,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EACnC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KACnC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;CACnE;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,CAAC,aAAa,SAAS,SAAS,IAAI,eAAe,GAAG;IAC5E,QAAQ,CAAC,SAAS,EAAE,aAAa,SAAS,aAAa,GAAG,aAAa,GAAG,SAAS,CAAC;IACpF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC/D,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,aAAa,SAAS,SAAS,GAAG,SAAS,EACrE,IAAI,EAAE,eAAe,CAAC,aAAa,CAAC,GACnC,YAAY,CAAC,aAAa,CAAC,CAiE7B"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
import * as addFormatsModule from 'ajv-formats';
|
|
4
|
+
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
5
|
+
import { isZodSchema, loadZodConverterSync, toJSONSchemaSync } from '@kindgi/schema';
|
|
6
|
+
const addFormatsRaw = addFormatsModule;
|
|
7
|
+
const addFormats = typeof addFormatsRaw === 'function'
|
|
8
|
+
? addFormatsRaw
|
|
9
|
+
: addFormatsRaw.default;
|
|
10
|
+
/**
|
|
11
|
+
* Build a `RegisteredCheck` with optional schema-derived config
|
|
12
|
+
* validation. Two authoring surfaces coexist:
|
|
13
|
+
* 1. JSON Schema Draft 2020-12 objects — compiled at author time
|
|
14
|
+
* via Ajv; the check's `validateConfig` is derived from the
|
|
15
|
+
* compiled validator.
|
|
16
|
+
* 2. Zod v4 schemas — converted via `z.toJSONSchema()` (peer dep),
|
|
17
|
+
* then compiled the same way. TS callers get `z.infer<typeof
|
|
18
|
+
* check.configZod>` for static config typing.
|
|
19
|
+
*
|
|
20
|
+
* When `configSchema` is omitted, this behaves as a passthrough:
|
|
21
|
+
* returns the check with the caller's `validateConfig` (or undefined).
|
|
22
|
+
*
|
|
23
|
+
* Failures at author time (Zod conversion or Ajv compile) surface via
|
|
24
|
+
* throw — same failure mode as construction of a bad
|
|
25
|
+
* `RegisteredCheck` object literal. Consumers catch at pack-init;
|
|
26
|
+
* downstream `defineGuardrail` runs the derived `validateConfig` at
|
|
27
|
+
* spec-registration time and reports via `Result`.
|
|
28
|
+
*/
|
|
29
|
+
export function defineCheck(spec) {
|
|
30
|
+
const converter = spec.configSchema !== undefined && isZodSchema(spec.configSchema)
|
|
31
|
+
? loadZodConverterSync()
|
|
32
|
+
: undefined;
|
|
33
|
+
let derivedValidator;
|
|
34
|
+
let jsonSchema;
|
|
35
|
+
let zodSchema;
|
|
36
|
+
if (spec.configSchema !== undefined) {
|
|
37
|
+
if (isZodSchema(spec.configSchema)) {
|
|
38
|
+
zodSchema = spec.configSchema;
|
|
39
|
+
const converted = toJSONSchemaSync(spec.configSchema, converter, 'input');
|
|
40
|
+
if (converted.kind === 'err') {
|
|
41
|
+
const err = {
|
|
42
|
+
code: 'invalid-check-definition',
|
|
43
|
+
message: `Check "${spec.id}" configSchema Zod conversion failed: ${converted.error.message}`,
|
|
44
|
+
checkId: spec.id,
|
|
45
|
+
cause: converted.error.cause,
|
|
46
|
+
};
|
|
47
|
+
throw errorFromDefinition(err);
|
|
48
|
+
}
|
|
49
|
+
jsonSchema = converted.value;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
jsonSchema = spec.configSchema;
|
|
53
|
+
}
|
|
54
|
+
const validator = compileValidator(jsonSchema, spec.id);
|
|
55
|
+
derivedValidator = (config) => {
|
|
56
|
+
if (!validator(config)) {
|
|
57
|
+
const errors = validator.errors ?? [];
|
|
58
|
+
const first = errors[0];
|
|
59
|
+
const path = first?.instancePath ?? '';
|
|
60
|
+
const message = first?.message ?? 'invalid config';
|
|
61
|
+
return `${path} ${message}`.trim();
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const chainValidator = (a, b) => {
|
|
67
|
+
if (a === undefined)
|
|
68
|
+
return b;
|
|
69
|
+
if (b === undefined)
|
|
70
|
+
return a;
|
|
71
|
+
return (config) => {
|
|
72
|
+
const first = a(config);
|
|
73
|
+
if (first !== undefined)
|
|
74
|
+
return first;
|
|
75
|
+
return b(config);
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
const validate = chainValidator(derivedValidator, spec.validateConfig);
|
|
79
|
+
const check = {
|
|
80
|
+
id: spec.id,
|
|
81
|
+
kind: spec.kind,
|
|
82
|
+
evaluate: spec.evaluate,
|
|
83
|
+
...(validate !== undefined && { validateConfig: validate }),
|
|
84
|
+
...(zodSchema !== undefined && { configZod: zodSchema }),
|
|
85
|
+
...(jsonSchema !== undefined && { configJsonSchema: jsonSchema }),
|
|
86
|
+
};
|
|
87
|
+
return check;
|
|
88
|
+
}
|
|
89
|
+
function compileValidator(schema, checkId) {
|
|
90
|
+
const ajv = new Ajv2020({ strict: true, allErrors: true, allowUnionTypes: false });
|
|
91
|
+
addFormats(ajv);
|
|
92
|
+
try {
|
|
93
|
+
return ajv.compile(schema);
|
|
94
|
+
}
|
|
95
|
+
catch (cause) {
|
|
96
|
+
const err = {
|
|
97
|
+
code: 'invalid-check-definition',
|
|
98
|
+
message: `Check "${checkId}" configSchema does not compile as JSON Schema Draft 2020-12: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
99
|
+
checkId,
|
|
100
|
+
cause,
|
|
101
|
+
};
|
|
102
|
+
throw errorFromDefinition(err);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function errorFromDefinition(err) {
|
|
106
|
+
const wrapped = new Error(err.message);
|
|
107
|
+
Object.assign(wrapped, err);
|
|
108
|
+
return wrapped;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=define-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-check.js","sourceRoot":"","sources":["../src/define-check.ts"],"names":[],"mappings":"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"}
|
package/dist/define.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Result } from '@kindgi/types';
|
|
2
|
+
import type { InvalidCheckConfigError, InvalidGuardrailError, UnknownCheckError } from './errors.js';
|
|
3
|
+
import type { CheckRegistry, Guardrail } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Validate a guardrail declaration + resolve its check.
|
|
6
|
+
*
|
|
7
|
+
* Fails if:
|
|
8
|
+
* 1. The declaration doesn't match `@kindgi/specs/guardrail.schema.json`.
|
|
9
|
+
* 2. The `check` id isn't in the registry.
|
|
10
|
+
* 3. The registered check's `kind` differs from the guardrail's `kind`.
|
|
11
|
+
* 4. The check has a config validator and `guardrail.config` fails it.
|
|
12
|
+
*
|
|
13
|
+
* Every failure surfaces at pack-init — before any run touches the guardrail.
|
|
14
|
+
*/
|
|
15
|
+
export declare function defineGuardrail(spec: Guardrail, checks: CheckRegistry): Result<Guardrail, InvalidGuardrailError | UnknownCheckError | InvalidCheckConfigError>;
|
|
16
|
+
/**
|
|
17
|
+
* Validate an arbitrary wire spec against `@kindgi/specs/guardrail.schema.json`.
|
|
18
|
+
* Unlike `defineGuardrail`, this does NOT resolve the `check` reference
|
|
19
|
+
* against a `CheckRegistry` — used by transport layers (e.g. the
|
|
20
|
+
* `@kindgi/api` guardrail routes) that accept metadata-only guardrail
|
|
21
|
+
* registrations. The check implementation must already be available to
|
|
22
|
+
* the server that evaluates the guardrail.
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateGuardrailSpec(spec: unknown): Result<Guardrail, InvalidGuardrailError>;
|
|
25
|
+
/** The `$id` of the JSON Schema this loader validates against. */
|
|
26
|
+
export declare const GUARDRAIL_SCHEMA_URI = "https://kindgi.com/schemas/v1/guardrail.schema.json";
|
|
27
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAe3D;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,aAAa,GACpB,MAAM,CAAC,SAAS,EAAE,qBAAqB,GAAG,iBAAiB,GAAG,uBAAuB,CAAC,CA4DxF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC,CA8B7F;AAED,kEAAkE;AAClE,eAAO,MAAM,oBAAoB,wDAAsB,CAAC"}
|
package/dist/define.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
import { createSpecRegistry } from '@kindgi/schema';
|
|
4
|
+
import guardrailSchema from './guardrail.schema.json' with { type: 'json' };
|
|
5
|
+
const GUARDRAIL_SCHEMA_ID = 'https://kindgi.com/schemas/v1/guardrail.schema.json';
|
|
6
|
+
let cachedRegistry;
|
|
7
|
+
function schemaRegistry() {
|
|
8
|
+
if (cachedRegistry !== undefined)
|
|
9
|
+
return cachedRegistry;
|
|
10
|
+
const built = createSpecRegistry([guardrailSchema]);
|
|
11
|
+
if (built.kind === 'err') {
|
|
12
|
+
throw new Error(`@kindgi/guardrails: bundled schema failed to compile: ${built.error.message}`);
|
|
13
|
+
}
|
|
14
|
+
cachedRegistry = built.value;
|
|
15
|
+
return cachedRegistry;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate a guardrail declaration + resolve its check.
|
|
19
|
+
*
|
|
20
|
+
* Fails if:
|
|
21
|
+
* 1. The declaration doesn't match `@kindgi/specs/guardrail.schema.json`.
|
|
22
|
+
* 2. The `check` id isn't in the registry.
|
|
23
|
+
* 3. The registered check's `kind` differs from the guardrail's `kind`.
|
|
24
|
+
* 4. The check has a config validator and `guardrail.config` fails it.
|
|
25
|
+
*
|
|
26
|
+
* Every failure surfaces at pack-init — before any run touches the guardrail.
|
|
27
|
+
*/
|
|
28
|
+
export function defineGuardrail(spec, checks) {
|
|
29
|
+
const r = schemaRegistry().validate(GUARDRAIL_SCHEMA_ID, spec);
|
|
30
|
+
if (r.kind === 'err') {
|
|
31
|
+
const err = r.error;
|
|
32
|
+
if (err.code !== 'validation-error') {
|
|
33
|
+
throw new Error(`@kindgi/guardrails: unexpected schema error ${err.code}: ${err.message}`);
|
|
34
|
+
}
|
|
35
|
+
const issues = err.errors.map((e) => {
|
|
36
|
+
const ajv = e;
|
|
37
|
+
return {
|
|
38
|
+
path: typeof ajv.instancePath === 'string' ? ajv.instancePath : '',
|
|
39
|
+
message: typeof ajv.message === 'string' ? ajv.message : 'validation failed',
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
kind: 'err',
|
|
44
|
+
error: { code: 'invalid-guardrail', message: err.message, issues },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const check = checks.get(spec.check);
|
|
48
|
+
if (check === undefined) {
|
|
49
|
+
return {
|
|
50
|
+
kind: 'err',
|
|
51
|
+
error: {
|
|
52
|
+
code: 'unknown-check',
|
|
53
|
+
message: `Guardrail "${spec.id}" references unregistered check "${spec.check}"`,
|
|
54
|
+
guardrailId: spec.id,
|
|
55
|
+
checkId: spec.check,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (check.kind !== spec.kind) {
|
|
60
|
+
return {
|
|
61
|
+
kind: 'err',
|
|
62
|
+
error: {
|
|
63
|
+
code: 'invalid-guardrail',
|
|
64
|
+
message: `Guardrail "${spec.id}" kind "${spec.kind}" does not match check "${spec.check}" kind "${check.kind}"`,
|
|
65
|
+
issues: [{ path: '/kind', message: `expected "${check.kind}"` }],
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (check.validateConfig !== undefined && spec.config !== undefined) {
|
|
70
|
+
const reason = check.validateConfig(spec.config);
|
|
71
|
+
if (reason !== undefined) {
|
|
72
|
+
return {
|
|
73
|
+
kind: 'err',
|
|
74
|
+
error: {
|
|
75
|
+
code: 'invalid-check-config',
|
|
76
|
+
message: `Guardrail "${spec.id}" config invalid: ${reason}`,
|
|
77
|
+
guardrailId: spec.id,
|
|
78
|
+
reason,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { kind: 'ok', value: spec };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate an arbitrary wire spec against `@kindgi/specs/guardrail.schema.json`.
|
|
87
|
+
* Unlike `defineGuardrail`, this does NOT resolve the `check` reference
|
|
88
|
+
* against a `CheckRegistry` — used by transport layers (e.g. the
|
|
89
|
+
* `@kindgi/api` guardrail routes) that accept metadata-only guardrail
|
|
90
|
+
* registrations. The check implementation must already be available to
|
|
91
|
+
* the server that evaluates the guardrail.
|
|
92
|
+
*/
|
|
93
|
+
export function validateGuardrailSpec(spec) {
|
|
94
|
+
if (spec === null || typeof spec !== 'object') {
|
|
95
|
+
return {
|
|
96
|
+
kind: 'err',
|
|
97
|
+
error: {
|
|
98
|
+
code: 'invalid-guardrail',
|
|
99
|
+
message: 'Guardrail spec must be an object',
|
|
100
|
+
issues: [{ path: '', message: 'must be an object' }],
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const r = schemaRegistry().validate(GUARDRAIL_SCHEMA_ID, spec);
|
|
105
|
+
if (r.kind === 'err') {
|
|
106
|
+
const err = r.error;
|
|
107
|
+
if (err.code !== 'validation-error') {
|
|
108
|
+
throw new Error(`@kindgi/guardrails: unexpected schema error ${err.code}: ${err.message}`);
|
|
109
|
+
}
|
|
110
|
+
const issues = err.errors.map((e) => {
|
|
111
|
+
const ajv = e;
|
|
112
|
+
return {
|
|
113
|
+
path: typeof ajv.instancePath === 'string' ? ajv.instancePath : '',
|
|
114
|
+
message: typeof ajv.message === 'string' ? ajv.message : 'validation failed',
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
kind: 'err',
|
|
119
|
+
error: { code: 'invalid-guardrail', message: err.message, issues },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return { kind: 'ok', value: spec };
|
|
123
|
+
}
|
|
124
|
+
/** The `$id` of the JSON Schema this loader validates against. */
|
|
125
|
+
export const GUARDRAIL_SCHEMA_URI = GUARDRAIL_SCHEMA_ID;
|
|
126
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}
|