indigiarmor 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 +24 -0
- package/README.md +257 -0
- package/dist/client.d.ts +117 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +359 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/guard.d.ts +17 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +39 -0
- package/dist/guard.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +34 -0
- package/dist/middleware.js.map +1 -0
- package/dist/next-handler.d.ts +4 -0
- package/dist/next-handler.d.ts.map +1 -0
- package/dist/next-handler.js +39 -0
- package/dist/next-handler.js.map +1 -0
- package/dist/protect.d.ts +9 -0
- package/dist/protect.d.ts.map +1 -0
- package/dist/protect.js +24 -0
- package/dist/protect.js.map +1 -0
- package/dist/types.d.ts +356 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/wrap-anthropic.d.ts +5 -0
- package/dist/wrap-anthropic.d.ts.map +1 -0
- package/dist/wrap-anthropic.js +107 -0
- package/dist/wrap-anthropic.js.map +1 -0
- package/dist/wrap-gemini.d.ts +5 -0
- package/dist/wrap-gemini.d.ts.map +1 -0
- package/dist/wrap-gemini.js +122 -0
- package/dist/wrap-gemini.js.map +1 -0
- package/dist/wrap-openai.d.ts +5 -0
- package/dist/wrap-openai.d.ts.map +1 -0
- package/dist/wrap-openai.js +106 -0
- package/dist/wrap-openai.js.map +1 -0
- package/package.json +54 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { IndigiArmorError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, } from './errors.js';
|
|
2
|
+
import { createGuard } from './guard.js';
|
|
3
|
+
import { createProtect } from './protect.js';
|
|
4
|
+
import { createMiddleware } from './middleware.js';
|
|
5
|
+
import { createNextHandler } from './next-handler.js';
|
|
6
|
+
import { createWrapOpenAI } from './wrap-openai.js';
|
|
7
|
+
import { createWrapAnthropic } from './wrap-anthropic.js';
|
|
8
|
+
import { createWrapGemini } from './wrap-gemini.js';
|
|
9
|
+
const DEFAULT_BASE_URL = 'https://indigiarmor.com';
|
|
10
|
+
const DEFAULT_TIMEOUT = 30_000;
|
|
11
|
+
export class IndigiArmor {
|
|
12
|
+
apiKey;
|
|
13
|
+
baseUrl;
|
|
14
|
+
fetchFn;
|
|
15
|
+
timeout;
|
|
16
|
+
callbacks;
|
|
17
|
+
constructor(apiKey, options = {}) {
|
|
18
|
+
if (!apiKey || !apiKey.startsWith('ia_sk_')) {
|
|
19
|
+
throw new Error('Invalid API key. Keys must start with "ia_sk_".');
|
|
20
|
+
}
|
|
21
|
+
this.apiKey = apiKey;
|
|
22
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
|
|
23
|
+
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
24
|
+
this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
25
|
+
this.callbacks = options.callbacks ?? {};
|
|
26
|
+
}
|
|
27
|
+
// ── Scanning ─────────────────────────────────
|
|
28
|
+
/** Scan a prompt for risk signals before sending to an LLM. */
|
|
29
|
+
async scan(prompt) {
|
|
30
|
+
const result = await this.post('/v1/scan', { prompt });
|
|
31
|
+
await this.invokeCallback(result);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
async invokeCallback(result) {
|
|
35
|
+
try {
|
|
36
|
+
const cb = result.tier === 'red' ? this.callbacks.onBlock :
|
|
37
|
+
result.tier === 'yellow' ? this.callbacks.onFlag :
|
|
38
|
+
this.callbacks.onAllow;
|
|
39
|
+
if (cb)
|
|
40
|
+
await cb(result);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Callback errors are swallowed — never break scan flow
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Scan document content (extracted text from PDF, DOCX, etc.) for risk signals. */
|
|
47
|
+
async scanDocument(content, documentMetadata) {
|
|
48
|
+
const result = await this.post('/v1/scan/document', {
|
|
49
|
+
content,
|
|
50
|
+
...(documentMetadata?.filename && { filename: documentMetadata.filename }),
|
|
51
|
+
...(documentMetadata?.mime_type && { mime_type: documentMetadata.mime_type }),
|
|
52
|
+
});
|
|
53
|
+
await this.invokeCallback(result);
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
/** Scan an LLM response for PII leaks and sensitive data. */
|
|
57
|
+
async scanResponse(response) {
|
|
58
|
+
return this.post('/v1/scan/response', { response });
|
|
59
|
+
}
|
|
60
|
+
/** Confirm a yellow-tier token (human-in-the-loop approval). */
|
|
61
|
+
async confirm(tokenId) {
|
|
62
|
+
return this.post(`/v1/confirm/${encodeURIComponent(tokenId)}`);
|
|
63
|
+
}
|
|
64
|
+
// ── Policies ─────────────────────────────────
|
|
65
|
+
/** List all policies for your organization. */
|
|
66
|
+
async listPolicies() {
|
|
67
|
+
const res = await this.get('/v1/policies');
|
|
68
|
+
return res.policies;
|
|
69
|
+
}
|
|
70
|
+
/** Create a new detection policy. */
|
|
71
|
+
async createPolicy(data) {
|
|
72
|
+
const res = await this.post('/v1/policies', data);
|
|
73
|
+
return res.policy;
|
|
74
|
+
}
|
|
75
|
+
/** Update an existing policy. */
|
|
76
|
+
async updatePolicy(id, data) {
|
|
77
|
+
const res = await this.put(`/v1/policies/${encodeURIComponent(id)}`, data);
|
|
78
|
+
return res.policy;
|
|
79
|
+
}
|
|
80
|
+
/** Delete a policy. */
|
|
81
|
+
async deletePolicy(id) {
|
|
82
|
+
await this.del(`/v1/policies/${encodeURIComponent(id)}`);
|
|
83
|
+
}
|
|
84
|
+
/** List available compliance policy templates (Education+). */
|
|
85
|
+
async listPolicyTemplates() {
|
|
86
|
+
const res = await this.get('/v1/policies/templates');
|
|
87
|
+
return res.templates;
|
|
88
|
+
}
|
|
89
|
+
/** Create a policy from a compliance template (Education+). */
|
|
90
|
+
async createPolicyFromTemplate(data) {
|
|
91
|
+
const res = await this.post('/v1/policies/from-template', data);
|
|
92
|
+
return res.policy;
|
|
93
|
+
}
|
|
94
|
+
// ── API Keys ─────────────────────────────────
|
|
95
|
+
/** List all API keys (hashes are never returned). */
|
|
96
|
+
async listKeys() {
|
|
97
|
+
const res = await this.get('/v1/keys');
|
|
98
|
+
return res.keys;
|
|
99
|
+
}
|
|
100
|
+
/** Create a new API key. The raw key is only returned once. */
|
|
101
|
+
async createKey(data) {
|
|
102
|
+
return this.post('/v1/keys', data);
|
|
103
|
+
}
|
|
104
|
+
/** Revoke an API key (soft-delete). */
|
|
105
|
+
async revokeKey(id) {
|
|
106
|
+
await this.del(`/v1/keys/${encodeURIComponent(id)}`);
|
|
107
|
+
}
|
|
108
|
+
// ── Usage ────────────────────────────────────
|
|
109
|
+
/** Get scan usage statistics, optionally filtered by date range. */
|
|
110
|
+
async getUsage(query) {
|
|
111
|
+
const params = new URLSearchParams();
|
|
112
|
+
if (query?.from)
|
|
113
|
+
params.set('from', query.from);
|
|
114
|
+
if (query?.to)
|
|
115
|
+
params.set('to', query.to);
|
|
116
|
+
const qs = params.toString();
|
|
117
|
+
return this.get(`/v1/usage${qs ? `?${qs}` : ''}`);
|
|
118
|
+
}
|
|
119
|
+
// ── Audit Logs ───────────────────────────────
|
|
120
|
+
/** Query paginated audit logs with optional filters. */
|
|
121
|
+
async listAuditLogs(query) {
|
|
122
|
+
const params = new URLSearchParams();
|
|
123
|
+
if (query?.limit !== undefined)
|
|
124
|
+
params.set('limit', String(query.limit));
|
|
125
|
+
if (query?.offset !== undefined)
|
|
126
|
+
params.set('offset', String(query.offset));
|
|
127
|
+
if (query?.tier)
|
|
128
|
+
params.set('tier', query.tier);
|
|
129
|
+
if (query?.from)
|
|
130
|
+
params.set('from', query.from);
|
|
131
|
+
if (query?.to)
|
|
132
|
+
params.set('to', query.to);
|
|
133
|
+
const qs = params.toString();
|
|
134
|
+
return this.get(`/v1/audit${qs ? `?${qs}` : ''}`);
|
|
135
|
+
}
|
|
136
|
+
/** Get a single audit log entry by ID. */
|
|
137
|
+
async getAuditLog(id) {
|
|
138
|
+
const res = await this.get(`/v1/audit/${encodeURIComponent(id)}`);
|
|
139
|
+
return res.log;
|
|
140
|
+
}
|
|
141
|
+
// ── Allowlist ────────────────────────────────
|
|
142
|
+
/** List all allowlisted terms for your organization. */
|
|
143
|
+
async listAllowlist() {
|
|
144
|
+
const res = await this.get('/v1/allowlist');
|
|
145
|
+
return res.allowlist;
|
|
146
|
+
}
|
|
147
|
+
/** Add a term to the allowlist. */
|
|
148
|
+
async addAllowlistEntry(data) {
|
|
149
|
+
const res = await this.post('/v1/allowlist', data);
|
|
150
|
+
return res.entry;
|
|
151
|
+
}
|
|
152
|
+
/** Remove an allowlist entry. */
|
|
153
|
+
async removeAllowlistEntry(id) {
|
|
154
|
+
await this.del(`/v1/allowlist/${encodeURIComponent(id)}`);
|
|
155
|
+
}
|
|
156
|
+
// ── Webhooks (Professional+) ───────────────
|
|
157
|
+
/** List all webhooks. */
|
|
158
|
+
async listWebhooks() {
|
|
159
|
+
const res = await this.get('/v1/webhooks');
|
|
160
|
+
return res.webhooks;
|
|
161
|
+
}
|
|
162
|
+
/** Create a webhook endpoint. */
|
|
163
|
+
async createWebhook(data) {
|
|
164
|
+
const res = await this.post('/v1/webhooks', data);
|
|
165
|
+
return res.webhook;
|
|
166
|
+
}
|
|
167
|
+
/** Update a webhook. */
|
|
168
|
+
async updateWebhook(id, data) {
|
|
169
|
+
const res = await this.put(`/v1/webhooks/${encodeURIComponent(id)}`, data);
|
|
170
|
+
return res.webhook;
|
|
171
|
+
}
|
|
172
|
+
/** Delete a webhook. */
|
|
173
|
+
async deleteWebhook(id) {
|
|
174
|
+
await this.del(`/v1/webhooks/${encodeURIComponent(id)}`);
|
|
175
|
+
}
|
|
176
|
+
/** Send a test event to a webhook. */
|
|
177
|
+
async testWebhook(id) {
|
|
178
|
+
return this.post(`/v1/webhooks/${encodeURIComponent(id)}/test`);
|
|
179
|
+
}
|
|
180
|
+
// ── Teams (Professional+) ─────────────────
|
|
181
|
+
/** List all teams. */
|
|
182
|
+
async listTeams() {
|
|
183
|
+
const res = await this.get('/v1/teams');
|
|
184
|
+
return res.teams;
|
|
185
|
+
}
|
|
186
|
+
/** Create a team. */
|
|
187
|
+
async createTeam(data) {
|
|
188
|
+
const res = await this.post('/v1/teams', data);
|
|
189
|
+
return res.team;
|
|
190
|
+
}
|
|
191
|
+
/** Update a team. */
|
|
192
|
+
async updateTeam(id, data) {
|
|
193
|
+
const res = await this.put(`/v1/teams/${encodeURIComponent(id)}`, data);
|
|
194
|
+
return res.team;
|
|
195
|
+
}
|
|
196
|
+
/** Delete a team. */
|
|
197
|
+
async deleteTeam(id) {
|
|
198
|
+
await this.del(`/v1/teams/${encodeURIComponent(id)}`);
|
|
199
|
+
}
|
|
200
|
+
/** List team members. */
|
|
201
|
+
async listTeamMembers(teamId) {
|
|
202
|
+
const res = await this.get(`/v1/teams/${encodeURIComponent(teamId)}/members`);
|
|
203
|
+
return res.members;
|
|
204
|
+
}
|
|
205
|
+
/** Add a member to a team. */
|
|
206
|
+
async addTeamMember(teamId, userId) {
|
|
207
|
+
await this.post(`/v1/teams/${encodeURIComponent(teamId)}/members`, { user_id: userId });
|
|
208
|
+
}
|
|
209
|
+
// ── Custom Entities (Enterprise) ──────────
|
|
210
|
+
/** List custom entity types. */
|
|
211
|
+
async listCustomEntities() {
|
|
212
|
+
const res = await this.get('/v1/custom-entities');
|
|
213
|
+
return res.entities;
|
|
214
|
+
}
|
|
215
|
+
/** Create a custom entity type. */
|
|
216
|
+
async createCustomEntity(data) {
|
|
217
|
+
const res = await this.post('/v1/custom-entities', data);
|
|
218
|
+
return res.entity;
|
|
219
|
+
}
|
|
220
|
+
/** Update a custom entity type. */
|
|
221
|
+
async updateCustomEntity(id, data) {
|
|
222
|
+
const res = await this.put(`/v1/custom-entities/${encodeURIComponent(id)}`, data);
|
|
223
|
+
return res.entity;
|
|
224
|
+
}
|
|
225
|
+
/** Delete a custom entity type. */
|
|
226
|
+
async deleteCustomEntity(id) {
|
|
227
|
+
await this.del(`/v1/custom-entities/${encodeURIComponent(id)}`);
|
|
228
|
+
}
|
|
229
|
+
// ── Reports (Education+) ──────────────────
|
|
230
|
+
/** Export audit logs as JSON. */
|
|
231
|
+
async exportAuditLogs(query) {
|
|
232
|
+
const params = new URLSearchParams({ from: query.from, to: query.to, format: query.format ?? 'json' });
|
|
233
|
+
if (query.domain)
|
|
234
|
+
params.set('domain', query.domain);
|
|
235
|
+
return this.get(`/v1/reports/audit-export?${params.toString()}`);
|
|
236
|
+
}
|
|
237
|
+
/** Generate a compliance summary report. */
|
|
238
|
+
async getComplianceReport(from, to) {
|
|
239
|
+
const params = new URLSearchParams({ from, to });
|
|
240
|
+
const res = await this.get(`/v1/reports/compliance?${params.toString()}`);
|
|
241
|
+
return res.report;
|
|
242
|
+
}
|
|
243
|
+
// ── Red Team (Enterprise) ─────────────────
|
|
244
|
+
/** Run a red team attack simulation against current policy. */
|
|
245
|
+
async runRedTeam() {
|
|
246
|
+
return this.post('/v1/redteam/run');
|
|
247
|
+
}
|
|
248
|
+
/** List available attack cases (without executing). */
|
|
249
|
+
async listAttackCases() {
|
|
250
|
+
const res = await this.get('/v1/redteam/attacks');
|
|
251
|
+
return res.attacks;
|
|
252
|
+
}
|
|
253
|
+
// ── Convenience Layers ─────────────────────────
|
|
254
|
+
/** Simple boolean gate — scan and decide in one call. */
|
|
255
|
+
async guard(prompt, options) {
|
|
256
|
+
return createGuard((p) => this.scan(p))(prompt, options);
|
|
257
|
+
}
|
|
258
|
+
/** Scan input, call function with safe prompt, optionally scan output. */
|
|
259
|
+
async protect(prompt, fn, options) {
|
|
260
|
+
return createProtect((p) => this.scan(p), (r) => this.scanResponse(r))(prompt, fn, options);
|
|
261
|
+
}
|
|
262
|
+
/** Express-compatible middleware that scans prompts from request bodies. */
|
|
263
|
+
middleware(options) {
|
|
264
|
+
return createMiddleware((p) => this.scan(p))(options);
|
|
265
|
+
}
|
|
266
|
+
/** Next.js App Router handler wrapper that scans prompts before processing. */
|
|
267
|
+
nextHandler(handler, options) {
|
|
268
|
+
return createNextHandler((p) => this.scan(p))(handler, options);
|
|
269
|
+
}
|
|
270
|
+
/** Proxy-wrap an OpenAI client to auto-scan all chat completions. */
|
|
271
|
+
wrapOpenAI(client, options) {
|
|
272
|
+
return createWrapOpenAI((p) => this.scan(p), (r) => this.scanResponse(r))(client, options);
|
|
273
|
+
}
|
|
274
|
+
/** Proxy-wrap an Anthropic client to auto-scan all messages. */
|
|
275
|
+
wrapAnthropic(client, options) {
|
|
276
|
+
return createWrapAnthropic((p) => this.scan(p), (r) => this.scanResponse(r))(client, options);
|
|
277
|
+
}
|
|
278
|
+
/** Proxy-wrap a Google GenAI client to auto-scan all generateContent calls. */
|
|
279
|
+
wrapGemini(client, options) {
|
|
280
|
+
return createWrapGemini((p) => this.scan(p), (r) => this.scanResponse(r))(client, options);
|
|
281
|
+
}
|
|
282
|
+
// ── HTTP helpers ─────────────────────────────
|
|
283
|
+
async get(path) {
|
|
284
|
+
return this.request('GET', path);
|
|
285
|
+
}
|
|
286
|
+
async post(path, body) {
|
|
287
|
+
return this.request('POST', path, body);
|
|
288
|
+
}
|
|
289
|
+
async put(path, body) {
|
|
290
|
+
return this.request('PUT', path, body);
|
|
291
|
+
}
|
|
292
|
+
async del(path) {
|
|
293
|
+
await this.request('DELETE', path);
|
|
294
|
+
}
|
|
295
|
+
async request(method, path, body) {
|
|
296
|
+
const url = `${this.baseUrl}${path}`;
|
|
297
|
+
const controller = new AbortController();
|
|
298
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
299
|
+
try {
|
|
300
|
+
const res = await this.fetchFn(url, {
|
|
301
|
+
method,
|
|
302
|
+
headers: {
|
|
303
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
304
|
+
'Content-Type': 'application/json',
|
|
305
|
+
Accept: 'application/json',
|
|
306
|
+
},
|
|
307
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
308
|
+
signal: controller.signal,
|
|
309
|
+
});
|
|
310
|
+
clearTimeout(timer);
|
|
311
|
+
if (!res.ok) {
|
|
312
|
+
await this.handleError(res);
|
|
313
|
+
}
|
|
314
|
+
// 204 No Content
|
|
315
|
+
if (res.status === 204) {
|
|
316
|
+
return undefined;
|
|
317
|
+
}
|
|
318
|
+
return (await res.json());
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
clearTimeout(timer);
|
|
322
|
+
if (err instanceof IndigiArmorError) {
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
326
|
+
throw new IndigiArmorError(`Request timed out after ${this.timeout}ms`, 'TIMEOUT', 0);
|
|
327
|
+
}
|
|
328
|
+
throw new IndigiArmorError(`Network error: ${err.message}`, 'NETWORK_ERROR', 0);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async handleError(res) {
|
|
332
|
+
const requestId = res.headers.get('x-request-id') ?? undefined;
|
|
333
|
+
let message = `API error: ${res.status}`;
|
|
334
|
+
try {
|
|
335
|
+
const body = (await res.json());
|
|
336
|
+
if (body.error?.message) {
|
|
337
|
+
message = body.error.message;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// Response body isn't JSON
|
|
342
|
+
}
|
|
343
|
+
switch (res.status) {
|
|
344
|
+
case 401:
|
|
345
|
+
throw new AuthenticationError(message, requestId);
|
|
346
|
+
case 429: {
|
|
347
|
+
const retryAfter = res.headers.get('retry-after');
|
|
348
|
+
throw new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : undefined, requestId);
|
|
349
|
+
}
|
|
350
|
+
case 400:
|
|
351
|
+
throw new ValidationError(message, requestId);
|
|
352
|
+
case 404:
|
|
353
|
+
throw new NotFoundError(message, requestId);
|
|
354
|
+
default:
|
|
355
|
+
throw new IndigiArmorError(message, 'API_ERROR', res.status, requestId);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AA6CA,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AACnD,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B,MAAM,OAAO,WAAW;IACL,MAAM,CAAS;IACf,OAAO,CAAS;IAChB,OAAO,CAA0B;IACjC,OAAO,CAAS;IAChB,SAAS,CAAuB;IAEjD,YAAY,MAAc,EAAE,UAA8B,EAAE;QAC1D,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,eAAe,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;IAC3C,CAAC;IAED,gDAAgD;IAEhD,+DAA+D;IAC/D,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAa,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACnE,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,MAAkB;QAC7C,IAAI,CAAC;YACH,MAAM,EAAE,GACN,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;gBAChD,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;oBAClD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YACzB,IAAI,EAAE;gBAAE,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;IACH,CAAC;IAED,oFAAoF;IACpF,KAAK,CAAC,YAAY,CAAC,OAAe,EAAE,gBAAmC;QACrE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAa,mBAAmB,EAAE;YAC9D,OAAO;YACP,GAAG,CAAC,gBAAgB,EAAE,QAAQ,IAAI,EAAE,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,CAAC;YAC1E,GAAG,CAAC,gBAAgB,EAAE,SAAS,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,SAAS,EAAE,CAAC;SAC9E,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,OAAO,IAAI,CAAC,IAAI,CAAqB,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,OAAO,CAAC,OAAe;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAgB,eAAe,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,gDAAgD;IAEhD,+CAA+C;IAC/C,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAyB,cAAc,CAAC,CAAC;QACnE,OAAO,GAAG,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,qCAAqC;IACrC,KAAK,CAAC,YAAY,CAAC,IAAyB;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAqB,cAAc,EAAE,IAAI,CAAC,CAAC;QACtE,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,iCAAiC;IACjC,KAAK,CAAC,YAAY,CAAC,EAAU,EAAE,IAAyB;QACtD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAqB,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC/F,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,uBAAuB;IACvB,KAAK,CAAC,YAAY,CAAC,EAAU;QAC3B,MAAM,IAAI,CAAC,GAAG,CAAC,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,mBAAmB;QACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAkC,wBAAwB,CAAC,CAAC;QACtF,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,wBAAwB,CAAC,IAA+B;QAC5D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAqB,4BAA4B,EAAE,IAAI,CAAC,CAAC;QACpF,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,gDAAgD;IAEhD,qDAAqD;IACrD,KAAK,CAAC,QAAQ;QACZ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAqB,UAAU,CAAC,CAAC;QAC3D,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,SAAS,CAAC,IAAsB;QACpC,OAAO,IAAI,CAAC,IAAI,CAAkB,UAAU,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,uCAAuC;IACvC,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,gDAAgD;IAEhD,oEAAoE;IACpE,KAAK,CAAC,QAAQ,CAAC,KAAkB;QAC/B,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,KAAK,EAAE,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,GAAG,CAAc,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,gDAAgD;IAEhD,wDAAwD;IACxD,KAAK,CAAC,aAAa,CAAC,KAAkB;QACpC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5E,IAAI,KAAK,EAAE,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,GAAG,CAAkB,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,WAAW,CAAC,EAAU;QAC1B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAoB,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACrF,OAAO,GAAG,CAAC,GAAG,CAAC;IACjB,CAAC;IAED,gDAAgD;IAEhD,wDAAwD;IACxD,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAkC,eAAe,CAAC,CAAC;QAC7E,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,mCAAmC;IACnC,KAAK,CAAC,iBAAiB,CAAC,IAA4B;QAClD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAA4B,eAAe,EAAE,IAAI,CAAC,CAAC;QAC9E,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,iCAAiC;IACjC,KAAK,CAAC,oBAAoB,CAAC,EAAU;QACnC,MAAM,IAAI,CAAC,GAAG,CAAC,iBAAiB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,8CAA8C;IAE9C,yBAAyB;IACzB,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,cAAc,CAAC,CAAC;QACpE,OAAO,GAAG,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,iCAAiC;IACjC,KAAK,CAAC,aAAa,CAAC,IAA0B;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAuB,cAAc,EAAE,IAAI,CAAC,CAAC;QACxE,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,wBAAwB;IACxB,KAAK,CAAC,aAAa,CAAC,EAAU,EAAE,IAA0B;QACxD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAuB,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACjG,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,wBAAwB;IACxB,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,IAAI,CAAC,GAAG,CAAC,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,WAAW,CAAC,EAAU;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,6CAA6C;IAE7C,sBAAsB;IACtB,KAAK,CAAC,SAAS;QACb,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAoB,WAAW,CAAC,CAAC;QAC3D,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,qBAAqB;IACrB,KAAK,CAAC,UAAU,CAAC,IAAuB;QACtC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAiB,WAAW,EAAE,IAAI,CAAC,CAAC;QAC/D,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,IAAsB;QACjD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAiB,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACxF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,yBAAyB;IACzB,KAAK,CAAC,eAAe,CAAC,MAAc;QAClC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAA4B,aAAa,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACzG,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,8BAA8B;IAC9B,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,MAAc;QAChD,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,kBAAkB,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,6CAA6C;IAE7C,gCAAgC;IAChC,KAAK,CAAC,kBAAkB;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAA+B,qBAAqB,CAAC,CAAC;QAChF,OAAO,GAAG,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,mCAAmC;IACnC,KAAK,CAAC,kBAAkB,CAAC,IAA+B;QACtD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAA2B,qBAAqB,EAAE,IAAI,CAAC,CAAC;QACnF,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,mCAAmC;IACnC,KAAK,CAAC,kBAAkB,CAAC,EAAU,EAAE,IAA+B;QAClE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAA2B,uBAAuB,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC5G,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,mCAAmC;IACnC,KAAK,CAAC,kBAAkB,CAAC,EAAU;QACjC,MAAM,IAAI,CAAC,GAAG,CAAC,uBAAuB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,6CAA6C;IAE7C,iCAAiC;IACjC,KAAK,CAAC,eAAe,CAAC,KAAuB;QAC3C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;QACvG,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,GAAG,CAAC,4BAA4B,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,4CAA4C;IAC5C,KAAK,CAAC,mBAAmB,CAAC,IAAY,EAAE,EAAU;QAChD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAA+B,0BAA0B,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACxG,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,6CAA6C;IAE7C,+DAA+D;IAC/D,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,IAAI,CAAsB,iBAAiB,CAAC,CAAC;IAC3D,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,eAAe;QACnB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAA4B,qBAAqB,CAAC,CAAC;QAC7E,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,kDAAkD;IAElD,yDAAyD;IACzD,KAAK,CAAC,KAAK,CAAC,MAAc,EAAE,OAAsB;QAChD,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,OAAO,CACX,MAAc,EACd,EAAsC,EACtC,OAAwB;QAExB,OAAO,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9F,CAAC;IAED,4EAA4E;IAC5E,UAAU,CAAC,OAA2B;QACpC,OAAO,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,+EAA+E;IAC/E,WAAW,CACT,OAAgF,EAChF,OAA4B;QAE5B,OAAO,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,qEAAqE;IACrE,UAAU,CAAmB,MAAS,EAAE,OAAwB;QAC9D,OAAO,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7F,CAAC;IAED,gEAAgE;IAChE,aAAa,CAAmB,MAAS,EAAE,OAAwB;QACjE,OAAO,mBAAmB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChG,CAAC;IAED,+EAA+E;IAC/E,UAAU,CAAmB,MAAS,EAAE,OAAwB;QAC9D,OAAO,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7F,CAAC;IAED,gDAAgD;IAExC,KAAK,CAAC,GAAG,CAAI,IAAY;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAI,KAAK,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,IAAI,CAAI,IAAY,EAAE,IAAc;QAChD,OAAO,IAAI,CAAC,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEO,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,IAAc;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAI,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,IAAY;QAC5B,MAAM,IAAI,CAAC,OAAO,CAAU,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,MAAc,EAAE,IAAY,EAAE,IAAc;QACnE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QAErC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAEjE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;gBAClC,MAAM;gBACN,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;oBAClC,MAAM,EAAE,kBAAkB;iBAC3B;gBACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC3D,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC9B,CAAC;YAED,iBAAiB;YACjB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,OAAO,SAAc,CAAC;YACxB,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;gBACpC,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC7D,MAAM,IAAI,gBAAgB,CACxB,2BAA2B,IAAI,CAAC,OAAO,IAAI,EAC3C,SAAS,EACT,CAAC,CACF,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,gBAAgB,CACxB,kBAAmB,GAAa,CAAC,OAAO,EAAE,EAC1C,eAAe,EACf,CAAC,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,GAAa;QACrC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;QAC/D,IAAI,OAAO,GAAG,cAAc,GAAG,CAAC,MAAM,EAAE,CAAC;QAEzC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAkB,CAAC;YACjD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;gBACxB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;QAED,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,GAAG;gBACN,MAAM,IAAI,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACpD,KAAK,GAAG,CAAC,CAAC,CAAC;gBACT,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAClD,MAAM,IAAI,cAAc,CACtB,OAAO,EACP,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EACjD,SAAS,CACV,CAAC;YACJ,CAAC;YACD,KAAK,GAAG;gBACN,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAChD,KAAK,GAAG;gBACN,MAAM,IAAI,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC9C;gBACE,MAAM,IAAI,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;CACF"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class IndigiArmorError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly requestId?: string;
|
|
5
|
+
constructor(message: string, code: string, status: number, requestId?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class AuthenticationError extends IndigiArmorError {
|
|
8
|
+
constructor(message: string, requestId?: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class RateLimitError extends IndigiArmorError {
|
|
11
|
+
readonly retryAfter?: number;
|
|
12
|
+
constructor(message: string, retryAfter?: number, requestId?: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class ValidationError extends IndigiArmorError {
|
|
15
|
+
constructor(message: string, requestId?: string);
|
|
16
|
+
}
|
|
17
|
+
export declare class NotFoundError extends IndigiArmorError {
|
|
18
|
+
constructor(message: string, requestId?: string);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,SAAS,CAAC,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAO9E;AAED,qBAAa,mBAAoB,SAAQ,gBAAgB;gBAC3C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD;AAED,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAKrE;AAED,qBAAa,eAAgB,SAAQ,gBAAgB;gBACvC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD;AAED,qBAAa,aAAc,SAAQ,gBAAgB;gBACrC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIhD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export class IndigiArmorError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
requestId;
|
|
5
|
+
constructor(message, code, status, requestId) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'IndigiArmorError';
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.requestId = requestId;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class AuthenticationError extends IndigiArmorError {
|
|
14
|
+
constructor(message, requestId) {
|
|
15
|
+
super(message, 'AUTHENTICATION_ERROR', 401, requestId);
|
|
16
|
+
this.name = 'AuthenticationError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class RateLimitError extends IndigiArmorError {
|
|
20
|
+
retryAfter;
|
|
21
|
+
constructor(message, retryAfter, requestId) {
|
|
22
|
+
super(message, 'RATE_LIMIT_EXCEEDED', 429, requestId);
|
|
23
|
+
this.name = 'RateLimitError';
|
|
24
|
+
this.retryAfter = retryAfter;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class ValidationError extends IndigiArmorError {
|
|
28
|
+
constructor(message, requestId) {
|
|
29
|
+
super(message, 'VALIDATION_ERROR', 400, requestId);
|
|
30
|
+
this.name = 'ValidationError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class NotFoundError extends IndigiArmorError {
|
|
34
|
+
constructor(message, requestId) {
|
|
35
|
+
super(message, 'NOT_FOUND', 404, requestId);
|
|
36
|
+
this.name = 'NotFoundError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzB,IAAI,CAAS;IACb,MAAM,CAAS;IACf,SAAS,CAAU;IAEnC,YAAY,OAAe,EAAE,IAAY,EAAE,MAAc,EAAE,SAAkB;QAC3E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,gBAAgB;IACvD,YAAY,OAAe,EAAE,SAAkB;QAC7C,KAAK,CAAC,OAAO,EAAE,sBAAsB,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAClC,UAAU,CAAU;IAEpC,YAAY,OAAe,EAAE,UAAmB,EAAE,SAAkB;QAClE,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,gBAAgB;IACnD,YAAY,OAAe,EAAE,SAAkB;QAC7C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,gBAAgB;IACjD,YAAY,OAAe,EAAE,SAAkB;QAC7C,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
|
package/dist/guard.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ScanResult, YellowStrategy, GuardOptions, GuardResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Determine if a scan result is safe given a yellow-tier strategy.
|
|
4
|
+
* Shared by guard, protect, middleware, next-handler, and LLM wrappers.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isSafe(result: ScanResult, yellowStrategy?: YellowStrategy): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the prompt to use after scanning.
|
|
9
|
+
* Returns sanitized version when available and appropriate, otherwise the original.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolvePrompt(original: string, result: ScanResult, yellowStrategy?: YellowStrategy): string;
|
|
12
|
+
/** Scan-and-decide interface used by `IndigiArmor.guard()`. */
|
|
13
|
+
export interface ScanFn {
|
|
14
|
+
(prompt: string): Promise<ScanResult>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createGuard(scanFn: ScanFn): (prompt: string, options?: GuardOptions) => Promise<GuardResult>;
|
|
17
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExF;;;GAGG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,cAAc,GAAE,cAA2B,GAAG,OAAO,CAK/F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,EAClB,cAAc,GAAE,cAA2B,GAC1C,MAAM,CAQR;AAED,+DAA+D;AAC/D,MAAM,WAAW,MAAM;IACrB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACvC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,IACZ,QAAQ,MAAM,EAAE,UAAS,YAAiB,KAAG,OAAO,CAAC,WAAW,CAAC,CAS9F"}
|
package/dist/guard.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determine if a scan result is safe given a yellow-tier strategy.
|
|
3
|
+
* Shared by guard, protect, middleware, next-handler, and LLM wrappers.
|
|
4
|
+
*/
|
|
5
|
+
export function isSafe(result, yellowStrategy = 'sanitize') {
|
|
6
|
+
if (result.tier === 'green')
|
|
7
|
+
return true;
|
|
8
|
+
if (result.tier === 'red')
|
|
9
|
+
return false;
|
|
10
|
+
// yellow
|
|
11
|
+
return yellowStrategy !== 'block';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the prompt to use after scanning.
|
|
15
|
+
* Returns sanitized version when available and appropriate, otherwise the original.
|
|
16
|
+
*/
|
|
17
|
+
export function resolvePrompt(original, result, yellowStrategy = 'sanitize') {
|
|
18
|
+
if (result.tier === 'green')
|
|
19
|
+
return original;
|
|
20
|
+
if (result.tier === 'red')
|
|
21
|
+
return original;
|
|
22
|
+
// yellow — only sanitize if strategy says so and a sanitized prompt exists
|
|
23
|
+
if (yellowStrategy === 'sanitize' && result.sanitized_prompt) {
|
|
24
|
+
return result.sanitized_prompt;
|
|
25
|
+
}
|
|
26
|
+
return original;
|
|
27
|
+
}
|
|
28
|
+
export function createGuard(scanFn) {
|
|
29
|
+
return async function guard(prompt, options = {}) {
|
|
30
|
+
const yellowStrategy = options.yellowStrategy ?? 'sanitize';
|
|
31
|
+
const result = await scanFn(prompt);
|
|
32
|
+
return {
|
|
33
|
+
safe: isSafe(result, yellowStrategy),
|
|
34
|
+
prompt: resolvePrompt(prompt, result, yellowStrategy),
|
|
35
|
+
result,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,MAAkB,EAAE,iBAAiC,UAAU;IACpF,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACxC,SAAS;IACT,OAAO,cAAc,KAAK,OAAO,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,MAAkB,EAClB,iBAAiC,UAAU;IAE3C,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC;IAC7C,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC3C,2EAA2E;IAC3E,IAAI,cAAc,KAAK,UAAU,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,gBAAgB,CAAC;IACjC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAOD,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,KAAK,UAAU,KAAK,CAAC,MAAc,EAAE,UAAwB,EAAE;QACpE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,UAAU,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;YACpC,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC;YACrD,MAAM;SACP,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { IndigiArmor } from './client.js';
|
|
2
|
+
export { IndigiArmorError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, } from './errors.js';
|
|
3
|
+
export type { IndigiArmorOptions, IndigiArmorCallbacks, ScanRequest, ScanResult, Signal, ScanResponseResult, ScanResponseRequest, ConfirmResult, DocumentMetadata, DocumentScanRequest, Policy, CreatePolicyRequest, UpdatePolicyRequest, PolicyTemplate, CreateFromTemplateRequest, DetectionDomain, ApiKey, CreateKeyRequest, CreateKeyResult, UsageResult, UsagePeriod, UsageQuery, AuditLog, AuditQuery, AuditListResult, AllowlistEntry, CreateAllowlistRequest, Webhook, CreateWebhookRequest, UpdateWebhookRequest, Team, CreateTeamRequest, TeamMember, CustomEntity, CreateCustomEntityRequest, UpdateCustomEntityRequest, AuditExportQuery, ComplianceReport, AttackCase, SimulationResult, SimulationSummary, SimulationRunResult, YellowStrategy, GuardOptions, GuardResult, ProtectOptions, ProtectResult, MiddlewareOptions, NextHandlerOptions, WrapLLMOptions, } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,UAAU,EACV,MAAM,EACN,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,MAAM,EACN,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,yBAAyB,EACzB,eAAe,EACf,MAAM,EACN,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,WAAW,EACX,UAAU,EACV,QAAQ,EACR,UAAU,EACV,eAAe,EACf,cAAc,EACd,sBAAsB,EAEtB,OAAO,EACP,oBAAoB,EACpB,oBAAoB,EAEpB,IAAI,EACJ,iBAAiB,EACjB,UAAU,EAEV,YAAY,EACZ,yBAAyB,EACzB,yBAAyB,EAEzB,gBAAgB,EAChB,gBAAgB,EAEhB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EAEnB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ScanResult, MiddlewareOptions } from './types.js';
|
|
2
|
+
import { type ScanFn } from './guard.js';
|
|
3
|
+
export interface MiddlewareRequest {
|
|
4
|
+
body?: Record<string, unknown>;
|
|
5
|
+
scanResult?: ScanResult;
|
|
6
|
+
}
|
|
7
|
+
export interface MiddlewareResponse {
|
|
8
|
+
status(code: number): MiddlewareResponse;
|
|
9
|
+
json(body: unknown): void;
|
|
10
|
+
}
|
|
11
|
+
export type NextFunction = (err?: unknown) => void;
|
|
12
|
+
export declare function createMiddleware(scanFn: ScanFn): (options?: MiddlewareOptions) => (req: MiddlewareRequest, res: MiddlewareResponse, next: NextFunction) => Promise<void>;
|
|
13
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAyB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAGhE,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAAC;IACzC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEnD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,IAClB,UAAS,iBAAsB,MAI1C,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,mBA8BpF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { isSafe, resolvePrompt } from './guard.js';
|
|
2
|
+
export function createMiddleware(scanFn) {
|
|
3
|
+
return function middleware(options = {}) {
|
|
4
|
+
const promptField = options.promptField ?? 'prompt';
|
|
5
|
+
const yellowStrategy = options.yellowStrategy ?? 'sanitize';
|
|
6
|
+
return async (req, res, next) => {
|
|
7
|
+
const prompt = req.body?.[promptField];
|
|
8
|
+
// No prompt field found — pass through
|
|
9
|
+
if (typeof prompt !== 'string') {
|
|
10
|
+
next();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const result = await scanFn(prompt);
|
|
15
|
+
req.scanResult = result;
|
|
16
|
+
if (!isSafe(result, yellowStrategy)) {
|
|
17
|
+
res.status(400).json({
|
|
18
|
+
error: 'blocked',
|
|
19
|
+
explanation: result.explanation,
|
|
20
|
+
tier: result.tier,
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Replace prompt with sanitized version in request body
|
|
25
|
+
req.body[promptField] = resolvePrompt(prompt, result, yellowStrategy);
|
|
26
|
+
next();
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
next(err);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAehE,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,SAAS,UAAU,CAAC,UAA6B,EAAE;QACxD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,QAAQ,CAAC;QACpD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,UAAU,CAAC;QAE5D,OAAO,KAAK,EAAE,GAAsB,EAAE,GAAuB,EAAE,IAAkB,EAAE,EAAE;YACnF,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC;YAEvC,uCAAuC;YACvC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,IAAI,EAAE,CAAC;gBACP,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;gBACpC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC;gBAExB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC;oBACpC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACnB,KAAK,EAAE,SAAS;wBAChB,WAAW,EAAE,MAAM,CAAC,WAAW;wBAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;qBAClB,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAED,wDAAwD;gBACxD,GAAG,CAAC,IAAK,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;gBACvE,IAAI,EAAE,CAAC;YACT,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,GAAG,CAAC,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ScanResult, NextHandlerOptions } from './types.js';
|
|
2
|
+
import { type ScanFn } from './guard.js';
|
|
3
|
+
export declare function createNextHandler(scanFn: ScanFn): (handler: (req: Request, scanResult: ScanResult | undefined) => Promise<Response>, options?: NextHandlerOptions) => (req: Request) => Promise<Response>;
|
|
4
|
+
//# sourceMappingURL=next-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-handler.d.ts","sourceRoot":"","sources":["../src/next-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAyB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAEhE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,IAE5C,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,SAAS,KAAK,OAAO,CAAC,QAAQ,CAAC,EAChF,UAAS,kBAAuB,MAKlB,KAAK,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAuCjD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isSafe, resolvePrompt } from './guard.js';
|
|
2
|
+
export function createNextHandler(scanFn) {
|
|
3
|
+
return function nextHandler(handler, options = {}) {
|
|
4
|
+
const promptField = options.promptField ?? 'prompt';
|
|
5
|
+
const yellowStrategy = options.yellowStrategy ?? 'sanitize';
|
|
6
|
+
return async (req) => {
|
|
7
|
+
let body;
|
|
8
|
+
try {
|
|
9
|
+
body = await req.clone().json();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Non-JSON request — pass through without scanning
|
|
13
|
+
return handler(req, undefined);
|
|
14
|
+
}
|
|
15
|
+
const prompt = body[promptField];
|
|
16
|
+
if (typeof prompt !== 'string') {
|
|
17
|
+
// No prompt field — pass through
|
|
18
|
+
return handler(req, undefined);
|
|
19
|
+
}
|
|
20
|
+
const result = await scanFn(prompt);
|
|
21
|
+
if (!isSafe(result, yellowStrategy)) {
|
|
22
|
+
return new Response(JSON.stringify({
|
|
23
|
+
error: 'blocked',
|
|
24
|
+
explanation: result.explanation,
|
|
25
|
+
tier: result.tier,
|
|
26
|
+
}), { status: 400, headers: { 'Content-Type': 'application/json' } });
|
|
27
|
+
}
|
|
28
|
+
// Replace prompt with sanitized version and create a new Request
|
|
29
|
+
body[promptField] = resolvePrompt(prompt, result, yellowStrategy);
|
|
30
|
+
const newReq = new Request(req.url, {
|
|
31
|
+
method: req.method,
|
|
32
|
+
headers: req.headers,
|
|
33
|
+
body: JSON.stringify(body),
|
|
34
|
+
});
|
|
35
|
+
return handler(newReq, result);
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=next-handler.js.map
|