@intflows/genkit-guard 0.0.13 → 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.
@@ -0,0 +1,23 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ export async function publishDecision(config, start, fields) {
3
+ const decision = Object.freeze({
4
+ schemaVersion: '1', decisionId: randomUUID(), timestamp: new Date().toISOString(),
5
+ policyVersion: config?.policyVersion ?? 'unversioned',
6
+ latencyMs: Math.max(0, performance.now() - start), ...fields,
7
+ });
8
+ const warning = decision.action === 'block' || decision.action === 'approval-required';
9
+ const level = config?.logging?.level ?? 'info';
10
+ if ((config?.logging?.enabled ?? true) && level !== 'error' && (level !== 'warn' || warning)) {
11
+ const record = {
12
+ timestamp: decision.timestamp, severityText: warning ? 'WARN' : 'INFO',
13
+ severityNumber: warning ? 13 : 9, body: 'Guard policy decision',
14
+ resource: { attributes: { 'service.name': config?.logging?.serviceName ?? '@intflows/genkit-guard' } },
15
+ attributes: { 'event.name': 'guard.decision', 'code.namespace': 'genkit-guard', decision },
16
+ };
17
+ (warning ? console.warn : console.log)(JSON.stringify(record));
18
+ }
19
+ // Persist before invoking the callback. Neither failure may trigger a model fallback.
20
+ await config?.logging?.store?.append(decision);
21
+ await config?.logging?.onDecision?.(decision);
22
+ return decision;
23
+ }
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+ import type { GuardDecision } from './decision.js';
3
+ export interface GuardDecisionStore {
4
+ append(decision: GuardDecision): void | Promise<void>;
5
+ }
6
+ /** Validates the v1 contract and strips unknown fields before persistence. */
7
+ export declare const guardDecisionSchema: z.ZodObject<{
8
+ schemaVersion: z.ZodLiteral<"1">;
9
+ decisionId: z.ZodString;
10
+ timestamp: z.ZodString;
11
+ guard: z.ZodEnum<{
12
+ injection: "injection";
13
+ intent: "intent";
14
+ pii: "pii";
15
+ tool: "tool";
16
+ }>;
17
+ policyVersion: z.ZodString;
18
+ action: z.ZodEnum<{
19
+ allow: "allow";
20
+ block: "block";
21
+ redact: "redact";
22
+ "approval-required": "approval-required";
23
+ }>;
24
+ reasonCode: z.ZodEnum<{
25
+ INJECTION_PATTERN: "INJECTION_PATTERN";
26
+ INJECTION_CLEAR: "INJECTION_CLEAR";
27
+ INTENT_ALLOWED: "INTENT_ALLOWED";
28
+ INTENT_REJECTED: "INTENT_REJECTED";
29
+ PII_DETECTED: "PII_DETECTED";
30
+ PII_CLEAR: "PII_CLEAR";
31
+ TOOL_ALLOWED: "TOOL_ALLOWED";
32
+ TOOL_BLOCKED: "TOOL_BLOCKED";
33
+ TOOL_REDACTED: "TOOL_REDACTED";
34
+ TOOL_APPROVAL_REQUIRED: "TOOL_APPROVAL_REQUIRED";
35
+ TOOL_APPROVED: "TOOL_APPROVED";
36
+ TOOL_APPROVAL_DENIED: "TOOL_APPROVAL_DENIED";
37
+ TOOL_POLICY_ERROR: "TOOL_POLICY_ERROR";
38
+ MODEL_FALLBACK_USED: "MODEL_FALLBACK_USED";
39
+ MODEL_UNAVAILABLE: "MODEL_UNAVAILABLE";
40
+ }>;
41
+ latencyMs: z.ZodNumber;
42
+ confidence: z.ZodOptional<z.ZodNumber>;
43
+ }, z.core.$strip>;
44
+ export declare function createGuardDecisionStore(adapter: GuardDecisionStore): GuardDecisionStore;
45
+ export interface JsonlDecisionStore extends GuardDecisionStore {
46
+ /** Read the complete file. Missing files return []; malformed records reject. */
47
+ read(): Promise<GuardDecision[]>;
48
+ }
49
+ /** Single-process JSONL writer. Each append is flushed before it resolves. */
50
+ export declare function createJsonlDecisionStore(filePath: string): JsonlDecisionStore;
@@ -0,0 +1,84 @@
1
+ import { open, mkdir, readFile } from 'node:fs/promises';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { z } from 'zod';
4
+ /** Validates the v1 contract and strips unknown fields before persistence. */
5
+ export const guardDecisionSchema = z.object({
6
+ schemaVersion: z.literal('1'),
7
+ decisionId: z.string().min(1), timestamp: z.string().datetime(),
8
+ guard: z.enum(['injection', 'intent', 'pii', 'tool']),
9
+ policyVersion: z.string(),
10
+ action: z.enum(['allow', 'block', 'redact', 'approval-required']),
11
+ reasonCode: z.enum([
12
+ 'INJECTION_PATTERN', 'INJECTION_CLEAR', 'INTENT_ALLOWED', 'INTENT_REJECTED',
13
+ 'PII_DETECTED', 'PII_CLEAR', 'TOOL_ALLOWED', 'TOOL_BLOCKED', 'TOOL_REDACTED',
14
+ 'TOOL_APPROVAL_REQUIRED', 'TOOL_APPROVED', 'TOOL_APPROVAL_DENIED', 'TOOL_POLICY_ERROR',
15
+ 'MODEL_FALLBACK_USED', 'MODEL_UNAVAILABLE',
16
+ ]),
17
+ latencyMs: z.number().finite().nonnegative(), confidence: z.number().finite().optional(),
18
+ });
19
+ export function createGuardDecisionStore(adapter) {
20
+ return { append: decision => adapter.append(guardDecisionSchema.parse(decision)) };
21
+ }
22
+ // Serialize instances targeting the same resolved path within this process.
23
+ const queues = new Map();
24
+ function enqueue(path, task) {
25
+ const result = (queues.get(path) ?? Promise.resolve()).catch(() => { }).then(task);
26
+ queues.set(path, result);
27
+ void result.then(() => { if (queues.get(path) === result)
28
+ queues.delete(path); }, () => { if (queues.get(path) === result)
29
+ queues.delete(path); });
30
+ return result;
31
+ }
32
+ /** Single-process JSONL writer. Each append is flushed before it resolves. */
33
+ export function createJsonlDecisionStore(filePath) {
34
+ const path = resolve(filePath);
35
+ return {
36
+ append(decision) {
37
+ // Serialize immediately so callers cannot change a queued record.
38
+ const line = JSON.stringify(guardDecisionSchema.parse(decision)) + '\n';
39
+ return enqueue(path, async () => {
40
+ await mkdir(dirname(path), { recursive: true });
41
+ const file = await open(path, 'a+', 0o600);
42
+ try {
43
+ const { size } = await file.stat();
44
+ if (size > 0) {
45
+ const tail = Buffer.alloc(1);
46
+ await file.read(tail, 0, 1, size - 1);
47
+ if (tail[0] !== 10)
48
+ throw new Error('Incomplete decision log record');
49
+ }
50
+ await file.writeFile(line, 'utf8');
51
+ await file.sync();
52
+ }
53
+ finally {
54
+ await file.close();
55
+ }
56
+ });
57
+ },
58
+ read() {
59
+ return enqueue(path, async () => {
60
+ let contents;
61
+ try {
62
+ contents = await readFile(path, 'utf8');
63
+ }
64
+ catch (error) {
65
+ if (error.code === 'ENOENT')
66
+ return [];
67
+ throw error;
68
+ }
69
+ if (!contents)
70
+ return [];
71
+ if (!contents.endsWith('\n'))
72
+ throw new Error('Incomplete decision log record');
73
+ return contents.slice(0, -1).split('\n').map((line, index) => {
74
+ try {
75
+ return guardDecisionSchema.parse(JSON.parse(line));
76
+ }
77
+ catch {
78
+ throw new Error(`Invalid decision log record at line ${index + 1}`);
79
+ }
80
+ });
81
+ });
82
+ },
83
+ };
84
+ }
@@ -0,0 +1,33 @@
1
+ export type GuardAction = 'allow' | 'block' | 'redact' | 'approval-required';
2
+ export type GuardReasonCode = 'INJECTION_PATTERN' | 'INJECTION_CLEAR' | 'INTENT_ALLOWED' | 'INTENT_REJECTED' | 'PII_DETECTED' | 'PII_CLEAR' | 'TOOL_ALLOWED' | 'TOOL_BLOCKED' | 'TOOL_REDACTED' | 'TOOL_APPROVAL_REQUIRED' | 'TOOL_APPROVED' | 'TOOL_APPROVAL_DENIED' | 'TOOL_POLICY_ERROR' | 'MODEL_FALLBACK_USED' | 'MODEL_UNAVAILABLE';
3
+ /** Content-free audit contract. Version independently of the npm package. */
4
+ export interface GuardDecision {
5
+ schemaVersion: '1';
6
+ decisionId: string;
7
+ timestamp: string;
8
+ guard: 'injection' | 'intent' | 'pii' | 'tool';
9
+ policyVersion: string;
10
+ action: GuardAction;
11
+ reasonCode: GuardReasonCode;
12
+ latencyMs: number;
13
+ confidence?: number;
14
+ }
15
+ export interface ToolPolicyContext {
16
+ toolName: string;
17
+ /** A copy of the restored arguments. Never included in GuardDecision events. */
18
+ input: unknown;
19
+ /** Trusted application context supplied by Genkit, not model arguments. */
20
+ context: unknown;
21
+ }
22
+ export interface ToolGuardConfig {
23
+ /** Default allow preserves existing behavior. Use block for an allowlist. */
24
+ defaultAction?: GuardAction;
25
+ rules?: Record<string, GuardAction>;
26
+ /** Called only for approval-required rules; only literal true authorizes execution. */
27
+ approve?: (call: ToolPolicyContext) => boolean | Promise<boolean>;
28
+ }
29
+ /** Thrown before tool execution for blocked, pending, denied or failed policies. */
30
+ export declare class GuardToolError extends Error {
31
+ readonly decision: GuardDecision;
32
+ constructor(decision: GuardDecision);
33
+ }
@@ -0,0 +1,9 @@
1
+ /** Thrown before tool execution for blocked, pending, denied or failed policies. */
2
+ export class GuardToolError extends Error {
3
+ decision;
4
+ constructor(decision) {
5
+ super(`Tool execution stopped: ${decision.reasonCode}`);
6
+ this.decision = decision;
7
+ this.name = 'GuardToolError';
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ import type { GuardConfig } from './middleware/middleware.js';
2
+ /** Model labels (case insensitive, optional BIOES prefix) to masking token types. */
3
+ export type PiiLabelMappings = Record<string, string | null>;
4
+ /** Define an application-owned guard.config.ts and pass it to both public APIs. */
5
+ export declare function defineGuardConfig(config: GuardConfig): GuardConfig;
6
+ export declare function resolveGuardModels(config?: GuardConfig): {
7
+ extractor: string;
8
+ mode: "ner" | "classifier";
9
+ pii: string;
10
+ };
@@ -0,0 +1,12 @@
1
+ /** Define an application-owned guard.config.ts and pass it to both public APIs. */
2
+ export function defineGuardConfig(config) {
3
+ return config;
4
+ }
5
+ export function resolveGuardModels(config) {
6
+ const mode = config?.pii?.mode ?? 'ner';
7
+ return {
8
+ extractor: config?.models?.extractor ?? 'Xenova/all-MiniLM-L6-v2',
9
+ mode,
10
+ pii: config?.pii?.model ?? (mode === 'ner' ? 'Xenova/bert-base-NER' : 'openai/privacy-filter'),
11
+ };
12
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,10 @@
1
+ export { createGuardDecisionStore, createJsonlDecisionStore, guardDecisionSchema } from './core/decision-storage.js';
2
+ export type { GuardDecisionStore, JsonlDecisionStore } from './core/decision-storage.js';
3
+ export { GuardModelError } from './util/fallback.js';
4
+ export * from './core/decision.js';
5
+ import type { GuardConfig } from './middleware/middleware.js';
6
+ export { defineGuardConfig } from './guard.config.js';
7
+ export type { PiiLabelMappings } from './guard.config.js';
1
8
  export { guard, guardAction, guardMiddleware, guardPlugin } from './middleware/middleware.js';
2
9
  export type { GuardConfig } from './middleware/middleware.js';
3
10
  export { InMemoryPiiVaultStorage, createPiiVaultStorage, createRedisPiiVaultStorage, defaultPiiVaultStorage, } from './pii/storage.js';
@@ -6,4 +13,4 @@ export * from './core/types.js';
6
13
  /**
7
14
  * Pre-load the model to avoid cold-start delay on first user request.
8
15
  */
9
- export declare function initGuard(config?: any): Promise<void>;
16
+ export declare function initGuard(config?: GuardConfig): Promise<void>;
package/dist/index.js CHANGED
@@ -1,3 +1,9 @@
1
+ export { createGuardDecisionStore, createJsonlDecisionStore, guardDecisionSchema } from './core/decision-storage.js';
2
+ export { GuardModelError } from './util/fallback.js';
3
+ import { runGuardModel } from './util/fallback.js';
4
+ export * from './core/decision.js';
5
+ import { resolveGuardModels } from './guard.config.js';
6
+ export { defineGuardConfig } from './guard.config.js';
1
7
  import { ModelSingleton } from './util/singleton.js';
2
8
  // export { intentGuard, piiGuard } from './middleware/middleware.js';
3
9
  export { guard, guardAction, guardMiddleware, guardPlugin } from './middleware/middleware.js';
@@ -26,16 +32,11 @@ function logGuardEvent(eventName, body, attributes = {}) {
26
32
  */
27
33
  export async function initGuard(config) {
28
34
  logGuardEvent('guard.models.loading', 'Loading local guard models');
29
- const extractorModel = config?.models?.extractor ?? 'Xenova/all-MiniLM-L6-v2';
30
- const piiModel = config?.pii?.model;
31
- const piiMode = config?.pii?.mode ?? 'ner';
32
- const tasks = [ModelSingleton.getExtractor(extractorModel)];
33
- if (piiMode === 'ner') {
34
- tasks.push(ModelSingleton.getNER(piiModel ?? 'Xenova/bert-base-NER'));
35
- }
36
- else {
37
- tasks.push(ModelSingleton.getPIIClassifier(piiModel ?? 'openai/privacy-filter'));
38
- }
35
+ const { extractor, pii, mode: piiMode } = resolveGuardModels(config);
36
+ const loadPii = (model, mode) => mode === 'ner'
37
+ ? ModelSingleton.getNER(model) : ModelSingleton.getPIIClassifier(model);
38
+ const tasks = [runGuardModel(config, 'intent', () => ModelSingleton.getExtractor(extractor), config?.models?.extractorFallback ? () => ModelSingleton.getExtractor(config.models.extractorFallback) : undefined)];
39
+ tasks.push(runGuardModel(config, 'pii', () => loadPii(pii, piiMode), config?.pii?.fallback ? () => loadPii(config.pii.fallback.model, config.pii.fallback.mode ?? piiMode) : undefined));
39
40
  await Promise.all(tasks);
40
41
  logGuardEvent('guard.models.loaded', 'Local guard models loaded', {
41
42
  piiMode,
@@ -1,5 +1,5 @@
1
1
  export declare function detectInjection(userInput: string): Promise<boolean>;
2
- export declare function analyzeIntentStructured(input: string, intents: Record<string, string>, threshold: number): Promise<{
2
+ export declare function analyzeIntentStructured(input: string, intents: Record<string, string>, threshold: number, model?: string): Promise<{
3
3
  intent: string;
4
4
  score: number;
5
5
  allowed: boolean;
@@ -58,8 +58,8 @@ const INJECTION_PATTERNS = [
58
58
  export async function detectInjection(userInput) {
59
59
  return INJECTION_PATTERNS.some(p => userInput.toLowerCase().includes(p));
60
60
  }
61
- export async function analyzeIntentStructured(input, intents, threshold) {
62
- const extractor = await ModelSingleton.getExtractor();
61
+ export async function analyzeIntentStructured(input, intents, threshold, model) {
62
+ const extractor = await ModelSingleton.getExtractor(model);
63
63
  let bestIntent = '';
64
64
  let bestScore = 0;
65
65
  for (const [key, desc] of Object.entries(intents)) {
@@ -1,6 +1,11 @@
1
+ import type { GuardDecisionStore } from '../core/decision-storage.js';
2
+ import { type GuardDecision, type ToolGuardConfig } from '../core/decision.js';
3
+ import { type PiiLabelMappings } from '../guard.config.js';
1
4
  import { z } from 'genkit';
2
5
  import { type PiiVaultStorage } from '../pii/storage.js';
3
6
  export type GuardConfig = {
7
+ policyVersion?: string;
8
+ tools?: ToolGuardConfig;
4
9
  intent?: {
5
10
  mode?: string;
6
11
  allowedIntent?: string;
@@ -13,6 +18,12 @@ export type GuardConfig = {
13
18
  reversible?: boolean;
14
19
  model?: string;
15
20
  mode?: 'ner' | 'classifier';
21
+ fallback?: {
22
+ model: string;
23
+ mode?: 'ner' | 'classifier';
24
+ labelMappings?: PiiLabelMappings;
25
+ };
26
+ labelMappings?: PiiLabelMappings;
16
27
  vault?: {
17
28
  storage?: PiiVaultStorage;
18
29
  scopeId?: string | ((req: any, ctx: any) => string | undefined);
@@ -22,14 +33,33 @@ export type GuardConfig = {
22
33
  enabled?: boolean;
23
34
  level?: LogSeverity;
24
35
  serviceName?: string;
36
+ /** Awaited audit callback, independent of console logging level/enabled. Failure stops execution. */
37
+ onDecision?: (decision: GuardDecision) => void | Promise<void>;
38
+ /** Durable audit delivery. Failure stops execution; called before onDecision. */
39
+ store?: GuardDecisionStore;
25
40
  };
26
41
  models?: {
27
42
  extractor?: string;
43
+ extractorFallback?: string;
28
44
  };
29
45
  [key: string]: any;
30
46
  };
31
47
  type LogSeverity = 'debug' | 'info' | 'warn' | 'error';
32
48
  export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodObject<{
49
+ policyVersion: z.ZodOptional<z.ZodString>;
50
+ tools: z.ZodOptional<z.ZodObject<{
51
+ defaultAction: z.ZodOptional<z.ZodEnum<["allow", "block", "redact", "approval-required"]>>;
52
+ rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<["allow", "block", "redact", "approval-required"]>>>;
53
+ approve: z.ZodOptional<z.ZodAny>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ defaultAction?: "allow" | "block" | "redact" | "approval-required" | undefined;
56
+ rules?: Record<string, "allow" | "block" | "redact" | "approval-required"> | undefined;
57
+ approve?: any;
58
+ }, {
59
+ defaultAction?: "allow" | "block" | "redact" | "approval-required" | undefined;
60
+ rules?: Record<string, "allow" | "block" | "redact" | "approval-required"> | undefined;
61
+ approve?: any;
62
+ }>>;
33
63
  intent: z.ZodOptional<z.ZodObject<{
34
64
  mode: z.ZodOptional<z.ZodString>;
35
65
  allowedIntent: z.ZodOptional<z.ZodString>;
@@ -62,6 +92,20 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
62
92
  reversible: z.ZodOptional<z.ZodBoolean>;
63
93
  model: z.ZodOptional<z.ZodString>;
64
94
  mode: z.ZodOptional<z.ZodEnum<["ner", "classifier"]>>;
95
+ fallback: z.ZodOptional<z.ZodObject<{
96
+ model: z.ZodString;
97
+ mode: z.ZodOptional<z.ZodEnum<["ner", "classifier"]>>;
98
+ labelMappings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ model: string;
101
+ mode?: "ner" | "classifier" | undefined;
102
+ labelMappings?: Record<string, string | null> | undefined;
103
+ }, {
104
+ model: string;
105
+ mode?: "ner" | "classifier" | undefined;
106
+ labelMappings?: Record<string, string | null> | undefined;
107
+ }>>;
108
+ labelMappings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
65
109
  vault: z.ZodOptional<z.ZodObject<{
66
110
  storage: z.ZodOptional<z.ZodAny>;
67
111
  scopeId: z.ZodOptional<z.ZodAny>;
@@ -73,17 +117,29 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
73
117
  scopeId?: any;
74
118
  }>>;
75
119
  }, "strip", z.ZodTypeAny, {
120
+ model?: string | undefined;
121
+ fallback?: {
122
+ model: string;
123
+ mode?: "ner" | "classifier" | undefined;
124
+ labelMappings?: Record<string, string | null> | undefined;
125
+ } | undefined;
76
126
  mode?: "ner" | "classifier" | undefined;
77
127
  reversible?: boolean | undefined;
78
- model?: string | undefined;
128
+ labelMappings?: Record<string, string | null> | undefined;
79
129
  vault?: {
80
130
  storage?: any;
81
131
  scopeId?: any;
82
132
  } | undefined;
83
133
  }, {
134
+ model?: string | undefined;
135
+ fallback?: {
136
+ model: string;
137
+ mode?: "ner" | "classifier" | undefined;
138
+ labelMappings?: Record<string, string | null> | undefined;
139
+ } | undefined;
84
140
  mode?: "ner" | "classifier" | undefined;
85
141
  reversible?: boolean | undefined;
86
- model?: string | undefined;
142
+ labelMappings?: Record<string, string | null> | undefined;
87
143
  vault?: {
88
144
  storage?: any;
89
145
  scopeId?: any;
@@ -93,23 +149,46 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
93
149
  enabled: z.ZodOptional<z.ZodBoolean>;
94
150
  level: z.ZodOptional<z.ZodEnum<["debug", "info", "warn", "error"]>>;
95
151
  serviceName: z.ZodOptional<z.ZodString>;
152
+ onDecision: z.ZodOptional<z.ZodAny>;
153
+ store: z.ZodOptional<z.ZodAny>;
96
154
  }, "strip", z.ZodTypeAny, {
97
155
  enabled?: boolean | undefined;
98
156
  level?: "debug" | "info" | "warn" | "error" | undefined;
99
157
  serviceName?: string | undefined;
158
+ onDecision?: any;
159
+ store?: any;
100
160
  }, {
101
161
  enabled?: boolean | undefined;
102
162
  level?: "debug" | "info" | "warn" | "error" | undefined;
103
163
  serviceName?: string | undefined;
164
+ onDecision?: any;
165
+ store?: any;
104
166
  }>>;
105
167
  models: z.ZodOptional<z.ZodObject<{
106
168
  extractor: z.ZodOptional<z.ZodString>;
169
+ extractorFallback: z.ZodOptional<z.ZodString>;
107
170
  }, "strip", z.ZodTypeAny, {
108
171
  extractor?: string | undefined;
172
+ extractorFallback?: string | undefined;
109
173
  }, {
110
174
  extractor?: string | undefined;
175
+ extractorFallback?: string | undefined;
111
176
  }>>;
112
177
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
178
+ policyVersion: z.ZodOptional<z.ZodString>;
179
+ tools: z.ZodOptional<z.ZodObject<{
180
+ defaultAction: z.ZodOptional<z.ZodEnum<["allow", "block", "redact", "approval-required"]>>;
181
+ rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<["allow", "block", "redact", "approval-required"]>>>;
182
+ approve: z.ZodOptional<z.ZodAny>;
183
+ }, "strip", z.ZodTypeAny, {
184
+ defaultAction?: "allow" | "block" | "redact" | "approval-required" | undefined;
185
+ rules?: Record<string, "allow" | "block" | "redact" | "approval-required"> | undefined;
186
+ approve?: any;
187
+ }, {
188
+ defaultAction?: "allow" | "block" | "redact" | "approval-required" | undefined;
189
+ rules?: Record<string, "allow" | "block" | "redact" | "approval-required"> | undefined;
190
+ approve?: any;
191
+ }>>;
113
192
  intent: z.ZodOptional<z.ZodObject<{
114
193
  mode: z.ZodOptional<z.ZodString>;
115
194
  allowedIntent: z.ZodOptional<z.ZodString>;
@@ -142,6 +221,20 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
142
221
  reversible: z.ZodOptional<z.ZodBoolean>;
143
222
  model: z.ZodOptional<z.ZodString>;
144
223
  mode: z.ZodOptional<z.ZodEnum<["ner", "classifier"]>>;
224
+ fallback: z.ZodOptional<z.ZodObject<{
225
+ model: z.ZodString;
226
+ mode: z.ZodOptional<z.ZodEnum<["ner", "classifier"]>>;
227
+ labelMappings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
228
+ }, "strip", z.ZodTypeAny, {
229
+ model: string;
230
+ mode?: "ner" | "classifier" | undefined;
231
+ labelMappings?: Record<string, string | null> | undefined;
232
+ }, {
233
+ model: string;
234
+ mode?: "ner" | "classifier" | undefined;
235
+ labelMappings?: Record<string, string | null> | undefined;
236
+ }>>;
237
+ labelMappings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
145
238
  vault: z.ZodOptional<z.ZodObject<{
146
239
  storage: z.ZodOptional<z.ZodAny>;
147
240
  scopeId: z.ZodOptional<z.ZodAny>;
@@ -153,17 +246,29 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
153
246
  scopeId?: any;
154
247
  }>>;
155
248
  }, "strip", z.ZodTypeAny, {
249
+ model?: string | undefined;
250
+ fallback?: {
251
+ model: string;
252
+ mode?: "ner" | "classifier" | undefined;
253
+ labelMappings?: Record<string, string | null> | undefined;
254
+ } | undefined;
156
255
  mode?: "ner" | "classifier" | undefined;
157
256
  reversible?: boolean | undefined;
158
- model?: string | undefined;
257
+ labelMappings?: Record<string, string | null> | undefined;
159
258
  vault?: {
160
259
  storage?: any;
161
260
  scopeId?: any;
162
261
  } | undefined;
163
262
  }, {
263
+ model?: string | undefined;
264
+ fallback?: {
265
+ model: string;
266
+ mode?: "ner" | "classifier" | undefined;
267
+ labelMappings?: Record<string, string | null> | undefined;
268
+ } | undefined;
164
269
  mode?: "ner" | "classifier" | undefined;
165
270
  reversible?: boolean | undefined;
166
- model?: string | undefined;
271
+ labelMappings?: Record<string, string | null> | undefined;
167
272
  vault?: {
168
273
  storage?: any;
169
274
  scopeId?: any;
@@ -173,23 +278,46 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
173
278
  enabled: z.ZodOptional<z.ZodBoolean>;
174
279
  level: z.ZodOptional<z.ZodEnum<["debug", "info", "warn", "error"]>>;
175
280
  serviceName: z.ZodOptional<z.ZodString>;
281
+ onDecision: z.ZodOptional<z.ZodAny>;
282
+ store: z.ZodOptional<z.ZodAny>;
176
283
  }, "strip", z.ZodTypeAny, {
177
284
  enabled?: boolean | undefined;
178
285
  level?: "debug" | "info" | "warn" | "error" | undefined;
179
286
  serviceName?: string | undefined;
287
+ onDecision?: any;
288
+ store?: any;
180
289
  }, {
181
290
  enabled?: boolean | undefined;
182
291
  level?: "debug" | "info" | "warn" | "error" | undefined;
183
292
  serviceName?: string | undefined;
293
+ onDecision?: any;
294
+ store?: any;
184
295
  }>>;
185
296
  models: z.ZodOptional<z.ZodObject<{
186
297
  extractor: z.ZodOptional<z.ZodString>;
298
+ extractorFallback: z.ZodOptional<z.ZodString>;
187
299
  }, "strip", z.ZodTypeAny, {
188
300
  extractor?: string | undefined;
301
+ extractorFallback?: string | undefined;
189
302
  }, {
190
303
  extractor?: string | undefined;
304
+ extractorFallback?: string | undefined;
191
305
  }>>;
192
306
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
307
+ policyVersion: z.ZodOptional<z.ZodString>;
308
+ tools: z.ZodOptional<z.ZodObject<{
309
+ defaultAction: z.ZodOptional<z.ZodEnum<["allow", "block", "redact", "approval-required"]>>;
310
+ rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<["allow", "block", "redact", "approval-required"]>>>;
311
+ approve: z.ZodOptional<z.ZodAny>;
312
+ }, "strip", z.ZodTypeAny, {
313
+ defaultAction?: "allow" | "block" | "redact" | "approval-required" | undefined;
314
+ rules?: Record<string, "allow" | "block" | "redact" | "approval-required"> | undefined;
315
+ approve?: any;
316
+ }, {
317
+ defaultAction?: "allow" | "block" | "redact" | "approval-required" | undefined;
318
+ rules?: Record<string, "allow" | "block" | "redact" | "approval-required"> | undefined;
319
+ approve?: any;
320
+ }>>;
193
321
  intent: z.ZodOptional<z.ZodObject<{
194
322
  mode: z.ZodOptional<z.ZodString>;
195
323
  allowedIntent: z.ZodOptional<z.ZodString>;
@@ -222,6 +350,20 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
222
350
  reversible: z.ZodOptional<z.ZodBoolean>;
223
351
  model: z.ZodOptional<z.ZodString>;
224
352
  mode: z.ZodOptional<z.ZodEnum<["ner", "classifier"]>>;
353
+ fallback: z.ZodOptional<z.ZodObject<{
354
+ model: z.ZodString;
355
+ mode: z.ZodOptional<z.ZodEnum<["ner", "classifier"]>>;
356
+ labelMappings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
357
+ }, "strip", z.ZodTypeAny, {
358
+ model: string;
359
+ mode?: "ner" | "classifier" | undefined;
360
+ labelMappings?: Record<string, string | null> | undefined;
361
+ }, {
362
+ model: string;
363
+ mode?: "ner" | "classifier" | undefined;
364
+ labelMappings?: Record<string, string | null> | undefined;
365
+ }>>;
366
+ labelMappings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
225
367
  vault: z.ZodOptional<z.ZodObject<{
226
368
  storage: z.ZodOptional<z.ZodAny>;
227
369
  scopeId: z.ZodOptional<z.ZodAny>;
@@ -233,17 +375,29 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
233
375
  scopeId?: any;
234
376
  }>>;
235
377
  }, "strip", z.ZodTypeAny, {
378
+ model?: string | undefined;
379
+ fallback?: {
380
+ model: string;
381
+ mode?: "ner" | "classifier" | undefined;
382
+ labelMappings?: Record<string, string | null> | undefined;
383
+ } | undefined;
236
384
  mode?: "ner" | "classifier" | undefined;
237
385
  reversible?: boolean | undefined;
238
- model?: string | undefined;
386
+ labelMappings?: Record<string, string | null> | undefined;
239
387
  vault?: {
240
388
  storage?: any;
241
389
  scopeId?: any;
242
390
  } | undefined;
243
391
  }, {
392
+ model?: string | undefined;
393
+ fallback?: {
394
+ model: string;
395
+ mode?: "ner" | "classifier" | undefined;
396
+ labelMappings?: Record<string, string | null> | undefined;
397
+ } | undefined;
244
398
  mode?: "ner" | "classifier" | undefined;
245
399
  reversible?: boolean | undefined;
246
- model?: string | undefined;
400
+ labelMappings?: Record<string, string | null> | undefined;
247
401
  vault?: {
248
402
  storage?: any;
249
403
  scopeId?: any;
@@ -253,24 +407,46 @@ export declare const guardMiddleware: import("genkit").GenerateMiddleware<z.ZodO
253
407
  enabled: z.ZodOptional<z.ZodBoolean>;
254
408
  level: z.ZodOptional<z.ZodEnum<["debug", "info", "warn", "error"]>>;
255
409
  serviceName: z.ZodOptional<z.ZodString>;
410
+ onDecision: z.ZodOptional<z.ZodAny>;
411
+ store: z.ZodOptional<z.ZodAny>;
256
412
  }, "strip", z.ZodTypeAny, {
257
413
  enabled?: boolean | undefined;
258
414
  level?: "debug" | "info" | "warn" | "error" | undefined;
259
415
  serviceName?: string | undefined;
416
+ onDecision?: any;
417
+ store?: any;
260
418
  }, {
261
419
  enabled?: boolean | undefined;
262
420
  level?: "debug" | "info" | "warn" | "error" | undefined;
263
421
  serviceName?: string | undefined;
422
+ onDecision?: any;
423
+ store?: any;
264
424
  }>>;
265
425
  models: z.ZodOptional<z.ZodObject<{
266
426
  extractor: z.ZodOptional<z.ZodString>;
427
+ extractorFallback: z.ZodOptional<z.ZodString>;
267
428
  }, "strip", z.ZodTypeAny, {
268
429
  extractor?: string | undefined;
430
+ extractorFallback?: string | undefined;
269
431
  }, {
270
432
  extractor?: string | undefined;
433
+ extractorFallback?: string | undefined;
271
434
  }>>;
272
435
  }, z.ZodTypeAny, "passthrough">>, void>;
273
436
  export declare const guardPlugin: (pluginOptions: void) => import("@genkit-ai/ai").GenkitPluginV2;
274
- export declare function guard(config?: GuardConfig): (req: any, ctxOrNext: any, maybeNext?: any) => Promise<any>;
437
+ type GuardHooks = ReturnType<typeof createGuardHooks>;
438
+ type NativeGuard = ReturnType<typeof guardMiddleware> & GuardHooks;
439
+ type LegacyGuard = ((req: any, ctxOrNext: any, maybeNext?: any) => Promise<any>) & GuardHooks;
440
+ export declare function guard(config: GuardConfig & {
441
+ tools: ToolGuardConfig;
442
+ }): NativeGuard;
443
+ export declare function guard(config?: GuardConfig & {
444
+ tools?: undefined;
445
+ }): LegacyGuard;
446
+ export declare function guard(config: GuardConfig): NativeGuard | LegacyGuard;
275
447
  export declare const guardAction: typeof guard;
448
+ declare function createGuardHooks(config?: GuardConfig): {
449
+ model: (req: any, ctx: any, next: any) => Promise<any>;
450
+ tool: (req: any, ctx: any, next: any) => Promise<any>;
451
+ };
276
452
  export {};