@solongate/policy-engine 0.2.1 → 0.2.2
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/dist/index.js +108 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -202,9 +202,50 @@ var COMMAND_HEURISTICS = [
|
|
|
202
202
|
// network commands
|
|
203
203
|
/^(rm|del|rmdir)\s+/i,
|
|
204
204
|
// destructive commands
|
|
205
|
-
/^(cat|type|more|less)\s+.*[/\\]/i
|
|
205
|
+
/^(cat|type|more|less)\s+.*[/\\]/i,
|
|
206
206
|
// file read commands with paths
|
|
207
|
+
/^(eval|source)\s+/i,
|
|
208
|
+
// eval/source wrappers
|
|
209
|
+
/^(printenv|env|set)\b/i,
|
|
210
|
+
// environment variable leak
|
|
211
|
+
/^(cat|head|tail|more|less|strings|xxd|od|hexdump|bat)\s+/i
|
|
212
|
+
// file read commands
|
|
207
213
|
];
|
|
214
|
+
var SUBSHELL_WRAPPERS = [
|
|
215
|
+
/^(?:sh|bash|zsh|fish|dash|ksh)\s+-c\s+['"](.+?)['"]\s*$/i,
|
|
216
|
+
/^(?:sh|bash|zsh|fish|dash|ksh)\s+-c\s+(.+)$/i,
|
|
217
|
+
/^eval\s+['"](.+?)['"]\s*$/i,
|
|
218
|
+
/^eval\s+(.+)$/i,
|
|
219
|
+
/^(?:sh|bash|zsh|fish|dash|ksh)\s+<<\s*['"]?(\w+)['"]?\n([\s\S]+?)\n\1$/i
|
|
220
|
+
];
|
|
221
|
+
function extractInnerCommands(command) {
|
|
222
|
+
const results = [command];
|
|
223
|
+
const trimmed = command.trim();
|
|
224
|
+
for (const pattern of SUBSHELL_WRAPPERS) {
|
|
225
|
+
const match = trimmed.match(pattern);
|
|
226
|
+
if (match) {
|
|
227
|
+
const inner = (match[2] ?? match[1] ?? "").trim();
|
|
228
|
+
if (inner) {
|
|
229
|
+
results.push(inner);
|
|
230
|
+
const nested = extractInnerCommands(inner);
|
|
231
|
+
for (const n of nested) {
|
|
232
|
+
if (n !== inner) results.push(n);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const chainParts = trimmed.split(/\s*(?:&&|;)\s*/);
|
|
239
|
+
if (chainParts.length > 1) {
|
|
240
|
+
for (const part of chainParts) {
|
|
241
|
+
const p = part.trim();
|
|
242
|
+
if (p && p !== trimmed && !p.includes("=")) {
|
|
243
|
+
results.push(p);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return [...new Set(results)];
|
|
248
|
+
}
|
|
208
249
|
function extractCommandArguments(args) {
|
|
209
250
|
const commands = [];
|
|
210
251
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -241,6 +282,16 @@ function extractCommandArguments(args) {
|
|
|
241
282
|
for (const [key, value] of Object.entries(args)) {
|
|
242
283
|
scanValue(key, value);
|
|
243
284
|
}
|
|
285
|
+
const expanded = [];
|
|
286
|
+
for (const cmd of commands) {
|
|
287
|
+
for (const inner of extractInnerCommands(cmd)) {
|
|
288
|
+
if (!seen.has(inner)) {
|
|
289
|
+
seen.add(inner);
|
|
290
|
+
expanded.push(inner);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
commands.push(...expanded);
|
|
244
295
|
return commands;
|
|
245
296
|
}
|
|
246
297
|
function matchCommandPattern(command, pattern) {
|
|
@@ -312,7 +363,9 @@ function extractFilenames(args) {
|
|
|
312
363
|
return;
|
|
313
364
|
}
|
|
314
365
|
if (trimmed.includes(" ")) {
|
|
315
|
-
for (const
|
|
366
|
+
for (const rawToken of trimmed.split(/\s+/)) {
|
|
367
|
+
const token = rawToken.replace(/^['"`]+|['"`]+$/g, "");
|
|
368
|
+
if (!token) continue;
|
|
316
369
|
if (token.includes("/") || token.includes("\\")) {
|
|
317
370
|
const parts = token.replace(/\\/g, "/").split("/");
|
|
318
371
|
const basename = parts[parts.length - 1];
|
|
@@ -320,6 +373,11 @@ function extractFilenames(args) {
|
|
|
320
373
|
} else if (looksLikeFilename(token)) {
|
|
321
374
|
addFilename(token);
|
|
322
375
|
}
|
|
376
|
+
if (token.includes("*") || token.includes("?")) {
|
|
377
|
+
for (const expanded of expandSensitiveGlob(token)) {
|
|
378
|
+
addFilename(expanded);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
323
381
|
}
|
|
324
382
|
return;
|
|
325
383
|
}
|
|
@@ -343,6 +401,53 @@ function extractFilenames(args) {
|
|
|
343
401
|
}
|
|
344
402
|
return filenames;
|
|
345
403
|
}
|
|
404
|
+
var SENSITIVE_FILENAMES = [
|
|
405
|
+
".env",
|
|
406
|
+
".env.local",
|
|
407
|
+
".env.production",
|
|
408
|
+
".env.development",
|
|
409
|
+
"credentials.json",
|
|
410
|
+
"secrets.json",
|
|
411
|
+
"secrets.yaml",
|
|
412
|
+
"secrets.yml",
|
|
413
|
+
".npmrc",
|
|
414
|
+
".pypirc",
|
|
415
|
+
".netrc",
|
|
416
|
+
"id_rsa",
|
|
417
|
+
"id_ed25519",
|
|
418
|
+
"id_ecdsa",
|
|
419
|
+
"policy.json",
|
|
420
|
+
".mcp.json",
|
|
421
|
+
"guard.mjs",
|
|
422
|
+
"audit.mjs",
|
|
423
|
+
"settings.json"
|
|
424
|
+
];
|
|
425
|
+
function expandSensitiveGlob(pattern) {
|
|
426
|
+
const p = pattern.toLowerCase();
|
|
427
|
+
const matches = [];
|
|
428
|
+
for (const filename of SENSITIVE_FILENAMES) {
|
|
429
|
+
const f = filename.toLowerCase();
|
|
430
|
+
if (p === "*") {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
const startsWithStar = p.startsWith("*");
|
|
434
|
+
const endsWithStar = p.endsWith("*");
|
|
435
|
+
if (startsWithStar && endsWithStar) {
|
|
436
|
+
const infix = p.slice(1, -1);
|
|
437
|
+
if (infix && f.includes(infix)) matches.push(filename);
|
|
438
|
+
} else if (endsWithStar) {
|
|
439
|
+
const prefix = p.slice(0, -1);
|
|
440
|
+
if (f.startsWith(prefix)) matches.push(filename);
|
|
441
|
+
} else if (startsWithStar) {
|
|
442
|
+
const suffix = p.slice(1);
|
|
443
|
+
if (f.endsWith(suffix)) matches.push(filename);
|
|
444
|
+
} else if (p.includes("?")) {
|
|
445
|
+
const regex = new RegExp("^" + p.replace(/\?/g, ".").replace(/\*/g, ".*") + "$", "i");
|
|
446
|
+
if (regex.test(f)) matches.push(filename);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return matches;
|
|
450
|
+
}
|
|
346
451
|
function looksLikeFilename(s) {
|
|
347
452
|
if (s.startsWith(".")) return true;
|
|
348
453
|
if (/\.\w+$/.test(s)) return true;
|
|
@@ -446,7 +551,7 @@ function extractUrlArguments(args) {
|
|
|
446
551
|
addUrl(value);
|
|
447
552
|
return;
|
|
448
553
|
}
|
|
449
|
-
if (/^[a-zA-Z0-9]([a-zA-Z0-9-]*\.)+
|
|
554
|
+
if (/^[a-zA-Z0-9]([a-zA-Z0-9-]*\.)+(?:com|net|org|io|dev|app|co|me|info|biz|gov|edu|mil|onion|xyz|ai|cloud|sh|run|so|to|cc|tv|fm|am|gg|id)(\/.*)?$/.test(value)) {
|
|
450
555
|
addUrl(value);
|
|
451
556
|
return;
|
|
452
557
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/path-matcher.ts","../src/command-matcher.ts","../src/filename-matcher.ts","../src/url-matcher.ts","../src/matcher.ts","../src/evaluator.ts","../src/validator.ts","../src/warnings.ts","../src/defaults.ts","../src/engine.ts","../src/policy-store.ts"],"names":["endTime","UNSAFE_CONFIGURATION_WARNINGS","TrustLevel"],"mappings":";;;;;;AAQO,SAAS,cAAc,IAAA,EAAsB;AAElD,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAGxC,EAAA,IAAI,WAAW,MAAA,GAAS,CAAA,IAAK,UAAA,CAAW,QAAA,CAAS,GAAG,CAAA,EAAG;AACrD,IAAA,UAAA,GAAa,UAAA,CAAW,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACrC;AAGA,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA;AAClC,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,IAAA,KAAS,GAAA,IAAO,IAAA,KAAS,EAAA,EAAI;AAC/B,MAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,QAAA,CAAS,KAAK,EAAE,CAAA;AAC3C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,QAAA,QAAA,CAAS,GAAA,EAAI;AAAA,MACf;AACA,MAAA;AAAA,IACF;AACA,IAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,EACpB;AAEA,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA,IAAK,GAAA;AAC/B;AAMO,SAAS,YAAA,CAAa,MAAc,IAAA,EAAuB;AAChE,EAAA,MAAM,cAAA,GAAiB,cAAc,IAAI,CAAA;AACzC,EAAA,MAAM,cAAA,GAAiB,cAAc,IAAI,CAAA;AAGzC,EAAA,IAAI,cAAA,KAAmB,gBAAgB,OAAO,IAAA;AAC9C,EAAA,OAAO,cAAA,CAAe,UAAA,CAAW,cAAA,GAAiB,GAAG,CAAA;AACvD;AAWO,SAAS,gBAAA,CAAiB,MAAc,OAAA,EAA0B;AACvE,EAAA,MAAM,cAAA,GAAiB,cAAc,IAAI,CAAA;AACzC,EAAA,MAAM,iBAAA,GAAoB,cAAc,OAAO,CAAA;AAE/C,EAAA,IAAI,iBAAA,KAAsB,KAAK,OAAO,IAAA;AACtC,EAAA,IAAI,iBAAA,KAAsB,gBAAgB,OAAO,IAAA;AAEjD,EAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,KAAA,CAAM,GAAG,CAAA;AAChD,EAAA,MAAM,SAAA,GAAY,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA;AAE1C,EAAA,OAAO,UAAA,CAAW,SAAA,EAAW,CAAA,EAAG,YAAA,EAAc,CAAC,CAAA;AACjD;AAEA,SAAS,UAAA,CACP,SAAA,EACA,EAAA,EACA,YAAA,EACA,EAAA,EACS;AACT,EAAA,OAAO,EAAA,GAAK,SAAA,CAAU,MAAA,IAAU,EAAA,GAAK,aAAa,MAAA,EAAQ;AACxD,IAAA,MAAM,OAAA,GAAU,aAAa,EAAE,CAAA;AAE/B,IAAA,IAAI,YAAY,IAAA,EAAM;AAEpB,MAAA,IAAI,EAAA,KAAO,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAG3C,MAAA,KAAA,IAAS,CAAA,GAAI,EAAA,EAAI,CAAA,IAAK,SAAA,CAAU,QAAQ,CAAA,EAAA,EAAK;AAC3C,QAAA,IAAI,WAAW,SAAA,EAAW,CAAA,EAAG,YAAA,EAAc,EAAA,GAAK,CAAC,CAAA,EAAG;AAClD,UAAA,OAAO,IAAA;AAAA,QACT;AAAA,MACF;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,YAAY,GAAA,EAAK;AAEnB,MAAA,EAAA,EAAA;AACA,MAAA,EAAA,EAAA;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACzB,MAAA,IAAI,CAAC,gBAAA,CAAiB,SAAA,CAAU,EAAE,CAAA,EAAI,OAAO,CAAA,EAAG;AAC9C,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,EAAA,EAAA;AACA,MAAA,EAAA,EAAA;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,KAAY,SAAA,CAAU,EAAE,CAAA,EAAG;AAC7B,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,EAAA,EAAA;AACA,IAAA,EAAA,EAAA;AAAA,EACF;AAGA,EAAA,OAAO,KAAK,YAAA,CAAa,MAAA,IAAU,YAAA,CAAa,EAAE,MAAM,IAAA,EAAM;AAC5D,IAAA,EAAA,EAAA;AAAA,EACF;AAEA,EAAA,OAAO,EAAA,KAAO,SAAA,CAAU,MAAA,IAAU,EAAA,KAAO,YAAA,CAAa,MAAA;AACxD;AAWO,SAAS,aAAA,CACd,MACA,WAAA,EACS;AAET,EAAA,IAAI,YAAY,aAAA,EAAe;AAC7B,IAAA,IAAI,CAAC,YAAA,CAAa,IAAA,EAAM,WAAA,CAAY,aAAa,CAAA,EAAG;AAClD,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,MAAA,EAAQ;AACxC,MAAA,IAAI,gBAAA,CAAiB,IAAA,EAAM,OAAO,CAAA,EAAG;AACnC,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,WAAA,CAAY,OAAA,IAAW,WAAA,CAAY,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzD,IAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,OAAA,EAAS;AACzC,MAAA,IAAI,gBAAA,CAAiB,IAAA,EAAM,OAAO,CAAA,EAAG;AACnC,QAAA,cAAA,GAAiB,IAAA;AACjB,QAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,gBAAgB,OAAO,KAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,IAAA;AACT;AAMA,SAAS,gBAAA,CAAiB,SAAiB,OAAA,EAA0B;AACnE,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA;AAC7C,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA;AAEzC,EAAA,IAAI,OAAA,KAAY,KAAK,OAAO,IAAA;AAE5B,EAAA,IAAI,kBAAkB,YAAA,EAAc;AAElC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACjC,IAAA,OAAO,QAAQ,WAAA,EAAY,CAAE,QAAA,CAAS,KAAA,CAAM,aAAa,CAAA;AAAA,EAC3D;AACA,EAAA,IAAI,cAAA,EAAgB;AAElB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA;AAC9B,IAAA,OAAO,QAAQ,WAAA,EAAY,CAAE,QAAA,CAAS,MAAA,CAAO,aAAa,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,YAAA,EAAc;AAEhB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAClC,IAAA,OAAO,QAAQ,WAAA,EAAY,CAAE,UAAA,CAAW,MAAA,CAAO,aAAa,CAAA;AAAA,EAC9D;AAGA,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACnC,EAAA,IAAI,YAAY,EAAA,EAAI;AAClB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA;AACvC,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,OAAA,GAAU,CAAC,CAAA;AACxC,IAAA,MAAM,GAAA,GAAM,QAAQ,WAAA,EAAY;AAChC,IAAA,OAAO,IAAI,UAAA,CAAW,MAAA,CAAO,WAAA,EAAa,KAAK,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,WAAA,EAAa,CAAA,IAAK,GAAA,CAAI,MAAA,IAAU,MAAA,CAAO,SAAS,MAAA,CAAO,MAAA;AAAA,EAC5H;AAEA,EAAA,OAAO,OAAA,KAAY,OAAA;AACrB;AAKA,IAAM,WAAA,uBAAkB,GAAA,CAAI;AAAA,EAC1B,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAC,CAAA;AASM,SAAS,qBACd,IAAA,EACU;AACV,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,SAAS,QAAQ,KAAA,EAAqB;AACpC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,IAAA,IAAI,OAAA,IAAW,CAAC,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,EAAG;AACjC,MAAA,IAAA,CAAK,IAAI,OAAO,CAAA;AAChB,MAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAG/B,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,GAAA,CAAI,WAAA,EAAa,CAAA,EAAG;AACtC,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,MAAM,QAAA,CAAS,GAAG,KAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,EAAG;AAC/C,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,KAAA,CAAM,UAAA,CAAW,GAAG,CAAA,EAAG;AACzB,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;;;AC7QA,IAAM,cAAA,uBAAqB,GAAA,CAAI;AAAA,EAC7B,SAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAC,CAAA;AAMD,IAAM,kBAAA,GAAqB;AAAA,EACzB,6CAAA;AAAA;AAAA,EACA,kBAAA;AAAA;AAAA,EACA,cAAA;AAAA;AAAA,EACA,iBAAA;AAAA;AAAA,EACA,gBAAA;AAAA;AAAA,EACA,0BAAA;AAAA;AAAA,EACA,qBAAA;AAAA;AAAA,EACA;AAAA;AACF,CAAA;AAOO,SAAS,wBACd,IAAA,EACU;AACV,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,SAAS,WAAW,KAAA,EAAqB;AACvC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,IAAA,IAAI,OAAA,IAAW,CAAC,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,EAAG;AACjC,MAAA,IAAA,CAAK,IAAI,OAAO,CAAA;AAChB,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,IACvB;AAAA,EACF;AAEA,EAAA,SAAS,SAAA,CAAU,KAAa,KAAA,EAAsB;AACpD,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAE7B,MAAA,IAAI,cAAA,CAAe,GAAA,CAAI,GAAA,CAAI,WAAA,EAAa,CAAA,EAAG;AACzC,QAAA,UAAA,CAAW,KAAK,CAAA;AAChB,QAAA;AAAA,MACF;AAEA,MAAA,KAAA,MAAW,WAAW,kBAAA,EAAoB;AACxC,QAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,EAAG;AACvB,UAAA,UAAA,CAAW,KAAK,CAAA;AAChB,UAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,SAAA,CAAU,KAAK,IAAI,CAAA;AAAA,MACrB;AAAA,IACF,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,EAAM;AACtD,MAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAgC,CAAA,EAAG;AACrE,QAAA,SAAA,CAAU,GAAG,CAAC,CAAA;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,SAAA,CAAU,KAAK,KAAK,CAAA;AAAA,EACtB;AAEA,EAAA,OAAO,QAAA;AACT;AAYO,SAAS,mBAAA,CAAoB,SAAiB,OAAA,EAA0B;AAC7E,EAAA,IAAI,OAAA,KAAY,KAAK,OAAO,IAAA;AAE5B,EAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,IAAA,EAAK,CAAE,WAAA,EAAY;AACrD,EAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,IAAA,EAAK,CAAE,WAAA,EAAY;AAErD,EAAA,IAAI,iBAAA,KAAsB,mBAAmB,OAAO,IAAA;AAEpD,EAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA;AACvD,EAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,QAAA,CAAS,GAAG,CAAA;AAEnD,EAAA,IAAI,kBAAkB,YAAA,EAAc;AAClC,IAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC3C,IAAA,OAAO,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,iBAAA,CAAkB,SAAS,KAAK,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC5C,IAAA,OAAO,iBAAA,CAAkB,WAAW,MAAM,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAC,CAAA;AACxC,IAAA,OAAO,iBAAA,CAAkB,SAAS,MAAM,CAAA;AAAA,EAC1C;AAGA,EAAA,MAAM,cAAc,iBAAA,CAAkB,KAAA,CAAM,KAAK,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AACzD,EAAA,OAAO,WAAA,KAAgB,iBAAA;AACzB;AAUO,SAAS,gBAAA,CACd,SACA,WAAA,EACS;AAET,EAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,MAAA,EAAQ;AACxC,MAAA,IAAI,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA,EAAG;AACzC,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,WAAA,CAAY,OAAA,IAAW,WAAA,CAAY,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzD,IAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,OAAA,EAAS;AACzC,MAAA,IAAI,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA,EAAG;AACzC,QAAA,cAAA,GAAiB,IAAA;AACjB,QAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,gBAAgB,OAAO,KAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,IAAA;AACT;;;ACzJO,SAAS,iBACd,IAAA,EACU;AACV,EAAA,MAAM,YAAsB,EAAC;AAC7B,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,SAAS,YAAY,IAAA,EAAoB;AACvC,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,OAAA,IAAW,CAAC,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,EAAG;AACjC,MAAA,IAAA,CAAK,IAAI,OAAO,CAAA;AAChB,MAAA,SAAA,CAAU,KAAK,OAAO,CAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,SAAS,UAAU,KAAA,EAAsB;AACvC,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,MAAA,IAAI,CAAC,OAAA,EAAS;AAGd,MAAA,IAAI,eAAA,CAAgB,IAAA,CAAK,OAAO,CAAA,EAAG;AAGnC,MAAA,IAAI,QAAQ,QAAA,CAAS,GAAG,KAAK,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,EAAG;AACnD,QAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAC7C,QAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA;AAClC,QAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACvC,QAAA,IAAI,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AACnC,UAAA,WAAA,CAAY,QAAQ,CAAA;AAAA,QACtB;AACA,QAAA;AAAA,MACF;AAIA,MAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACzB,QAAA,KAAA,MAAW,KAAA,IAAS,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,EAAG;AACxC,UAAA,IAAI,MAAM,QAAA,CAAS,GAAG,KAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,EAAG;AAC/C,YAAA,MAAM,QAAQ,KAAA,CAAM,OAAA,CAAQ,OAAO,GAAG,CAAA,CAAE,MAAM,GAAG,CAAA;AACjD,YAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACvC,YAAA,IAAI,QAAA,IAAY,iBAAA,CAAkB,QAAQ,CAAA,cAAe,QAAQ,CAAA;AAAA,UACnE,CAAA,MAAA,IAAW,iBAAA,CAAkB,KAAK,CAAA,EAAG;AACnC,YAAA,WAAA,CAAY,KAAK,CAAA;AAAA,UACnB;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,iBAAA,CAAkB,OAAO,CAAA,EAAG;AAC9B,QAAA,WAAA,CAAY,OAAO,CAAA;AAAA,MACrB;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,SAAA,CAAU,IAAI,CAAA;AAAA,MAChB;AAAA,IACF,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,EAAM;AACtD,MAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,EAAG;AACpC,QAAA,SAAA,CAAU,CAAC,CAAA;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA,EAAG;AACvC,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB;AAEA,EAAA,OAAO,SAAA;AACT;AAMA,SAAS,kBAAkB,CAAA,EAAoB;AAE7C,EAAA,IAAI,CAAA,CAAE,UAAA,CAAW,GAAG,CAAA,EAAG,OAAO,IAAA;AAE9B,EAAA,IAAI,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AAE7B,EAAA,MAAM,UAAA,uBAAiB,GAAA,CAAI;AAAA,IACzB,QAAA;AAAA,IAAU,QAAA;AAAA,IAAU,UAAA;AAAA,IAAY,YAAA;AAAA,IAChC,iBAAA;AAAA,IAAmB,aAAA;AAAA,IACnB,UAAA;AAAA,IAAY,YAAA;AAAA,IAAc,aAAA;AAAA,IAC1B,SAAA;AAAA,IAAW,UAAA;AAAA,IAAY;AAAA,GACxB,CAAA;AACD,EAAA,IAAI,WAAW,GAAA,CAAI,CAAA,CAAE,WAAA,EAAa,GAAG,OAAO,IAAA;AAC5C,EAAA,OAAO,KAAA;AACT;AAWO,SAAS,oBAAA,CAAqB,UAAkB,OAAA,EAA0B;AAC/E,EAAA,IAAI,OAAA,KAAY,KAAK,OAAO,IAAA;AAE5B,EAAA,MAAM,kBAAA,GAAqB,SAAS,WAAA,EAAY;AAChD,EAAA,MAAM,iBAAA,GAAoB,QAAQ,WAAA,EAAY;AAE9C,EAAA,IAAI,kBAAA,KAAuB,mBAAmB,OAAO,IAAA;AAErD,EAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA;AACvD,EAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,QAAA,CAAS,GAAG,CAAA;AAEnD,EAAA,IAAI,kBAAkB,YAAA,EAAc;AAClC,IAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC3C,IAAA,OAAO,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,kBAAA,CAAmB,SAAS,KAAK,CAAA;AAAA,EAC9D;AACA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAC,CAAA;AACxC,IAAA,OAAO,kBAAA,CAAmB,SAAS,MAAM,CAAA;AAAA,EAC3C;AACA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC5C,IAAA,OAAO,kBAAA,CAAmB,WAAW,MAAM,CAAA;AAAA,EAC7C;AAGA,EAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,OAAA,CAAQ,GAAG,CAAA;AAC7C,EAAA,IAAI,YAAY,EAAA,EAAI;AAClB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,OAAA,GAAU,CAAC,CAAA;AAClD,IAAA,OACE,kBAAA,CAAmB,UAAA,CAAW,MAAM,CAAA,IACpC,kBAAA,CAAmB,QAAA,CAAS,MAAM,CAAA,IAClC,kBAAA,CAAmB,MAAA,IAAU,MAAA,CAAO,MAAA,GAAS,MAAA,CAAO,MAAA;AAAA,EAExD;AAEA,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,iBAAA,CACd,UACA,WAAA,EACS;AAET,EAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,MAAA,EAAQ;AACxC,MAAA,IAAI,oBAAA,CAAqB,QAAA,EAAU,OAAO,CAAA,EAAG;AAC3C,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,WAAA,CAAY,OAAA,IAAW,WAAA,CAAY,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzD,IAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,OAAA,EAAS;AACzC,MAAA,IAAI,oBAAA,CAAqB,QAAA,EAAU,OAAO,CAAA,EAAG;AAC3C,QAAA,cAAA,GAAiB,IAAA;AACjB,QAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,gBAAgB,OAAO,KAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,IAAA;AACT;;;ACjLA,IAAM,UAAA,uBAAiB,GAAA,CAAI;AAAA,EACzB,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAC,CAAA;AAOM,SAAS,oBACd,IAAA,EACU;AACV,EAAA,MAAM,OAAiB,EAAC;AACxB,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,SAAS,OAAO,KAAA,EAAqB;AACnC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,IAAA,IAAI,OAAA,IAAW,CAAC,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,EAAG;AACjC,MAAA,IAAA,CAAK,IAAI,OAAO,CAAA;AAChB,MAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,IACnB;AAAA,EACF;AAEA,EAAA,SAAS,SAAA,CAAU,KAAa,KAAA,EAAsB;AACpD,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAE9B,MAAA,IAAI,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,EAAG;AACzB,QAAA,MAAA,CAAO,KAAK,CAAA;AACZ,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,cAAA,CAAe,IAAA,CAAK,KAAK,CAAA,EAAG;AAC9B,QAAA,MAAA,CAAO,KAAK,CAAA;AACZ,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,oDAAA,CAAqD,IAAA,CAAK,KAAK,CAAA,EAAG;AACpE,QAAA,MAAA,CAAO,KAAK,CAAA;AACZ,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,SAAA,CAAU,KAAK,IAAI,CAAA;AAAA,MACrB;AAAA,IACF,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,EAAM;AACtD,MAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC1C,QAAA,SAAA,CAAU,GAAG,CAAC,CAAA;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,SAAA,CAAU,KAAK,KAAK,CAAA;AAAA,EACtB;AAEA,EAAA,OAAO,IAAA;AACT;AAYO,SAAS,eAAA,CAAgB,KAAa,OAAA,EAA0B;AACrE,EAAA,IAAI,OAAA,KAAY,KAAK,OAAO,IAAA;AAE5B,EAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,IAAA,EAAK,CAAE,WAAA,EAAY;AAC7C,EAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,IAAA,EAAK,CAAE,WAAA,EAAY;AAErD,EAAA,IAAI,iBAAA,KAAsB,eAAe,OAAO,IAAA;AAEhD,EAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA;AACvD,EAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,QAAA,CAAS,GAAG,CAAA;AAEnD,EAAA,IAAI,kBAAkB,YAAA,EAAc;AAClC,IAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC3C,IAAA,OAAO,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,aAAA,CAAc,SAAS,KAAK,CAAA;AAAA,EACzD;AACA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC5C,IAAA,OAAO,aAAA,CAAc,WAAW,MAAM,CAAA;AAAA,EACxC;AACA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,CAAC,CAAA;AACxC,IAAA,OAAO,aAAA,CAAc,SAAS,MAAM,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,YAAA,CACd,KACA,WAAA,EACS;AAET,EAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,MAAA,EAAQ;AACxC,MAAA,IAAI,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,EAAG;AACjC,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,WAAA,CAAY,OAAA,IAAW,WAAA,CAAY,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzD,IAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,IAAA,KAAA,MAAW,OAAA,IAAW,YAAY,OAAA,EAAS;AACzC,MAAA,IAAI,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,EAAG;AACjC,QAAA,cAAA,GAAiB,IAAA;AACjB,QAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,gBAAgB,OAAO,KAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,IAAA;AACT;;;AC1IO,SAAS,kBAAA,CACd,MACA,OAAA,EACS;AACT,EAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,OAAO,KAAA;AAC1B,EAAA,IAAI,KAAK,UAAA,IAAc,IAAA,CAAK,UAAA,KAAe,OAAA,CAAQ,oBAAoB,OAAO,KAAA;AAC9E,EAAA,IAAI,CAAC,kBAAA,CAAmB,IAAA,CAAK,aAAa,OAAA,CAAQ,QAAQ,GAAG,OAAO,KAAA;AACpE,EAAA,IAAI,CAAC,sBAAA,CAAuB,OAAA,CAAQ,QAAQ,UAAA,EAAY,IAAA,CAAK,iBAAiB,CAAA,EAAG;AAC/E,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAK,mBAAA,EAAqB;AAC5B,IAAA,IAAI,CAAC,wBAAA,CAAyB,IAAA,CAAK,mBAAA,EAAqB,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC1E,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,IAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,IAAA,CAAK,eAAA,EAAiB,QAAQ,SAAS,CAAA;AAG9E,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,IAAI,WAAW,OAAO,KAAA;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,IAAI,CAAC,WAAW,OAAO,KAAA;AAAA,IACzB;AAAA,EACF;AACA,EAAA,IAAI,KAAK,kBAAA,EAAoB;AAC3B,IAAA,MAAM,SAAA,GAAY,uBAAA,CAAwB,IAAA,CAAK,kBAAA,EAAoB,QAAQ,SAAS,CAAA;AACpF,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,IAAI,WAAW,OAAO,KAAA;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,IAAI,CAAC,WAAW,OAAO,KAAA;AAAA,IACzB;AAAA,EACF;AACA,EAAA,IAAI,KAAK,mBAAA,EAAqB;AAC5B,IAAA,MAAM,SAAA,GAAY,wBAAA,CAAyB,IAAA,CAAK,mBAAA,EAAqB,QAAQ,SAAS,CAAA;AACtF,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,IAAI,WAAW,OAAO,KAAA;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,IAAI,CAAC,WAAW,OAAO,KAAA;AAAA,IACzB;AAAA,EACF;AACA,EAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,IAAA,MAAM,SAAA,GAAY,mBAAA,CAAoB,IAAA,CAAK,cAAA,EAAgB,QAAQ,SAAS,CAAA;AAC5E,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,IAAI,WAAW,OAAO,KAAA;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,IAAI,CAAC,WAAW,OAAO,KAAA;AAAA,IACzB;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAWO,SAAS,kBAAA,CAAmB,SAAiB,QAAA,EAA2B;AAC7E,EAAA,IAAI,OAAA,KAAY,KAAK,OAAO,IAAA;AAE5B,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA;AAC7C,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA;AAEzC,EAAA,IAAI,kBAAkB,YAAA,EAAc;AAElC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACjC,IAAA,OAAO,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,QAAA,CAAS,SAAS,KAAK,CAAA;AAAA,EACpD;AACA,EAAA,IAAI,YAAA,EAAc;AAEhB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAClC,IAAA,OAAO,QAAA,CAAS,WAAW,MAAM,CAAA;AAAA,EACnC;AACA,EAAA,IAAI,cAAA,EAAgB;AAElB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA;AAC9B,IAAA,OAAO,QAAA,CAAS,SAAS,MAAM,CAAA;AAAA,EACjC;AAEA,EAAA,OAAO,OAAA,KAAY,QAAA;AACrB;AAEA,IAAM,iBAAA,GAA4C;AAAA,EAChD,CAAC,UAAA,CAAW,SAAS,GAAG,CAAA;AAAA,EACxB,CAAC,UAAA,CAAW,QAAQ,GAAG,CAAA;AAAA,EACvB,CAAC,UAAA,CAAW,OAAO,GAAG;AACxB,CAAA;AAEO,SAAS,sBAAA,CACd,QACA,OAAA,EACS;AACT,EAAA,OAAA,CAAQ,kBAAkB,MAAM,CAAA,IAAK,EAAA,MAAQ,iBAAA,CAAkB,OAAO,CAAA,IAAK,QAAA,CAAA;AAC7E;AAiBA,SAAS,wBAAA,CACP,aACA,IAAA,EACS;AACT,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC3D,IAAA,IAAI,EAAE,GAAA,IAAO,IAAA,CAAA,EAAO,OAAO,KAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,KAAK,GAAG,CAAA;AAGzB,IAAA,IAAI,OAAO,eAAe,QAAA,EAAU;AAClC,MAAA,IAAI,eAAe,GAAA,EAAK;AACxB,MAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAChC,QAAA,IAAI,QAAA,KAAa,YAAY,OAAO,KAAA;AAAA,MACtC,CAAA,MAAO;AACL,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,OAAO,eAAe,QAAA,IAAY,UAAA,KAAe,QAAQ,CAAC,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AACvF,MAAA,MAAM,GAAA,GAAM,UAAA;AACZ,MAAA,MAAM,QAAA,GAAW,OAAO,QAAA,KAAa,QAAA,GAAW,QAAA,GAAW,MAAA;AAC3D,MAAA,MAAM,QAAA,GAAW,OAAO,QAAA,KAAa,QAAA,GAAW,QAAA,GAAW,MAAA;AAE3D,MAAA,IAAI,WAAA,IAAe,GAAA,IAAO,OAAO,GAAA,CAAI,cAAc,QAAA,EAAU;AAC3D,QAAA,IAAI,CAAC,YAAY,CAAC,QAAA,CAAS,SAAS,GAAA,CAAI,SAAS,GAAG,OAAO,KAAA;AAAA,MAC7D;AACA,MAAA,IAAI,cAAA,IAAkB,GAAA,IAAO,OAAO,GAAA,CAAI,iBAAiB,QAAA,EAAU;AACjE,QAAA,IAAI,YAAY,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,YAAY,GAAG,OAAO,KAAA;AAAA,MAC9D;AACA,MAAA,IAAI,aAAA,IAAiB,GAAA,IAAO,OAAO,GAAA,CAAI,gBAAgB,QAAA,EAAU;AAC/D,QAAA,IAAI,CAAC,YAAY,CAAC,QAAA,CAAS,WAAW,GAAA,CAAI,WAAW,GAAG,OAAO,KAAA;AAAA,MACjE;AACA,MAAA,IAAI,WAAA,IAAe,GAAA,IAAO,OAAO,GAAA,CAAI,cAAc,QAAA,EAAU;AAC3D,QAAA,IAAI,CAAC,YAAY,CAAC,QAAA,CAAS,SAAS,GAAA,CAAI,SAAS,GAAG,OAAO,KAAA;AAAA,MAC7D;AACA,MAAA,IAAI,SAAS,GAAA,IAAO,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,EAAG;AAC1C,QAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,QAAA,CAAS,QAAQ,GAAG,OAAO,KAAA;AAAA,MAC1C;AACA,MAAA,IAAI,YAAY,GAAA,IAAO,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,EAAG;AAChD,QAAA,IAAI,GAAA,CAAI,MAAA,CAAO,QAAA,CAAS,QAAQ,GAAG,OAAO,KAAA;AAAA,MAC5C;AACA,MAAA,IAAI,KAAA,IAAS,GAAA,IAAO,OAAO,GAAA,CAAI,QAAQ,QAAA,EAAU;AAC/C,QAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,IAAY,GAAA,CAAI,KAAK,OAAO,KAAA;AAAA,MAC5D;AACA,MAAA,IAAI,KAAA,IAAS,GAAA,IAAO,OAAO,GAAA,CAAI,QAAQ,QAAA,EAAU;AAC/C,QAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,IAAY,GAAA,CAAI,KAAK,OAAO,KAAA;AAAA,MAC5D;AACA,MAAA,IAAI,MAAA,IAAU,GAAA,IAAO,OAAO,GAAA,CAAI,SAAS,QAAA,EAAU;AACjD,QAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,GAAW,GAAA,CAAI,MAAM,OAAO,KAAA;AAAA,MAC5D;AACA,MAAA,IAAI,MAAA,IAAU,GAAA,IAAO,OAAO,GAAA,CAAI,SAAS,QAAA,EAAU;AACjD,QAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,GAAW,GAAA,CAAI,MAAM,OAAO,KAAA;AAAA,MAC5D;AAEA,MAAA;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,oBAAA,CACP,aACA,IAAA,EACS;AACT,EAAA,MAAM,KAAA,GAAQ,qBAAqB,IAAI,CAAA;AAGvC,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAG/B,EAAA,OAAO,MAAM,KAAA,CAAM,CAAC,SAAS,aAAA,CAAc,IAAA,EAAM,WAAW,CAAC,CAAA;AAC/D;AAEA,SAAS,uBAAA,CACP,aACA,IAAA,EACS;AACT,EAAA,MAAM,QAAA,GAAW,wBAAwB,IAAI,CAAA;AAG7C,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAGlC,EAAA,OAAO,SAAS,KAAA,CAAM,CAAC,QAAQ,gBAAA,CAAiB,GAAA,EAAK,WAAW,CAAC,CAAA;AACnE;AAEA,SAAS,wBAAA,CACP,aACA,IAAA,EACS;AACT,EAAA,MAAM,SAAA,GAAY,iBAAiB,IAAI,CAAA;AAGvC,EAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAGnC,EAAA,OAAO,UAAU,KAAA,CAAM,CAAC,SAAS,iBAAA,CAAkB,IAAA,EAAM,WAAW,CAAC,CAAA;AACvE;AAEA,SAAS,mBAAA,CACP,aACA,IAAA,EACS;AACT,EAAA,MAAM,IAAA,GAAO,oBAAoB,IAAI,CAAA;AAGrC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAG9B,EAAA,OAAO,KAAK,KAAA,CAAM,CAAC,QAAQ,YAAA,CAAa,GAAA,EAAK,WAAW,CAAC,CAAA;AAC3D;;;ACzNO,SAAS,cAAA,CACd,WACA,OAAA,EACgB;AAChB,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAElC,EAAA,MAAM,WAAA,GAAc,CAAC,GAAG,SAAA,CAAU,KAAK,CAAA,CAAE,IAAA;AAAA,IACvC,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA,CAAE;AAAA,GAC3B;AAEA,EAAA,KAAA,MAAW,QAAQ,WAAA,EAAa;AAC9B,IAAA,IAAI,kBAAA,CAAmB,IAAA,EAAM,OAAO,CAAA,EAAG;AACrC,MAAA,MAAMA,QAAAA,GAAU,YAAY,GAAA,EAAI;AAChC,MAAA,OAAO;AAAA,QACL,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,WAAA,EAAa,IAAA;AAAA,QACb,QAAQ,CAAA,cAAA,EAAiB,IAAA,CAAK,EAAE,CAAA,GAAA,EAAM,KAAK,WAAW,CAAA,CAAA;AAAA,QACtD,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,kBAAkBA,QAAAA,GAAU;AAAA,OAC9B;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,YAAY,GAAA,EAAI;AAChC,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,qBAAA;AAAA,IACR,WAAA,EAAa,IAAA;AAAA,IACb,MAAA,EAAQ,sDAAA;AAAA,IACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,kBAAkB,OAAA,GAAU,SAAA;AAAA,IAC5B,QAAA,EAAU;AAAA,MACR,gBAAgB,WAAA,CAAY,MAAA;AAAA,MAC5B,SAAS,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA,QACd,MAAM,OAAA,CAAQ,QAAA;AAAA,QACd,WAAW,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,IAAa,EAAE;AAAA;AAChD;AACF,GACF;AACF;AC/CO,SAAS,mBAAmB,KAAA,EAAkC;AACnE,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,SAAA,CAAU,KAAK,CAAA;AAC/C,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA;AAAA,QAC1B,CAAC,CAAA,KAAM,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA;AAAA,OAC1C;AAAA,MACA,UAAU;AAAC,KACb;AAAA,EACF;AAEA,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AAEpB,EAAA,IAAI,IAAA,CAAK,WAAA,KAAgB,GAAA,IAAO,IAAA,CAAK,WAAW,OAAA,EAAS;AACvD,IAAA,QAAA,CAAS,IAAA,CAAK,8BAA8B,cAAc,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,IAAA,CAAK,sBAAsB,SAAA,EAAW;AACxC,IAAA,QAAA,CAAS,IAAA,CAAK,8BAA8B,sBAAsB,CAAA;AAAA,EACpE;AAEA,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,eAAe,SAAA,EAAW;AACrD,IAAA,QAAA,CAAS,IAAA,CAAK,8BAA8B,sBAAsB,CAAA;AAAA,EACpE;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAS;AACzC;AAEO,SAAS,kBAAkB,KAAA,EAAkC;AAClE,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,SAAA,CAAU,KAAK,CAAA;AAC9C,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA;AAAA,QAC1B,CAAC,CAAA,KAAM,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA;AAAA,OAC1C;AAAA,MACA,UAAU;AAAC,KACb;AAAA,EACF;AAEA,EAAA,MAAM,YAAY,MAAA,CAAO,IAAA;AAEzB,EAAA,IAAI,SAAA,CAAU,KAAA,CAAM,MAAA,GAAS,wBAAA,EAA0B;AACrD,IAAA,MAAA,CAAO,IAAA;AAAA,MACL,iCAAiC,wBAAwB,CAAA,MAAA;AAAA,KAC3D;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,KAAA,MAAW,IAAA,IAAQ,UAAU,KAAA,EAAO;AAClC,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AACxB,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuB,IAAA,CAAK,EAAE,CAAA,CAAA,CAAG,CAAA;AAAA,IAC/C;AACA,IAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,EACrB;AAEA,EAAA,KAAA,MAAW,IAAA,IAAQ,UAAU,KAAA,EAAO;AAClC,IAAA,MAAM,UAAA,GAAa,mBAAmB,IAAI,CAAA;AAC1C,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,UAAA,CAAW,QAAQ,CAAA;AAAA,EACtC;AAEA,EAAA,MAAM,WAAA,GAAc,UAAU,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,MAAM,CAAA;AACnE,EAAA,IAAI,CAAC,WAAA,IAAe,SAAA,CAAU,KAAA,CAAM,SAAS,CAAA,EAAG;AAC9C,IAAA,QAAA,CAAS,IAAA;AAAA,MACP;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,OAAO,MAAA,KAAW,CAAA;AAAA,IACzB,MAAA;AAAA,IACA;AAAA,GACF;AACF;AChFO,SAAS,wBACd,SAAA,EAC4B;AAC5B,EAAA,MAAM,WAA8B,EAAC;AAErC,EAAA,KAAA,MAAW,IAAA,IAAQ,UAAU,KAAA,EAAO;AAClC,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,mBAAA,CAAoB,IAAI,CAAC,CAAA;AAAA,EAC5C;AAEA,EAAA,MAAM,UAAA,GAAa,UAAU,KAAA,CAAM,MAAA;AAAA,IACjC,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA,CAAE;AAAA,GACnC;AACA,EAAA,MAAM,iBAAiB,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,gBAAgB,GAAG,CAAA;AAErE,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,QAAA,CAAS,IAAA,CAAK;AAAA,MACZ,KAAA,EAAO,UAAA;AAAA,MACP,IAAA,EAAM,gBAAA;AAAA,MACN,SAASC,6BAAAA,CAA8B,cAAA;AAAA,MACvC,cAAA,EACE;AAAA,KACH,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,QAAA;AACT;AAEA,SAAS,oBAAoB,IAAA,EAAqC;AAChE,EAAA,MAAM,WAA8B,EAAC;AAErC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,OAAA,IAAW,IAAA,CAAK,sBAAsB,WAAA,EAAa;AACrE,IAAA,QAAA,CAAS,IAAA,CAAK;AAAA,MACZ,KAAA,EAAO,UAAA;AAAA,MACP,IAAA,EAAM,iBAAA;AAAA,MACN,OAAA,EAAS,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,qFAAA,CAAA;AAAA,MACzB,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,cAAA,EACE;AAAA,KACH,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,IAAA,CAAK,WAAW,OAAA,KAAY,CAAC,KAAK,UAAA,IAAc,IAAA,CAAK,eAAe,SAAA,CAAA,EAAY;AAClF,IAAA,QAAA,CAAS,IAAA,CAAK;AAAA,MACZ,KAAA,EAAO,SAAA;AAAA,MACP,IAAA,EAAM,eAAA;AAAA,MACN,SAASA,6BAAAA,CAA8B,sBAAA;AAAA,MACvC,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,cAAA,EACE;AAAA,KACH,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,QAAA;AACT;AC1DO,SAAS,0BAAA,GAAwC;AACtD,EAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEnC,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,cAAA;AAAA,IACJ,IAAA,EAAM,kBAAA;AAAA,IACN,WAAA,EACE,yFAAA;AAAA,IACF,OAAA,EAAS,CAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL;AAAA,QACE,EAAA,EAAI,kBAAA;AAAA,QACJ,WAAA,EAAa,qCAAA;AAAA,QACb,QAAQ,YAAA,CAAa,IAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,OAAA;AAAA,QACvB,mBAAmBC,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,gBAAA;AAAA,QACJ,WAAA,EAAa,sCAAA;AAAA,QACb,QAAQ,YAAA,CAAa,IAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,KAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,eAAA;AAAA,QACJ,WAAA,EAAa,qCAAA;AAAA,QACb,QAAQ,YAAA,CAAa,IAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,IAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,SAAA,EAAW,GAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AACF;AAOO,SAAS,yBAAA,GAAuC;AACrD,EAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEnC,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,YAAA;AAAA,IACJ,IAAA,EAAM,wBAAA;AAAA,IACN,WAAA,EAAa,0GAAA;AAAA,IACb,OAAA,EAAS,CAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL;AAAA,QACE,EAAA,EAAI,mBAAA;AAAA,QACJ,WAAA,EAAa,2BAAA;AAAA,QACb,QAAQ,YAAA,CAAa,KAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,OAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,gBAAA;AAAA,QACJ,WAAA,EAAa,2BAAA;AAAA,QACb,QAAQ,YAAA,CAAa,KAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,IAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,iBAAA;AAAA,QACJ,WAAA,EAAa,4BAAA;AAAA,QACb,QAAQ,YAAA,CAAa,KAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,KAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,SAAA,EAAW,GAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AACF;AAMO,SAAS,wBAAwB,WAAA,EAAgC;AACtE,EAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEnC,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,aAAa,WAAW,CAAA,CAAA;AAAA,IAC5B,IAAA,EAAM,cAAc,WAAW,CAAA,CAAA;AAAA,IAC/B,WAAA,EAAa,yCAAyC,WAAW,CAAA,4BAAA,CAAA;AAAA,IACjE,OAAA,EAAS,CAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL;AAAA,QACE,EAAA,EAAI,cAAc,WAAW,CAAA,CAAA;AAAA,QAC7B,WAAA,EAAa,wBAAwB,WAAW,CAAA,CAAA;AAAA,QAChD,QAAQ,YAAA,CAAa,KAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA;AAAA,QACA,YAAY,UAAA,CAAW,IAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,QAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,SAAA,EAAW,GAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AACF;AAOO,SAAS,yBAAyB,OAAA,EAA4B;AACnE,EAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEnC,EAAA,OAAO;AAAA,IACL,IAAI,CAAA,QAAA,EAAW,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAC,CAAA,CAAA;AAAA,IAC1C,IAAA,EAAM,YAAY,OAAO,CAAA,CAAA;AAAA,IACzB,WAAA,EAAa,4BAA4B,OAAO,CAAA,sDAAA,CAAA;AAAA,IAChD,OAAA,EAAS,CAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL;AAAA,QACE,EAAA,EAAI,yBAAA;AAAA,QACJ,WAAA,EAAa,gCAAA;AAAA,QACb,QAAQ,YAAA,CAAa,IAAA;AAAA,QACrB,QAAA,EAAU,EAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,OAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,kBAAA,EAAoB;AAAA,UAClB,MAAA,EAAQ;AAAA,YACN,UAAA;AAAA,YAAY,UAAA;AAAA,YAAY,OAAA;AAAA,YAAS,SAAA;AAAA,YACjC,cAAA;AAAA,YAAgB,YAAA;AAAA,YAChB,WAAA;AAAA,YAAa,SAAA;AAAA,YAAW;AAAA;AAC1B,SACF;AAAA,QACA,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,sBAAA;AAAA,QACJ,WAAA,EAAa,iCAAA;AAAA,QACb,QAAQ,YAAA,CAAa,IAAA;AAAA,QACrB,QAAA,EAAU,EAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,OAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,eAAA,EAAiB;AAAA,UACf,MAAA,EAAQ;AAAA,YACN,UAAA;AAAA,YAAY,YAAA;AAAA,YAAc,YAAA;AAAA,YAC1B,iBAAA;AAAA,YAAmB,UAAA;AAAA,YAAY;AAAA;AACjC,SACF;AAAA,QACA,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,uBAAA;AAAA,QACJ,WAAA,EAAa,gCAAgC,OAAO,CAAA,CAAA;AAAA,QACpD,QAAQ,YAAA,CAAa,KAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,QAAA;AAAA,QACb,YAAY,UAAA,CAAW,OAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,eAAA,EAAiB;AAAA,UACf,aAAA,EAAe,OAAA;AAAA,UACf,OAAA,EAAS,CAAC,CAAA,EAAG,OAAO,CAAA,GAAA,CAAK;AAAA,SAC3B;AAAA,QACA,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,QACE,EAAA,EAAI,mBAAA;AAAA,QACJ,WAAA,EAAa,iCAAA;AAAA,QACb,QAAQ,YAAA,CAAa,KAAA;AAAA,QACrB,QAAA,EAAU,GAAA;AAAA,QACV,WAAA,EAAa,GAAA;AAAA,QACb,YAAY,UAAA,CAAW,OAAA;AAAA,QACvB,mBAAmBA,UAAAA,CAAW,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,SAAA,EAAW,GAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AACF;;;AChNO,IAAM,eAAN,MAAmB;AAAA,EAChB,SAAA;AAAA,EACS,SAAA;AAAA,EACA,KAAA;AAAA,EAEjB,YAAY,OAAA,EAIT;AACD,IAAA,IAAA,CAAK,SAAA,GAAY,OAAA,EAAS,SAAA,IAAa,0BAAA,EAA2B;AAClE,IAAA,IAAA,CAAK,SAAA,GAAY,SAAS,SAAA,IAAa,4BAAA;AACvC,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAS,KAAA,IAAS,IAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,OAAA,EAA2C;AAClD,IAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAClC,IAAA,MAAM,QAAA,GAAW,cAAA,CAAe,IAAA,CAAK,SAAA,EAAW,OAAO,CAAA;AACvD,IAAA,MAAM,OAAA,GAAU,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAEpC,IAAA,IAAI,OAAA,GAAU,KAAK,SAAA,EAAW;AAC5B,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,CAAA,mCAAA,EAAsC,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAC,cAC7C,IAAA,CAAK,SAAS,CAAA,cAAA,EAAiB,OAAA,CAAQ,QAAQ,CAAA,CAAA;AAAA,OAC5D;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAA,CACE,WACA,OAAA,EACkB;AAClB,IAAA,MAAM,UAAA,GAAa,kBAAkB,SAAS,CAAA;AAC9C,IAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AACrB,MAAA,OAAO,UAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AAEjB,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,KAAA,CAAM,WAAA;AAAA,QACT,SAAA;AAAA,QACA,SAAS,MAAA,IAAU,gBAAA;AAAA,QACnB,SAAS,SAAA,IAAa;AAAA,OACxB;AAAA,IACF;AAEA,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,OAAA,EAAgC;AACvC,IAAA,IAAI,CAAC,KAAK,KAAA,EAAO;AACf,MAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,IAChE;AAEA,IAAA,MAAM,gBAAgB,IAAA,CAAK,KAAA,CAAM,SAAS,IAAA,CAAK,SAAA,CAAU,IAAI,OAAO,CAAA;AACpE,IAAA,IAAA,CAAK,YAAY,aAAA,CAAc,SAAA;AAC/B,IAAA,OAAO,aAAA;AAAA,EACT;AAAA,EAEA,YAAA,GAAoC;AAClC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,mBAAA,GAAkD;AAChD,IAAA,OAAO,uBAAA,CAAwB,KAAK,SAAS,CAAA;AAAA,EAC/C;AAAA,EAEA,QAAA,GAA+B;AAC7B,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,YAAY,0BAAA,EAA2B;AAAA,EAC9C;AACF;AC3EO,IAAM,cAAN,MAAkB;AAAA,EACN,QAAA,uBAAe,GAAA,EAA6B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7D,WAAA,CACE,SAAA,EACA,MAAA,EACA,SAAA,EACe;AACf,IAAA,MAAM,KAAK,SAAA,CAAU,EAAA;AACrB,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAE,KAAK,EAAC;AAE1C,IAAA,MAAM,aAAA,GAAgB,QAAQ,MAAA,GAAS,CAAA,GAAI,QAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,CAAG,OAAA,GAAU,CAAA;AAElF,IAAA,MAAM,OAAA,GAAyB;AAAA,MAC7B,SAAS,aAAA,GAAgB,CAAA;AAAA,MACzB,WAAW,MAAA,CAAO,MAAA,CAAO,EAAE,GAAG,WAAW,CAAA;AAAA,MACzC,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,SAAS,CAAA;AAAA,MAChC,MAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,KACpC;AAEA,IAAA,MAAM,UAAA,GAAa,CAAC,GAAG,OAAA,EAAS,OAAO,CAAA;AACvC,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAA,EAAI,UAAU,CAAA;AAEhC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,CAAW,IAAY,OAAA,EAAuC;AAC5D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AACpC,IAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,IAAA,OAAO,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,OAAA,KAAY,OAAO,CAAA,IAAK,IAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,EAAA,EAAkC;AAC1C,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AACpC,IAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,MAAA,KAAW,GAAG,OAAO,IAAA;AAC7C,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,EAAA,EAAsC;AAC/C,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAE,KAAK,EAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAA,CAAS,IAAY,SAAA,EAAkC;AACrD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,UAAA,CAAW,EAAA,EAAI,SAAS,CAAA;AAC5C,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,SAAS,CAAA,uBAAA,EAA0B,EAAE,CAAA,CAAA,CAAG,CAAA;AAAA,IACrE;AAEA,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,MACV,MAAA,CAAO,SAAA;AAAA,MACP,uBAAuB,SAAS,CAAA,CAAA;AAAA,MAChC;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,CAAK,IAAmB,EAAA,EAA+B;AACrD,IAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,EAAA,CAAG,UAAU,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AACpE,IAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,EAAA,CAAG,UAAU,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AAEpE,IAAA,MAAM,QAAsB,EAAC;AAC7B,IAAA,MAAM,UAAwB,EAAC;AAC/B,IAAA,MAAM,WAAmD,EAAC;AAG1D,IAAA,KAAA,MAAW,CAAC,EAAA,EAAI,OAAO,CAAA,IAAK,WAAA,EAAa;AACvC,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,GAAA,CAAI,EAAE,CAAA;AAClC,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAAA,MACpB,CAAA,MAAA,IAAW,KAAK,SAAA,CAAU,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG;AAC9D,QAAA,QAAA,CAAS,KAAK,EAAE,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,SAAS,CAAA;AAAA,MAC9C;AAAA,IACF;AAGA,IAAA,KAAA,MAAW,CAAC,EAAA,EAAI,OAAO,CAAA,IAAK,WAAA,EAAa;AACvC,MAAA,IAAI,CAAC,WAAA,CAAY,GAAA,CAAI,EAAE,CAAA,EAAG;AACxB,QAAA,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,MACtB;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAS;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAA,EAA8B;AACxC,IAAA,MAAM,UAAA,GAAa,KAAK,SAAA,CAAU,SAAA,EAAW,OAAO,IAAA,CAAK,SAAS,CAAA,CAAE,IAAA,EAAM,CAAA;AAC1E,IAAA,OAAO,WAAW,QAAQ,CAAA,CAAE,OAAO,UAAU,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,EAC7D;AACF","file":"index.js","sourcesContent":["import type { PolicyRule } from '@solongate/core';\n\ntype PathConstraints = NonNullable<PolicyRule['pathConstraints']>;\n\n/**\n * Normalizes a file path for consistent matching.\n * Resolves . and .. segments, normalizes separators.\n */\nexport function normalizePath(path: string): string {\n // Normalize separators to forward slash\n let normalized = path.replace(/\\\\/g, '/');\n\n // Remove trailing slash (except for root)\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n // Resolve . and .. segments\n const parts = normalized.split('/');\n const resolved: string[] = [];\n\n for (const part of parts) {\n if (part === '.' || part === '') {\n if (resolved.length === 0) resolved.push('');\n continue;\n }\n if (part === '..') {\n if (resolved.length > 1) {\n resolved.pop();\n }\n continue;\n }\n resolved.push(part);\n }\n\n return resolved.join('/') || '/';\n}\n\n/**\n * Checks if a path is within a root directory (sandbox boundary).\n * Prevents escaping via .., symlinks, etc.\n */\nexport function isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedRoot = normalizePath(root);\n\n // Path must start with root\n if (normalizedPath === normalizedRoot) return true;\n return normalizedPath.startsWith(normalizedRoot + '/');\n}\n\n/**\n * Glob-style path pattern matching.\n * Supports:\n * - * matches any single path segment (not /)\n * - ** matches any number of path segments\n * - Exact match\n *\n * Does NOT support regex (ReDoS prevention).\n */\nexport function matchPathPattern(path: string, pattern: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedPattern = normalizePath(pattern);\n\n if (normalizedPattern === '*') return true;\n if (normalizedPattern === normalizedPath) return true;\n\n const patternParts = normalizedPattern.split('/');\n const pathParts = normalizedPath.split('/');\n\n return matchParts(pathParts, 0, patternParts, 0);\n}\n\nfunction matchParts(\n pathParts: string[],\n pi: number,\n patternParts: string[],\n qi: number,\n): boolean {\n while (pi < pathParts.length && qi < patternParts.length) {\n const pattern = patternParts[qi]!;\n\n if (pattern === '**') {\n // ** can match zero or more path segments\n if (qi === patternParts.length - 1) return true;\n\n // Try matching ** against 0, 1, 2, ... path segments\n for (let i = pi; i <= pathParts.length; i++) {\n if (matchParts(pathParts, i, patternParts, qi + 1)) {\n return true;\n }\n }\n return false;\n }\n\n if (pattern === '*') {\n // * matches exactly one path segment\n pi++;\n qi++;\n continue;\n }\n\n // Support intra-segment globs: *.txt, file.*, test-*-data, etc.\n if (pattern.includes('*')) {\n if (!matchSegmentGlob(pathParts[pi]!, pattern)) {\n return false;\n }\n pi++;\n qi++;\n continue;\n }\n\n if (pattern !== pathParts[pi]) {\n return false;\n }\n\n pi++;\n qi++;\n }\n\n // Skip trailing ** patterns\n while (qi < patternParts.length && patternParts[qi] === '**') {\n qi++;\n }\n\n return pi === pathParts.length && qi === patternParts.length;\n}\n\n/**\n * Checks if a path is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If rootDirectory is set, path must be within it\n * 2. If denied list exists, path must NOT match any denied pattern\n * 3. If allowed list exists, path must match at least one allowed pattern\n * 4. If neither list exists, path is allowed (constraints are optional)\n */\nexport function isPathAllowed(\n path: string,\n constraints: PathConstraints,\n): boolean {\n // 1. Root directory check (sandbox)\n if (constraints.rootDirectory) {\n if (!isWithinRoot(path, constraints.rootDirectory)) {\n return false;\n }\n }\n\n // 2. Denied list - any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchPathPattern(path, pattern)) {\n return false;\n }\n }\n }\n\n // 3. Allowed list - must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchPathPattern(path, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n\n/**\n * Matches a single path segment against a glob pattern containing *.\n * Examples: *.txt matches safe.txt, file.* matches file.js, *secret* matches my-secret-key\n */\nfunction matchSegmentGlob(segment: string, pattern: string): boolean {\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (pattern === '*') return true;\n\n if (startsWithStar && endsWithStar) {\n // *infix* — contains\n const infix = pattern.slice(1, -1);\n return segment.toLowerCase().includes(infix.toLowerCase());\n }\n if (startsWithStar) {\n // *suffix — ends with\n const suffix = pattern.slice(1);\n return segment.toLowerCase().endsWith(suffix.toLowerCase());\n }\n if (endsWithStar) {\n // prefix* — starts with\n const prefix = pattern.slice(0, -1);\n return segment.toLowerCase().startsWith(prefix.toLowerCase());\n }\n\n // Single * in middle: split on * and check prefix+suffix\n const starIdx = pattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = pattern.slice(0, starIdx);\n const suffix = pattern.slice(starIdx + 1);\n const seg = segment.toLowerCase();\n return seg.startsWith(prefix.toLowerCase()) && seg.endsWith(suffix.toLowerCase()) && seg.length >= prefix.length + suffix.length;\n }\n\n return segment === pattern;\n}\n\n/**\n * Known argument field names that typically contain file paths.\n */\nconst PATH_FIELDS = new Set([\n 'path',\n 'file',\n 'file_path',\n 'filepath',\n 'filename',\n 'directory',\n 'dir',\n 'folder',\n 'source',\n 'destination',\n 'dest',\n 'target',\n 'input',\n 'output',\n 'cwd',\n 'root',\n 'notebook_path',\n]);\n\n/**\n * Extracts path-like arguments from tool call arguments.\n * Uses multiple heuristics:\n * 1. Known path field names — always extract\n * 2. Strings containing / or \\ (original heuristic)\n * 3. Strings starting with . (.env, ./foo)\n */\nexport function extractPathArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n\n function addPath(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n paths.push(trimmed);\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n if (typeof value !== 'string') continue;\n\n // Known path field names\n if (PATH_FIELDS.has(key.toLowerCase())) {\n addPath(value);\n continue;\n }\n\n // Contains path separators\n if (value.includes('/') || value.includes('\\\\')) {\n addPath(value);\n continue;\n }\n\n // Starts with . (.env, ./config, ../secret)\n if (value.startsWith('.')) {\n addPath(value);\n continue;\n }\n }\n\n return paths;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype CommandConstraints = NonNullable<PolicyRule['commandConstraints']>;\n\n/**\n * Known argument field names that typically contain commands or shell-like content.\n * Used to extract commands from tool call arguments for constraint matching.\n */\nconst COMMAND_FIELDS = new Set([\n 'command',\n 'cmd',\n 'query',\n 'code',\n 'script',\n 'shell',\n 'exec',\n 'sql',\n 'expression',\n 'function',\n]);\n\n/**\n * Heuristic patterns that indicate a string value is likely a command/shell expression,\n * even when the field name is not in COMMAND_FIELDS.\n */\nconst COMMAND_HEURISTICS = [\n /^(sh|bash|cmd|powershell|zsh|fish)\\s+-c\\s+/i, // shell -c \"...\"\n /^(sudo|doas)\\s+/i, // privilege escalation\n /^\\w+\\s+&&\\s+/, // cmd1 && cmd2\n /^\\w+\\s*\\|\\s*\\w+/, // cmd1 | cmd2\n /^\\w+\\s*;\\s*\\w+/, // cmd1; cmd2\n /^(curl|wget|nc|ncat)\\s+/i, // network commands\n /^(rm|del|rmdir)\\s+/i, // destructive commands\n /^(cat|type|more|less)\\s+.*[/\\\\]/i, // file read commands with paths\n];\n\n/**\n * Extracts command-like arguments from tool call arguments.\n * Uses known field names plus heuristic detection for command-like strings\n * in any field, and recurses into nested objects/arrays.\n */\nexport function extractCommandArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const commands: string[] = [];\n const seen = new Set<string>();\n\n function addCommand(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n commands.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n // Known command field names — always extract\n if (COMMAND_FIELDS.has(key.toLowerCase())) {\n addCommand(value);\n return;\n }\n // Deep scan: heuristic detection of command-like strings\n for (const pattern of COMMAND_HEURISTICS) {\n if (pattern.test(value)) {\n addCommand(value);\n return;\n }\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n return commands;\n}\n\n/**\n * Glob-style command pattern matching.\n * Matches against the command string (first word) or full command line.\n *\n * Patterns:\n * 'ls' → exact match on command name\n * 'git*' → command starts with 'git'\n * '*sql*' → command contains 'sql'\n * 'rm -rf *' → full command line starts with 'rm -rf '\n */\nexport function matchCommandPattern(command: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedCommand = command.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedCommand) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedCommand.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedCommand.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedCommand.endsWith(suffix);\n }\n\n // Also try matching just the command name (first word)\n const commandName = normalizedCommand.split(/\\s+/)[0] ?? '';\n return commandName === normalizedPattern;\n}\n\n/**\n * Checks if a command is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, command must NOT match any denied pattern\n * 2. If allowed list exists, command must match at least one allowed pattern\n * 3. If neither list exists, command is allowed (constraints are optional)\n */\nexport function isCommandAllowed(\n command: string,\n constraints: CommandConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchCommandPattern(command, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchCommandPattern(command, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype FilenameConstraints = NonNullable<PolicyRule['filenameConstraints']>;\n\n/**\n * Extracts filenames from ALL string arguments (deep scan).\n * For path-like values, extracts the basename.\n * For non-path values, uses the string itself if it looks like a filename.\n */\nexport function extractFilenames(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const filenames: string[] = [];\n const seen = new Set<string>();\n\n function addFilename(name: string): void {\n const trimmed = name.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n filenames.push(trimmed);\n }\n }\n\n function scanValue(value: unknown): void {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (!trimmed) return;\n\n // Skip URLs\n if (/^https?:\\/\\//i.test(trimmed)) return;\n\n // If it contains a path separator, extract the basename\n if (trimmed.includes('/') || trimmed.includes('\\\\')) {\n const normalized = trimmed.replace(/\\\\/g, '/');\n const parts = normalized.split('/');\n const basename = parts[parts.length - 1];\n if (basename && basename.length > 0) {\n addFilename(basename);\n }\n return;\n }\n\n // Multi-word strings: split by whitespace and check each token\n // Catches: \"SELECT * FROM .env\", \"echo .env.local\", etc.\n if (trimmed.includes(' ')) {\n for (const token of trimmed.split(/\\s+/)) {\n if (token.includes('/') || token.includes('\\\\')) {\n const parts = token.replace(/\\\\/g, '/').split('/');\n const basename = parts[parts.length - 1];\n if (basename && looksLikeFilename(basename)) addFilename(basename);\n } else if (looksLikeFilename(token)) {\n addFilename(token);\n }\n }\n return;\n }\n\n // Single token: if it looks like a filename (has a dot extension or starts with dot)\n if (looksLikeFilename(trimmed)) {\n addFilename(trimmed);\n }\n return;\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const v of Object.values(value)) {\n scanValue(v);\n }\n }\n }\n\n for (const value of Object.values(args)) {\n scanValue(value);\n }\n\n return filenames;\n}\n\n/**\n * Checks if a string looks like a filename.\n * Matches: .env, .env.local, config.json, id_rsa, Makefile, etc.\n */\nfunction looksLikeFilename(s: string): boolean {\n // Starts with dot (.env, .gitignore, .env.local)\n if (s.startsWith('.')) return true;\n // Has a file extension (foo.txt, package.json)\n if (/\\.\\w+$/.test(s)) return true;\n // Known extensionless filenames\n const knownFiles = new Set([\n 'id_rsa', 'id_dsa', 'id_ecdsa', 'id_ed25519',\n 'authorized_keys', 'known_hosts',\n 'makefile', 'dockerfile', 'vagrantfile',\n 'gemfile', 'rakefile', 'procfile',\n ]);\n if (knownFiles.has(s.toLowerCase())) return true;\n return false;\n}\n\n/**\n * Glob-style filename pattern matching (case-insensitive).\n *\n * Patterns:\n * '.env' → exact match\n * '*.pem' → ends with .pem\n * '.env.*' → starts with .env.\n * '*secret*' → contains \"secret\"\n */\nexport function matchFilenamePattern(filename: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedFilename = filename.toLowerCase();\n const normalizedPattern = pattern.toLowerCase();\n\n if (normalizedFilename === normalizedPattern) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedFilename.includes(infix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedFilename.endsWith(suffix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedFilename.startsWith(prefix);\n }\n\n // Single * in middle: .env.* → split on * and check prefix+suffix\n const starIdx = normalizedPattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = normalizedPattern.slice(0, starIdx);\n const suffix = normalizedPattern.slice(starIdx + 1);\n return (\n normalizedFilename.startsWith(prefix) &&\n normalizedFilename.endsWith(suffix) &&\n normalizedFilename.length >= prefix.length + suffix.length\n );\n }\n\n return false;\n}\n\n/**\n * Checks if a filename is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, filename must NOT match any denied pattern\n * 2. If allowed list exists, filename must match at least one allowed pattern\n * 3. If neither list exists, filename is allowed\n */\nexport function isFilenameAllowed(\n filename: string,\n constraints: FilenameConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchFilenamePattern(filename, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchFilenamePattern(filename, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype UrlConstraints = NonNullable<PolicyRule['urlConstraints']>;\n\n/**\n * Known argument field names that typically contain URLs.\n */\nconst URL_FIELDS = new Set([\n 'url',\n 'href',\n 'uri',\n 'endpoint',\n 'link',\n 'src',\n 'source',\n 'target',\n 'redirect',\n 'callback',\n 'webhook',\n]);\n\n/**\n * Extracts URL arguments from tool call arguments.\n * Scans ALL string values — not just known field names.\n * Any string containing http:// or https:// is treated as a URL.\n */\nexport function extractUrlArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const urls: string[] = [];\n const seen = new Set<string>();\n\n function addUrl(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n urls.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n const lower = key.toLowerCase();\n // Known URL fields — always extract\n if (URL_FIELDS.has(lower)) {\n addUrl(value);\n return;\n }\n // Deep scan: any string containing a URL protocol\n if (/https?:\\/\\//i.test(value)) {\n addUrl(value);\n return;\n }\n // Bare domain patterns (e.g. \"instagram.com\", \"foo.onion\")\n if (/^[a-zA-Z0-9]([a-zA-Z0-9-]*\\.)+[a-zA-Z]{2,}(\\/.*)?$/.test(value)) {\n addUrl(value);\n return;\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n return urls;\n}\n\n/**\n * Glob-style URL pattern matching.\n * Normalizes both URL and pattern to lowercase for comparison.\n *\n * Patterns:\n * '*instagram.com*' → URL contains instagram.com\n * 'https://api.example.com/*' → URL starts with prefix\n * '*.onion' → URL ends with .onion\n * '*' → matches everything\n */\nexport function matchUrlPattern(url: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedUrl = url.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedUrl) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedUrl.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedUrl.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedUrl.endsWith(suffix);\n }\n\n return false;\n}\n\n/**\n * Checks if a URL is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, URL must NOT match any denied pattern\n * 2. If allowed list exists, URL must match at least one allowed pattern\n * 3. If neither list exists, URL is allowed\n */\nexport function isUrlAllowed(\n url: string,\n constraints: UrlConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchUrlPattern(url, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchUrlPattern(url, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule, ExecutionRequest } from '@solongate/core';\nimport { TrustLevel } from '@solongate/core';\nimport { isPathAllowed, extractPathArguments } from './path-matcher.js';\nimport { isCommandAllowed, extractCommandArguments } from './command-matcher.js';\nimport { isFilenameAllowed, extractFilenames } from './filename-matcher.js';\nimport { isUrlAllowed, extractUrlArguments } from './url-matcher.js';\n\n/**\n * Pure function: determines if a policy rule matches an execution request.\n * No side effects. No I/O. Fully deterministic.\n */\nexport function ruleMatchesRequest(\n rule: PolicyRule,\n request: ExecutionRequest,\n): boolean {\n if (!rule.enabled) return false;\n if (rule.permission && rule.permission !== request.requiredPermission) return false;\n if (!toolPatternMatches(rule.toolPattern, request.toolName)) return false;\n if (!trustLevelMeetsMinimum(request.context.trustLevel, rule.minimumTrustLevel)) {\n return false;\n }\n if (rule.argumentConstraints) {\n if (!argumentConstraintsMatch(rule.argumentConstraints, request.arguments)) {\n return false;\n }\n }\n if (rule.pathConstraints) {\n const satisfied = pathConstraintsMatch(rule.pathConstraints, request.arguments);\n // For DENY rules: match when constraints are VIOLATED (path is dangerous)\n // For ALLOW rules: match when constraints are SATISFIED (path is safe)\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // path is safe → don't deny\n } else {\n if (!satisfied) return false; // path is dangerous → don't allow\n }\n }\n if (rule.commandConstraints) {\n const satisfied = commandConstraintsMatch(rule.commandConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false;\n } else {\n if (!satisfied) return false;\n }\n }\n if (rule.filenameConstraints) {\n const satisfied = filenameConstraintsMatch(rule.filenameConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // filename is safe → don't deny\n } else {\n if (!satisfied) return false; // filename is dangerous → don't allow\n }\n }\n if (rule.urlConstraints) {\n const satisfied = urlConstraintsMatch(rule.urlConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // URL is safe → don't deny\n } else {\n if (!satisfied) return false; // URL is dangerous → don't allow\n }\n }\n return true;\n}\n\n/**\n * Glob-style tool name pattern matching.\n * Supports:\n * '*' → match all\n * 'prefix*' → starts with prefix\n * '*suffix' → ends with suffix\n * '*infix*' → contains infix\n * Does NOT support regex (ReDoS prevention).\n */\nexport function toolPatternMatches(pattern: string, toolName: string): boolean {\n if (pattern === '*') return true;\n\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n // *infix* → contains\n const infix = pattern.slice(1, -1);\n return infix.length > 0 && toolName.includes(infix);\n }\n if (endsWithStar) {\n // prefix* → starts with\n const prefix = pattern.slice(0, -1);\n return toolName.startsWith(prefix);\n }\n if (startsWithStar) {\n // *suffix → ends with\n const suffix = pattern.slice(1);\n return toolName.endsWith(suffix);\n }\n\n return pattern === toolName;\n}\n\nconst TRUST_LEVEL_ORDER: Record<string, number> = {\n [TrustLevel.UNTRUSTED]: 0,\n [TrustLevel.VERIFIED]: 1,\n [TrustLevel.TRUSTED]: 2,\n};\n\nexport function trustLevelMeetsMinimum(\n actual: TrustLevel,\n minimum: TrustLevel,\n): boolean {\n return (TRUST_LEVEL_ORDER[actual] ?? -1) >= (TRUST_LEVEL_ORDER[minimum] ?? Infinity);\n}\n\n/**\n * Condition operators for argument constraints.\n * When constraint value is a plain string → exact match (or '*' for any).\n * When constraint value is an object → operator-based matching:\n * { $contains: \"str\" } — value includes substring\n * { $notContains: \"str\" } — value does NOT include substring\n * { $startsWith: \"str\" } — value starts with prefix\n * { $endsWith: \"str\" } — value ends with suffix\n * { $in: [\"a\",\"b\"] } — value is one of the listed values\n * { $notIn: [\"a\",\"b\"] } — value is NOT one of the listed values\n * { $gt: 5 } — numeric greater than\n * { $lt: 5 } — numeric less than\n * { $gte: 5 } — numeric greater than or equal\n * { $lte: 5 } — numeric less than or equal\n */\nfunction argumentConstraintsMatch(\n constraints: Record<string, unknown>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n for (const [key, constraint] of Object.entries(constraints)) {\n if (!(key in args)) return false;\n const argValue = args[key];\n\n // Plain string: exact match (backward compatible)\n if (typeof constraint === 'string') {\n if (constraint === '*') continue;\n if (typeof argValue === 'string') {\n if (argValue !== constraint) return false;\n } else {\n return false;\n }\n continue;\n }\n\n // Object with operators\n if (typeof constraint === 'object' && constraint !== null && !Array.isArray(constraint)) {\n const ops = constraint as Record<string, unknown>;\n const strValue = typeof argValue === 'string' ? argValue : undefined;\n const numValue = typeof argValue === 'number' ? argValue : undefined;\n\n if ('$contains' in ops && typeof ops.$contains === 'string') {\n if (!strValue || !strValue.includes(ops.$contains)) return false;\n }\n if ('$notContains' in ops && typeof ops.$notContains === 'string') {\n if (strValue && strValue.includes(ops.$notContains)) return false;\n }\n if ('$startsWith' in ops && typeof ops.$startsWith === 'string') {\n if (!strValue || !strValue.startsWith(ops.$startsWith)) return false;\n }\n if ('$endsWith' in ops && typeof ops.$endsWith === 'string') {\n if (!strValue || !strValue.endsWith(ops.$endsWith)) return false;\n }\n if ('$in' in ops && Array.isArray(ops.$in)) {\n if (!ops.$in.includes(argValue)) return false;\n }\n if ('$notIn' in ops && Array.isArray(ops.$notIn)) {\n if (ops.$notIn.includes(argValue)) return false;\n }\n if ('$gt' in ops && typeof ops.$gt === 'number') {\n if (numValue === undefined || numValue <= ops.$gt) return false;\n }\n if ('$lt' in ops && typeof ops.$lt === 'number') {\n if (numValue === undefined || numValue >= ops.$lt) return false;\n }\n if ('$gte' in ops && typeof ops.$gte === 'number') {\n if (numValue === undefined || numValue < ops.$gte) return false;\n }\n if ('$lte' in ops && typeof ops.$lte === 'number') {\n if (numValue === undefined || numValue > ops.$lte) return false;\n }\n\n continue;\n }\n }\n return true;\n}\n\nfunction pathConstraintsMatch(\n constraints: NonNullable<PolicyRule['pathConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const paths = extractPathArguments(args);\n\n // If no path arguments found, constraints don't apply\n if (paths.length === 0) return true;\n\n // ALL path arguments must satisfy constraints\n return paths.every((path) => isPathAllowed(path, constraints));\n}\n\nfunction commandConstraintsMatch(\n constraints: NonNullable<PolicyRule['commandConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const commands = extractCommandArguments(args);\n\n // If no command arguments found, constraints don't apply\n if (commands.length === 0) return true;\n\n // ALL command arguments must satisfy constraints\n return commands.every((cmd) => isCommandAllowed(cmd, constraints));\n}\n\nfunction filenameConstraintsMatch(\n constraints: NonNullable<PolicyRule['filenameConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const filenames = extractFilenames(args);\n\n // If no filename arguments found, constraints don't apply\n if (filenames.length === 0) return true;\n\n // ALL filenames must satisfy constraints\n return filenames.every((name) => isFilenameAllowed(name, constraints));\n}\n\nfunction urlConstraintsMatch(\n constraints: NonNullable<PolicyRule['urlConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const urls = extractUrlArguments(args);\n\n // If no URL arguments found, constraints don't apply\n if (urls.length === 0) return true;\n\n // ALL URLs must satisfy constraints\n return urls.every((url) => isUrlAllowed(url, constraints));\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n PolicyEffect,\n} from '@solongate/core';\nimport { DEFAULT_POLICY_EFFECT } from '@solongate/core';\nimport { ruleMatchesRequest } from './matcher.js';\n\n/**\n * Evaluates a policy set against an execution request.\n *\n * Pure function: no side effects, no I/O, fully deterministic.\n *\n * Algorithm:\n * 1. Sort rules by priority (ascending - lower number = higher priority)\n * 2. Find the first matching rule\n * 3. If a rule matches, return its effect\n * 4. If no rule matches, return DENY (default-deny)\n */\nexport function evaluatePolicy(\n policySet: PolicySet,\n request: ExecutionRequest,\n): PolicyDecision {\n const startTime = performance.now();\n\n const sortedRules = [...policySet.rules].sort(\n (a, b) => a.priority - b.priority,\n );\n\n for (const rule of sortedRules) {\n if (ruleMatchesRequest(rule, request)) {\n const endTime = performance.now();\n return {\n effect: rule.effect,\n matchedRule: rule,\n reason: `Matched rule \"${rule.id}\": ${rule.description}`,\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n };\n }\n }\n\n const endTime = performance.now();\n return {\n effect: DEFAULT_POLICY_EFFECT as PolicyEffect,\n matchedRule: null,\n reason: 'No matching policy rule found. Default action: DENY.',\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n metadata: {\n evaluatedRules: sortedRules.length,\n ruleIds: sortedRules.map((r) => r.id),\n requestContext: {\n tool: request.toolName,\n arguments: Object.keys(request.arguments ?? {}),\n },\n },\n };\n}\n","import { PolicyRuleSchema, PolicySetSchema } from '@solongate/core';\nimport {\n MAX_RULES_PER_POLICY_SET,\n UNSAFE_CONFIGURATION_WARNINGS,\n} from '@solongate/core';\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly errors: readonly string[];\n readonly warnings: readonly string[];\n}\n\nexport function validatePolicyRule(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicyRuleSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const rule = result.data;\n\n if (rule.toolPattern === '*' && rule.effect === 'ALLOW') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW);\n }\n\n if (rule.minimumTrustLevel === 'TRUSTED') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.TRUSTED_LEVEL_EXTERNAL);\n }\n\n if (!rule.permission || rule.permission === 'EXECUTE') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW);\n }\n\n return { valid: true, errors, warnings };\n}\n\nexport function validatePolicySet(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicySetSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const policySet = result.data;\n\n if (policySet.rules.length > MAX_RULES_PER_POLICY_SET) {\n errors.push(\n `Policy set exceeds maximum of ${MAX_RULES_PER_POLICY_SET} rules`,\n );\n }\n\n const ruleIds = new Set<string>();\n for (const rule of policySet.rules) {\n if (ruleIds.has(rule.id)) {\n errors.push(`Duplicate rule ID: \"${rule.id}\"`);\n }\n ruleIds.add(rule.id);\n }\n\n for (const rule of policySet.rules) {\n const ruleResult = validatePolicyRule(rule);\n warnings.push(...ruleResult.warnings);\n }\n\n const hasDenyRule = policySet.rules.some((r) => r.effect === 'DENY');\n if (!hasDenyRule && policySet.rules.length > 0) {\n warnings.push(\n 'Policy set contains only ALLOW rules. The default-deny fallback is the only protection.',\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import type { PolicyRule, PolicySet } from '@solongate/core';\nimport { UNSAFE_CONFIGURATION_WARNINGS } from '@solongate/core';\n\nexport interface SecurityWarning {\n readonly level: 'WARNING' | 'CRITICAL';\n readonly code: string;\n readonly message: string;\n readonly ruleId?: string;\n readonly recommendation: string;\n}\n\n/** Analyzes a policy set and returns security warnings. Pure function. */\nexport function analyzeSecurityWarnings(\n policySet: PolicySet,\n): readonly SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n for (const rule of policySet.rules) {\n warnings.push(...analyzeRuleWarnings(rule));\n }\n\n const allowRules = policySet.rules.filter(\n (r) => r.effect === 'ALLOW' && r.enabled,\n );\n const wildcardAllows = allowRules.filter((r) => r.toolPattern === '*');\n\n if (wildcardAllows.length > 0) {\n warnings.push({\n level: 'CRITICAL',\n code: 'WILDCARD_ALLOW',\n message: UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW,\n recommendation:\n 'Replace wildcard ALLOW rules with specific tool patterns.',\n });\n }\n\n return warnings;\n}\n\nfunction analyzeRuleWarnings(rule: PolicyRule): SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n if (rule.effect === 'ALLOW' && rule.minimumTrustLevel === 'UNTRUSTED') {\n warnings.push({\n level: 'CRITICAL',\n code: 'ALLOW_UNTRUSTED',\n message: `Rule \"${rule.id}\" allows execution for UNTRUSTED requests. Unverified LLM requests can execute tools.`,\n ruleId: rule.id,\n recommendation:\n 'Set minimumTrustLevel to VERIFIED or higher for ALLOW rules.',\n });\n }\n\n if (rule.effect === 'ALLOW' && (!rule.permission || rule.permission === 'EXECUTE')) {\n warnings.push({\n level: 'WARNING',\n code: 'ALLOW_EXECUTE',\n message: UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW,\n ruleId: rule.id,\n recommendation:\n 'Ensure EXECUTE permissions are intentional and scoped to specific tools.',\n });\n }\n\n return warnings;\n}\n","import type { PolicySet } from '@solongate/core';\nimport { PolicyEffect, Permission, TrustLevel } from '@solongate/core';\n\n/**\n * Creates the default \"deny all\" policy set.\n * This is the starting policy for any new SolonGate deployment.\n */\nexport function createDefaultDenyPolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'default-deny',\n name: 'Default Deny All',\n description:\n 'Denies all tool executions. Add explicit ALLOW rules to grant access to specific tools.',\n version: 1,\n rules: [\n {\n id: 'deny-all-execute',\n description: 'Explicitly deny all tool executions',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-write',\n description: 'Explicitly deny all write operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-read',\n description: 'Explicitly deny all read operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a permissive \"allow all\" policy set.\n * Allows all tool executions — useful for development or when\n * using SolonGate only for monitoring and audit logging.\n */\nexport function createPermissivePolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'permissive',\n name: 'Permissive (Allow All)',\n description: 'Allows all tool executions. SolonGate still provides input validation, rate limiting, and audit logging.',\n version: 1,\n rules: [\n {\n id: 'allow-all-execute',\n description: 'Allow all tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-read',\n description: 'Allow all read operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-write',\n description: 'Allow all write operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a read-only policy set for a specific tool pattern.\n * Allows reads for VERIFIED requests only.\n */\nexport function createReadOnlyPolicySet(toolPattern: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `read-only-${toolPattern}`,\n name: `Read-Only: ${toolPattern}`,\n description: `Allows read access to tools matching \"${toolPattern}\". Denies write and execute.`,\n version: 1,\n rules: [\n {\n id: `allow-read-${toolPattern}`,\n description: `Allow read access to ${toolPattern}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern,\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.VERIFIED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a sandboxed policy set for a given root directory.\n * Allows file operations within rootDir, blocks dangerous commands,\n * denies access to sensitive files.\n */\nexport function createSandboxedPolicySet(rootDir: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `sandbox-${rootDir.replace(/\\//g, '-')}`,\n name: `Sandbox: ${rootDir}`,\n description: `Allows operations within ${rootDir}. Blocks dangerous commands and sensitive file access.`,\n version: 1,\n rules: [\n {\n id: 'deny-dangerous-commands',\n description: 'Block dangerous shell commands',\n effect: PolicyEffect.DENY,\n priority: 50,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n commandConstraints: {\n denied: [\n 'rm -rf *', 'rm -r /*', 'mkfs*', 'dd if=*',\n 'curl*|*bash*', 'wget*|*sh*',\n 'shutdown*', 'reboot*', 'chmod*777*',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-sensitive-paths',\n description: 'Block access to sensitive files',\n effect: PolicyEffect.DENY,\n priority: 51,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n denied: [\n '**/.env*', '**/.ssh/**', '**/.aws/**',\n '**/credentials*', '**/*.pem', '**/*.key',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-sandboxed-files',\n description: `Allow file operations within ${rootDir}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern: 'file_*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n rootDirectory: rootDir,\n allowed: [`${rootDir}/**`],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-execute',\n description: 'Allow all other tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n} from '@solongate/core';\nimport { POLICY_EVALUATION_TIMEOUT_MS } from '@solongate/core';\nimport { evaluatePolicy } from './evaluator.js';\nimport { validatePolicySet, type ValidationResult } from './validator.js';\nimport { analyzeSecurityWarnings, type SecurityWarning } from './warnings.js';\nimport { createDefaultDenyPolicySet } from './defaults.js';\nimport { PolicyStore, type PolicyVersion } from './policy-store.js';\n\n/**\n * PolicyEngine is the primary interface for policy evaluation.\n *\n * Wraps pure evaluation functions with:\n * - Policy set management (load, validate, swap)\n * - Timeout protection\n * - Warning aggregation\n * - Optional versioned policy store\n */\nexport class PolicyEngine {\n private policySet: PolicySet;\n private readonly timeoutMs: number;\n private readonly store: PolicyStore | null;\n\n constructor(options?: {\n policySet?: PolicySet;\n timeoutMs?: number;\n store?: PolicyStore;\n }) {\n this.policySet = options?.policySet ?? createDefaultDenyPolicySet();\n this.timeoutMs = options?.timeoutMs ?? POLICY_EVALUATION_TIMEOUT_MS;\n this.store = options?.store ?? null;\n }\n\n /**\n * Evaluates an execution request against the current policy set.\n * Never throws for denials - denial is a normal outcome, not an error.\n */\n evaluate(request: ExecutionRequest): PolicyDecision {\n const startTime = performance.now();\n const decision = evaluatePolicy(this.policySet, request);\n const elapsed = performance.now() - startTime;\n\n if (elapsed > this.timeoutMs) {\n console.warn(\n `[SolonGate] Policy evaluation took ${elapsed.toFixed(1)}ms ` +\n `(limit: ${this.timeoutMs}ms) for tool \"${request.toolName}\"`,\n );\n }\n\n return decision;\n }\n\n /**\n * Loads a new policy set, replacing the current one.\n * Validates before accepting. Auto-saves version when store is present.\n */\n loadPolicySet(\n policySet: PolicySet,\n options?: { reason?: string; createdBy?: string },\n ): ValidationResult {\n const validation = validatePolicySet(policySet);\n if (!validation.valid) {\n return validation;\n }\n this.policySet = policySet;\n\n if (this.store) {\n this.store.saveVersion(\n policySet,\n options?.reason ?? 'Policy updated',\n options?.createdBy ?? 'system',\n );\n }\n\n return validation;\n }\n\n /**\n * Rolls back to a previous policy version.\n * Only available when a PolicyStore is configured.\n */\n rollback(version: number): PolicyVersion {\n if (!this.store) {\n throw new Error('PolicyStore not configured - cannot rollback');\n }\n\n const policyVersion = this.store.rollback(this.policySet.id, version);\n this.policySet = policyVersion.policySet;\n return policyVersion;\n }\n\n getPolicySet(): Readonly<PolicySet> {\n return this.policySet;\n }\n\n getSecurityWarnings(): readonly SecurityWarning[] {\n return analyzeSecurityWarnings(this.policySet);\n }\n\n getStore(): PolicyStore | null {\n return this.store;\n }\n\n reset(): void {\n this.policySet = createDefaultDenyPolicySet();\n }\n}\n","import type { PolicySet, PolicyRule } from '@solongate/core';\nimport { createHash } from 'node:crypto';\n\n/**\n * A versioned snapshot of a policy set.\n * Immutable once created - modifications create new versions.\n */\nexport interface PolicyVersion {\n readonly version: number;\n readonly policySet: PolicySet;\n readonly hash: string;\n readonly reason: string;\n readonly createdBy: string;\n readonly createdAt: string;\n}\n\n/**\n * Diff between two policy versions.\n */\nexport interface PolicyDiff {\n readonly added: readonly PolicyRule[];\n readonly removed: readonly PolicyRule[];\n readonly modified: readonly { readonly old: PolicyRule; readonly new: PolicyRule }[];\n}\n\n/**\n * In-memory versioned policy store.\n * Stores complete history of policy changes with cryptographic hashes.\n *\n * Security properties:\n * - Immutable versions: once saved, a version cannot be modified\n * - Hash chain: each version includes SHA256 of the policy content\n * - Full history: no version is ever deleted\n */\nexport class PolicyStore {\n private readonly versions = new Map<string, PolicyVersion[]>();\n\n /**\n * Saves a new version of a policy set.\n * The version number auto-increments.\n */\n saveVersion(\n policySet: PolicySet,\n reason: string,\n createdBy: string,\n ): PolicyVersion {\n const id = policySet.id;\n const history = this.versions.get(id) ?? [];\n\n const latestVersion = history.length > 0 ? history[history.length - 1]!.version : 0;\n\n const version: PolicyVersion = {\n version: latestVersion + 1,\n policySet: Object.freeze({ ...policySet }),\n hash: this.computeHash(policySet),\n reason,\n createdBy,\n createdAt: new Date().toISOString(),\n };\n\n const newHistory = [...history, version];\n this.versions.set(id, newHistory);\n\n return version;\n }\n\n /**\n * Gets a specific version of a policy set.\n */\n getVersion(id: string, version: number): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history) return null;\n return history.find((v) => v.version === version) ?? null;\n }\n\n /**\n * Gets the latest version of a policy set.\n */\n getLatest(id: string): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history || history.length === 0) return null;\n return history[history.length - 1]!;\n }\n\n /**\n * Gets the full version history of a policy set.\n */\n getHistory(id: string): readonly PolicyVersion[] {\n return this.versions.get(id) ?? [];\n }\n\n /**\n * Rolls back to a previous version by creating a new version\n * with the same content as the target version.\n */\n rollback(id: string, toVersion: number): PolicyVersion {\n const target = this.getVersion(id, toVersion);\n if (!target) {\n throw new Error(`Version ${toVersion} not found for policy \"${id}\"`);\n }\n\n return this.saveVersion(\n target.policySet,\n `Rollback to version ${toVersion}`,\n 'system',\n );\n }\n\n /**\n * Computes a diff between two policy versions.\n */\n diff(v1: PolicyVersion, v2: PolicyVersion): PolicyDiff {\n const oldRulesMap = new Map(v1.policySet.rules.map((r) => [r.id, r]));\n const newRulesMap = new Map(v2.policySet.rules.map((r) => [r.id, r]));\n\n const added: PolicyRule[] = [];\n const removed: PolicyRule[] = [];\n const modified: { old: PolicyRule; new: PolicyRule }[] = [];\n\n // Find added and modified rules\n for (const [id, newRule] of newRulesMap) {\n const oldRule = oldRulesMap.get(id);\n if (!oldRule) {\n added.push(newRule);\n } else if (JSON.stringify(oldRule) !== JSON.stringify(newRule)) {\n modified.push({ old: oldRule, new: newRule });\n }\n }\n\n // Find removed rules\n for (const [id, oldRule] of oldRulesMap) {\n if (!newRulesMap.has(id)) {\n removed.push(oldRule);\n }\n }\n\n return { added, removed, modified };\n }\n\n /**\n * Computes SHA256 hash of a policy set for integrity verification.\n */\n computeHash(policySet: PolicySet): string {\n const serialized = JSON.stringify(policySet, Object.keys(policySet).sort());\n return createHash('sha256').update(serialized).digest('hex');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/path-matcher.ts","../src/command-matcher.ts","../src/filename-matcher.ts","../src/url-matcher.ts","../src/matcher.ts","../src/evaluator.ts","../src/validator.ts","../src/warnings.ts","../src/defaults.ts","../src/engine.ts","../src/policy-store.ts"],"names":["endTime","UNSAFE_CONFIGURATION_WARNINGS","TrustLevel"],"mappings":"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","file":"index.js","sourcesContent":["import type { PolicyRule } from '@solongate/core';\n\ntype PathConstraints = NonNullable<PolicyRule['pathConstraints']>;\n\n/**\n * Normalizes a file path for consistent matching.\n * Resolves . and .. segments, normalizes separators.\n */\nexport function normalizePath(path: string): string {\n // Normalize separators to forward slash\n let normalized = path.replace(/\\\\/g, '/');\n\n // Remove trailing slash (except for root)\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n // Resolve . and .. segments\n const parts = normalized.split('/');\n const resolved: string[] = [];\n\n for (const part of parts) {\n if (part === '.' || part === '') {\n if (resolved.length === 0) resolved.push('');\n continue;\n }\n if (part === '..') {\n if (resolved.length > 1) {\n resolved.pop();\n }\n continue;\n }\n resolved.push(part);\n }\n\n return resolved.join('/') || '/';\n}\n\n/**\n * Checks if a path is within a root directory (sandbox boundary).\n * Prevents escaping via .., symlinks, etc.\n */\nexport function isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedRoot = normalizePath(root);\n\n // Path must start with root\n if (normalizedPath === normalizedRoot) return true;\n return normalizedPath.startsWith(normalizedRoot + '/');\n}\n\n/**\n * Glob-style path pattern matching.\n * Supports:\n * - * matches any single path segment (not /)\n * - ** matches any number of path segments\n * - Exact match\n *\n * Does NOT support regex (ReDoS prevention).\n */\nexport function matchPathPattern(path: string, pattern: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedPattern = normalizePath(pattern);\n\n if (normalizedPattern === '*') return true;\n if (normalizedPattern === normalizedPath) return true;\n\n const patternParts = normalizedPattern.split('/');\n const pathParts = normalizedPath.split('/');\n\n return matchParts(pathParts, 0, patternParts, 0);\n}\n\nfunction matchParts(\n pathParts: string[],\n pi: number,\n patternParts: string[],\n qi: number,\n): boolean {\n while (pi < pathParts.length && qi < patternParts.length) {\n const pattern = patternParts[qi]!;\n\n if (pattern === '**') {\n // ** can match zero or more path segments\n if (qi === patternParts.length - 1) return true;\n\n // Try matching ** against 0, 1, 2, ... path segments\n for (let i = pi; i <= pathParts.length; i++) {\n if (matchParts(pathParts, i, patternParts, qi + 1)) {\n return true;\n }\n }\n return false;\n }\n\n if (pattern === '*') {\n // * matches exactly one path segment\n pi++;\n qi++;\n continue;\n }\n\n // Support intra-segment globs: *.txt, file.*, test-*-data, etc.\n if (pattern.includes('*')) {\n if (!matchSegmentGlob(pathParts[pi]!, pattern)) {\n return false;\n }\n pi++;\n qi++;\n continue;\n }\n\n if (pattern !== pathParts[pi]) {\n return false;\n }\n\n pi++;\n qi++;\n }\n\n // Skip trailing ** patterns\n while (qi < patternParts.length && patternParts[qi] === '**') {\n qi++;\n }\n\n return pi === pathParts.length && qi === patternParts.length;\n}\n\n/**\n * Checks if a path is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If rootDirectory is set, path must be within it\n * 2. If denied list exists, path must NOT match any denied pattern\n * 3. If allowed list exists, path must match at least one allowed pattern\n * 4. If neither list exists, path is allowed (constraints are optional)\n */\nexport function isPathAllowed(\n path: string,\n constraints: PathConstraints,\n): boolean {\n // 1. Root directory check (sandbox)\n if (constraints.rootDirectory) {\n if (!isWithinRoot(path, constraints.rootDirectory)) {\n return false;\n }\n }\n\n // 2. Denied list - any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchPathPattern(path, pattern)) {\n return false;\n }\n }\n }\n\n // 3. Allowed list - must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchPathPattern(path, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n\n/**\n * Matches a single path segment against a glob pattern containing *.\n * Examples: *.txt matches safe.txt, file.* matches file.js, *secret* matches my-secret-key\n */\nfunction matchSegmentGlob(segment: string, pattern: string): boolean {\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (pattern === '*') return true;\n\n if (startsWithStar && endsWithStar) {\n // *infix* — contains\n const infix = pattern.slice(1, -1);\n return segment.toLowerCase().includes(infix.toLowerCase());\n }\n if (startsWithStar) {\n // *suffix — ends with\n const suffix = pattern.slice(1);\n return segment.toLowerCase().endsWith(suffix.toLowerCase());\n }\n if (endsWithStar) {\n // prefix* — starts with\n const prefix = pattern.slice(0, -1);\n return segment.toLowerCase().startsWith(prefix.toLowerCase());\n }\n\n // Single * in middle: split on * and check prefix+suffix\n const starIdx = pattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = pattern.slice(0, starIdx);\n const suffix = pattern.slice(starIdx + 1);\n const seg = segment.toLowerCase();\n return seg.startsWith(prefix.toLowerCase()) && seg.endsWith(suffix.toLowerCase()) && seg.length >= prefix.length + suffix.length;\n }\n\n return segment === pattern;\n}\n\n/**\n * Known argument field names that typically contain file paths.\n */\nconst PATH_FIELDS = new Set([\n 'path',\n 'file',\n 'file_path',\n 'filepath',\n 'filename',\n 'directory',\n 'dir',\n 'folder',\n 'source',\n 'destination',\n 'dest',\n 'target',\n 'input',\n 'output',\n 'cwd',\n 'root',\n 'notebook_path',\n]);\n\n/**\n * Extracts path-like arguments from tool call arguments.\n * Uses multiple heuristics:\n * 1. Known path field names — always extract\n * 2. Strings containing / or \\ (original heuristic)\n * 3. Strings starting with . (.env, ./foo)\n */\nexport function extractPathArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n\n function addPath(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n paths.push(trimmed);\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n if (typeof value !== 'string') continue;\n\n // Known path field names\n if (PATH_FIELDS.has(key.toLowerCase())) {\n addPath(value);\n continue;\n }\n\n // Contains path separators\n if (value.includes('/') || value.includes('\\\\')) {\n addPath(value);\n continue;\n }\n\n // Starts with . (.env, ./config, ../secret)\n if (value.startsWith('.')) {\n addPath(value);\n continue;\n }\n }\n\n return paths;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype CommandConstraints = NonNullable<PolicyRule['commandConstraints']>;\n\n/**\n * Known argument field names that typically contain commands or shell-like content.\n * Used to extract commands from tool call arguments for constraint matching.\n */\nconst COMMAND_FIELDS = new Set([\n 'command',\n 'cmd',\n 'query',\n 'code',\n 'script',\n 'shell',\n 'exec',\n 'sql',\n 'expression',\n 'function',\n]);\n\n/**\n * Heuristic patterns that indicate a string value is likely a command/shell expression,\n * even when the field name is not in COMMAND_FIELDS.\n */\nconst COMMAND_HEURISTICS = [\n /^(sh|bash|cmd|powershell|zsh|fish)\\s+-c\\s+/i, // shell -c \"...\"\n /^(sudo|doas)\\s+/i, // privilege escalation\n /^\\w+\\s+&&\\s+/, // cmd1 && cmd2\n /^\\w+\\s*\\|\\s*\\w+/, // cmd1 | cmd2\n /^\\w+\\s*;\\s*\\w+/, // cmd1; cmd2\n /^(curl|wget|nc|ncat)\\s+/i, // network commands\n /^(rm|del|rmdir)\\s+/i, // destructive commands\n /^(cat|type|more|less)\\s+.*[/\\\\]/i, // file read commands with paths\n /^(eval|source)\\s+/i, // eval/source wrappers\n /^(printenv|env|set)\\b/i, // environment variable leak\n /^(cat|head|tail|more|less|strings|xxd|od|hexdump|bat)\\s+/i, // file read commands\n];\n\n/**\n * Regex to match subshell wrapper patterns like `bash -c '...'`, `sh -c \"...\"`, `eval \"...\"`.\n * Extracts the inner command for recursive constraint checking.\n */\nconst SUBSHELL_WRAPPERS = [\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+-c\\s+['\"](.+?)['\"]\\s*$/i,\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+-c\\s+(.+)$/i,\n /^eval\\s+['\"](.+?)['\"]\\s*$/i,\n /^eval\\s+(.+)$/i,\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+<<\\s*['\"]?(\\w+)['\"]?\\n([\\s\\S]+?)\\n\\1$/i,\n];\n\n/**\n * Extracts inner commands from subshell wrappers (bash -c, eval, etc.)\n * Returns the original command plus any extracted inner commands.\n */\nexport function extractInnerCommands(command: string): string[] {\n const results = [command];\n const trimmed = command.trim();\n\n for (const pattern of SUBSHELL_WRAPPERS) {\n const match = trimmed.match(pattern);\n if (match) {\n // For heredoc pattern, inner command is in group 2\n const inner = (match[2] ?? match[1] ?? '').trim();\n if (inner) {\n results.push(inner);\n // Recurse: inner command might also be a wrapper\n const nested = extractInnerCommands(inner);\n for (const n of nested) {\n if (n !== inner) results.push(n);\n }\n }\n break;\n }\n }\n\n // Also handle string concatenation patterns that build commands:\n // variable=value && ... && command \"$variable\"\n // Look for the final command after the last && or ;\n const chainParts = trimmed.split(/\\s*(?:&&|;)\\s*/);\n if (chainParts.length > 1) {\n for (const part of chainParts) {\n const p = part.trim();\n if (p && p !== trimmed && !p.includes('=')) {\n results.push(p);\n }\n }\n }\n\n return [...new Set(results)];\n}\n\n/**\n * Extracts command-like arguments from tool call arguments.\n * Uses known field names plus heuristic detection for command-like strings\n * in any field, and recurses into nested objects/arrays.\n */\nexport function extractCommandArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const commands: string[] = [];\n const seen = new Set<string>();\n\n function addCommand(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n commands.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n // Known command field names — always extract\n if (COMMAND_FIELDS.has(key.toLowerCase())) {\n addCommand(value);\n return;\n }\n // Deep scan: heuristic detection of command-like strings\n for (const pattern of COMMAND_HEURISTICS) {\n if (pattern.test(value)) {\n addCommand(value);\n return;\n }\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n // Extract inner commands from subshell wrappers (bash -c, eval, etc.)\n const expanded: string[] = [];\n for (const cmd of commands) {\n for (const inner of extractInnerCommands(cmd)) {\n if (!seen.has(inner)) {\n seen.add(inner);\n expanded.push(inner);\n }\n }\n }\n commands.push(...expanded);\n\n return commands;\n}\n\n/**\n * Glob-style command pattern matching.\n * Matches against the command string (first word) or full command line.\n *\n * Patterns:\n * 'ls' → exact match on command name\n * 'git*' → command starts with 'git'\n * '*sql*' → command contains 'sql'\n * 'rm -rf *' → full command line starts with 'rm -rf '\n */\nexport function matchCommandPattern(command: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedCommand = command.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedCommand) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedCommand.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedCommand.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedCommand.endsWith(suffix);\n }\n\n // Also try matching just the command name (first word)\n const commandName = normalizedCommand.split(/\\s+/)[0] ?? '';\n return commandName === normalizedPattern;\n}\n\n/**\n * Checks if a command is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, command must NOT match any denied pattern\n * 2. If allowed list exists, command must match at least one allowed pattern\n * 3. If neither list exists, command is allowed (constraints are optional)\n */\nexport function isCommandAllowed(\n command: string,\n constraints: CommandConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchCommandPattern(command, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchCommandPattern(command, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype FilenameConstraints = NonNullable<PolicyRule['filenameConstraints']>;\n\n/**\n * Extracts filenames from ALL string arguments (deep scan).\n * For path-like values, extracts the basename.\n * For non-path values, uses the string itself if it looks like a filename.\n */\nexport function extractFilenames(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const filenames: string[] = [];\n const seen = new Set<string>();\n\n function addFilename(name: string): void {\n const trimmed = name.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n filenames.push(trimmed);\n }\n }\n\n function scanValue(value: unknown): void {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (!trimmed) return;\n\n // Skip URLs\n if (/^https?:\\/\\//i.test(trimmed)) return;\n\n // If it contains a path separator, extract the basename\n if (trimmed.includes('/') || trimmed.includes('\\\\')) {\n const normalized = trimmed.replace(/\\\\/g, '/');\n const parts = normalized.split('/');\n const basename = parts[parts.length - 1];\n if (basename && basename.length > 0) {\n addFilename(basename);\n }\n return;\n }\n\n // Multi-word strings: split by whitespace and check each token\n // Catches: \"SELECT * FROM .env\", \"echo .env.local\", \"bash -c 'cat .env'\", etc.\n if (trimmed.includes(' ')) {\n for (const rawToken of trimmed.split(/\\s+/)) {\n // Strip surrounding quotes and trailing punctuation from tokens\n const token = rawToken.replace(/^['\"`]+|['\"`]+$/g, '');\n if (!token) continue;\n if (token.includes('/') || token.includes('\\\\')) {\n const parts = token.replace(/\\\\/g, '/').split('/');\n const basename = parts[parts.length - 1];\n if (basename && looksLikeFilename(basename)) addFilename(basename);\n } else if (looksLikeFilename(token)) {\n addFilename(token);\n }\n // Expand shell glob wildcards that could match sensitive files\n // e.g., \"cred*\" could match \"credentials.json\", \"sec*\" → \"secrets.json\"\n if (token.includes('*') || token.includes('?')) {\n for (const expanded of expandSensitiveGlob(token)) {\n addFilename(expanded);\n }\n }\n }\n return;\n }\n\n // Single token: if it looks like a filename (has a dot extension or starts with dot)\n if (looksLikeFilename(trimmed)) {\n addFilename(trimmed);\n }\n return;\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const v of Object.values(value)) {\n scanValue(v);\n }\n }\n }\n\n for (const value of Object.values(args)) {\n scanValue(value);\n }\n\n return filenames;\n}\n\n/**\n * Known sensitive filenames that glob patterns in commands might target.\n * When a wildcard like \"cred*\" or \"sec*\" is used, we check if it could\n * match any of these sensitive files to prevent wildcard-based bypass.\n */\nconst SENSITIVE_FILENAMES = [\n '.env', '.env.local', '.env.production', '.env.development',\n 'credentials.json', 'secrets.json', 'secrets.yaml', 'secrets.yml',\n '.npmrc', '.pypirc', '.netrc',\n 'id_rsa', 'id_ed25519', 'id_ecdsa',\n 'policy.json', '.mcp.json', 'guard.mjs', 'audit.mjs',\n 'settings.json',\n];\n\n/**\n * Expands a glob-like pattern against known sensitive filenames.\n * Returns sensitive filenames that the glob would match.\n * e.g., \"cred*\" → [\"credentials.json\"], \"sec*\" → [\"secrets.json\", \"secrets.yaml\"]\n */\nfunction expandSensitiveGlob(pattern: string): string[] {\n const p = pattern.toLowerCase();\n const matches: string[] = [];\n\n for (const filename of SENSITIVE_FILENAMES) {\n const f = filename.toLowerCase();\n\n if (p === '*') {\n // Don't expand bare wildcard to everything\n continue;\n }\n\n const startsWithStar = p.startsWith('*');\n const endsWithStar = p.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = p.slice(1, -1);\n if (infix && f.includes(infix)) matches.push(filename);\n } else if (endsWithStar) {\n const prefix = p.slice(0, -1);\n if (f.startsWith(prefix)) matches.push(filename);\n } else if (startsWithStar) {\n const suffix = p.slice(1);\n if (f.endsWith(suffix)) matches.push(filename);\n } else if (p.includes('?')) {\n // Simple ? glob: replace ? with regex .\n const regex = new RegExp('^' + p.replace(/\\?/g, '.').replace(/\\*/g, '.*') + '$', 'i');\n if (regex.test(f)) matches.push(filename);\n }\n }\n\n return matches;\n}\n\n/**\n * Checks if a string looks like a filename.\n * Matches: .env, .env.local, config.json, id_rsa, Makefile, etc.\n */\nfunction looksLikeFilename(s: string): boolean {\n // Starts with dot (.env, .gitignore, .env.local)\n if (s.startsWith('.')) return true;\n // Has a file extension (foo.txt, package.json)\n if (/\\.\\w+$/.test(s)) return true;\n // Known extensionless filenames\n const knownFiles = new Set([\n 'id_rsa', 'id_dsa', 'id_ecdsa', 'id_ed25519',\n 'authorized_keys', 'known_hosts',\n 'makefile', 'dockerfile', 'vagrantfile',\n 'gemfile', 'rakefile', 'procfile',\n ]);\n if (knownFiles.has(s.toLowerCase())) return true;\n return false;\n}\n\n/**\n * Glob-style filename pattern matching (case-insensitive).\n *\n * Patterns:\n * '.env' → exact match\n * '*.pem' → ends with .pem\n * '.env.*' → starts with .env.\n * '*secret*' → contains \"secret\"\n */\nexport function matchFilenamePattern(filename: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedFilename = filename.toLowerCase();\n const normalizedPattern = pattern.toLowerCase();\n\n if (normalizedFilename === normalizedPattern) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedFilename.includes(infix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedFilename.endsWith(suffix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedFilename.startsWith(prefix);\n }\n\n // Single * in middle: .env.* → split on * and check prefix+suffix\n const starIdx = normalizedPattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = normalizedPattern.slice(0, starIdx);\n const suffix = normalizedPattern.slice(starIdx + 1);\n return (\n normalizedFilename.startsWith(prefix) &&\n normalizedFilename.endsWith(suffix) &&\n normalizedFilename.length >= prefix.length + suffix.length\n );\n }\n\n return false;\n}\n\n/**\n * Checks if a filename is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, filename must NOT match any denied pattern\n * 2. If allowed list exists, filename must match at least one allowed pattern\n * 3. If neither list exists, filename is allowed\n */\nexport function isFilenameAllowed(\n filename: string,\n constraints: FilenameConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchFilenamePattern(filename, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchFilenamePattern(filename, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype UrlConstraints = NonNullable<PolicyRule['urlConstraints']>;\n\n/**\n * Known argument field names that typically contain URLs.\n */\nconst URL_FIELDS = new Set([\n 'url',\n 'href',\n 'uri',\n 'endpoint',\n 'link',\n 'src',\n 'source',\n 'target',\n 'redirect',\n 'callback',\n 'webhook',\n]);\n\n/**\n * Extracts URL arguments from tool call arguments.\n * Scans ALL string values — not just known field names.\n * Any string containing http:// or https:// is treated as a URL.\n */\nexport function extractUrlArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const urls: string[] = [];\n const seen = new Set<string>();\n\n function addUrl(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n urls.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n const lower = key.toLowerCase();\n // Known URL fields — always extract\n if (URL_FIELDS.has(lower)) {\n addUrl(value);\n return;\n }\n // Deep scan: any string containing a URL protocol\n if (/https?:\\/\\//i.test(value)) {\n addUrl(value);\n return;\n }\n // Bare domain patterns (e.g. \"instagram.com\", \"foo.onion\")\n // Require known TLD suffix to avoid false positives on version strings like \"1.0.abc\"\n if (/^[a-zA-Z0-9]([a-zA-Z0-9-]*\\.)+(?:com|net|org|io|dev|app|co|me|info|biz|gov|edu|mil|onion|xyz|ai|cloud|sh|run|so|to|cc|tv|fm|am|gg|id)(\\/.*)?$/.test(value)) {\n addUrl(value);\n return;\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n return urls;\n}\n\n/**\n * Glob-style URL pattern matching.\n * Normalizes both URL and pattern to lowercase for comparison.\n *\n * Patterns:\n * '*instagram.com*' → URL contains instagram.com\n * 'https://api.example.com/*' → URL starts with prefix\n * '*.onion' → URL ends with .onion\n * '*' → matches everything\n */\nexport function matchUrlPattern(url: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedUrl = url.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedUrl) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedUrl.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedUrl.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedUrl.endsWith(suffix);\n }\n\n return false;\n}\n\n/**\n * Checks if a URL is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, URL must NOT match any denied pattern\n * 2. If allowed list exists, URL must match at least one allowed pattern\n * 3. If neither list exists, URL is allowed\n */\nexport function isUrlAllowed(\n url: string,\n constraints: UrlConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchUrlPattern(url, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchUrlPattern(url, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule, ExecutionRequest } from '@solongate/core';\nimport { TrustLevel } from '@solongate/core';\nimport { isPathAllowed, extractPathArguments } from './path-matcher.js';\nimport { isCommandAllowed, extractCommandArguments } from './command-matcher.js';\nimport { isFilenameAllowed, extractFilenames } from './filename-matcher.js';\nimport { isUrlAllowed, extractUrlArguments } from './url-matcher.js';\n\n/**\n * Pure function: determines if a policy rule matches an execution request.\n * No side effects. No I/O. Fully deterministic.\n */\nexport function ruleMatchesRequest(\n rule: PolicyRule,\n request: ExecutionRequest,\n): boolean {\n if (!rule.enabled) return false;\n if (rule.permission && rule.permission !== request.requiredPermission) return false;\n if (!toolPatternMatches(rule.toolPattern, request.toolName)) return false;\n if (!trustLevelMeetsMinimum(request.context.trustLevel, rule.minimumTrustLevel)) {\n return false;\n }\n if (rule.argumentConstraints) {\n if (!argumentConstraintsMatch(rule.argumentConstraints, request.arguments)) {\n return false;\n }\n }\n if (rule.pathConstraints) {\n const satisfied = pathConstraintsMatch(rule.pathConstraints, request.arguments);\n // For DENY rules: match when constraints are VIOLATED (path is dangerous)\n // For ALLOW rules: match when constraints are SATISFIED (path is safe)\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // path is safe → don't deny\n } else {\n if (!satisfied) return false; // path is dangerous → don't allow\n }\n }\n if (rule.commandConstraints) {\n const satisfied = commandConstraintsMatch(rule.commandConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false;\n } else {\n if (!satisfied) return false;\n }\n }\n if (rule.filenameConstraints) {\n const satisfied = filenameConstraintsMatch(rule.filenameConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // filename is safe → don't deny\n } else {\n if (!satisfied) return false; // filename is dangerous → don't allow\n }\n }\n if (rule.urlConstraints) {\n const satisfied = urlConstraintsMatch(rule.urlConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // URL is safe → don't deny\n } else {\n if (!satisfied) return false; // URL is dangerous → don't allow\n }\n }\n return true;\n}\n\n/**\n * Glob-style tool name pattern matching.\n * Supports:\n * '*' → match all\n * 'prefix*' → starts with prefix\n * '*suffix' → ends with suffix\n * '*infix*' → contains infix\n * Does NOT support regex (ReDoS prevention).\n */\nexport function toolPatternMatches(pattern: string, toolName: string): boolean {\n if (pattern === '*') return true;\n\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n // *infix* → contains\n const infix = pattern.slice(1, -1);\n return infix.length > 0 && toolName.includes(infix);\n }\n if (endsWithStar) {\n // prefix* → starts with\n const prefix = pattern.slice(0, -1);\n return toolName.startsWith(prefix);\n }\n if (startsWithStar) {\n // *suffix → ends with\n const suffix = pattern.slice(1);\n return toolName.endsWith(suffix);\n }\n\n return pattern === toolName;\n}\n\nconst TRUST_LEVEL_ORDER: Record<string, number> = {\n [TrustLevel.UNTRUSTED]: 0,\n [TrustLevel.VERIFIED]: 1,\n [TrustLevel.TRUSTED]: 2,\n};\n\nexport function trustLevelMeetsMinimum(\n actual: TrustLevel,\n minimum: TrustLevel,\n): boolean {\n return (TRUST_LEVEL_ORDER[actual] ?? -1) >= (TRUST_LEVEL_ORDER[minimum] ?? Infinity);\n}\n\n/**\n * Condition operators for argument constraints.\n * When constraint value is a plain string → exact match (or '*' for any).\n * When constraint value is an object → operator-based matching:\n * { $contains: \"str\" } — value includes substring\n * { $notContains: \"str\" } — value does NOT include substring\n * { $startsWith: \"str\" } — value starts with prefix\n * { $endsWith: \"str\" } — value ends with suffix\n * { $in: [\"a\",\"b\"] } — value is one of the listed values\n * { $notIn: [\"a\",\"b\"] } — value is NOT one of the listed values\n * { $gt: 5 } — numeric greater than\n * { $lt: 5 } — numeric less than\n * { $gte: 5 } — numeric greater than or equal\n * { $lte: 5 } — numeric less than or equal\n */\nfunction argumentConstraintsMatch(\n constraints: Record<string, unknown>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n for (const [key, constraint] of Object.entries(constraints)) {\n if (!(key in args)) return false;\n const argValue = args[key];\n\n // Plain string: exact match (backward compatible)\n if (typeof constraint === 'string') {\n if (constraint === '*') continue;\n if (typeof argValue === 'string') {\n if (argValue !== constraint) return false;\n } else {\n return false;\n }\n continue;\n }\n\n // Object with operators\n if (typeof constraint === 'object' && constraint !== null && !Array.isArray(constraint)) {\n const ops = constraint as Record<string, unknown>;\n const strValue = typeof argValue === 'string' ? argValue : undefined;\n const numValue = typeof argValue === 'number' ? argValue : undefined;\n\n if ('$contains' in ops && typeof ops.$contains === 'string') {\n if (!strValue || !strValue.includes(ops.$contains)) return false;\n }\n if ('$notContains' in ops && typeof ops.$notContains === 'string') {\n if (strValue && strValue.includes(ops.$notContains)) return false;\n }\n if ('$startsWith' in ops && typeof ops.$startsWith === 'string') {\n if (!strValue || !strValue.startsWith(ops.$startsWith)) return false;\n }\n if ('$endsWith' in ops && typeof ops.$endsWith === 'string') {\n if (!strValue || !strValue.endsWith(ops.$endsWith)) return false;\n }\n if ('$in' in ops && Array.isArray(ops.$in)) {\n if (!ops.$in.includes(argValue)) return false;\n }\n if ('$notIn' in ops && Array.isArray(ops.$notIn)) {\n if (ops.$notIn.includes(argValue)) return false;\n }\n if ('$gt' in ops && typeof ops.$gt === 'number') {\n if (numValue === undefined || numValue <= ops.$gt) return false;\n }\n if ('$lt' in ops && typeof ops.$lt === 'number') {\n if (numValue === undefined || numValue >= ops.$lt) return false;\n }\n if ('$gte' in ops && typeof ops.$gte === 'number') {\n if (numValue === undefined || numValue < ops.$gte) return false;\n }\n if ('$lte' in ops && typeof ops.$lte === 'number') {\n if (numValue === undefined || numValue > ops.$lte) return false;\n }\n\n continue;\n }\n }\n return true;\n}\n\nfunction pathConstraintsMatch(\n constraints: NonNullable<PolicyRule['pathConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const paths = extractPathArguments(args);\n\n // If no path arguments found, constraints don't apply\n if (paths.length === 0) return true;\n\n // ALL path arguments must satisfy constraints\n return paths.every((path) => isPathAllowed(path, constraints));\n}\n\nfunction commandConstraintsMatch(\n constraints: NonNullable<PolicyRule['commandConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const commands = extractCommandArguments(args);\n\n // If no command arguments found, constraints don't apply\n if (commands.length === 0) return true;\n\n // ALL command arguments must satisfy constraints\n return commands.every((cmd) => isCommandAllowed(cmd, constraints));\n}\n\nfunction filenameConstraintsMatch(\n constraints: NonNullable<PolicyRule['filenameConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const filenames = extractFilenames(args);\n\n // If no filename arguments found, constraints don't apply\n if (filenames.length === 0) return true;\n\n // ALL filenames must satisfy constraints\n return filenames.every((name) => isFilenameAllowed(name, constraints));\n}\n\nfunction urlConstraintsMatch(\n constraints: NonNullable<PolicyRule['urlConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const urls = extractUrlArguments(args);\n\n // If no URL arguments found, constraints don't apply\n if (urls.length === 0) return true;\n\n // ALL URLs must satisfy constraints\n return urls.every((url) => isUrlAllowed(url, constraints));\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n PolicyEffect,\n} from '@solongate/core';\nimport { DEFAULT_POLICY_EFFECT } from '@solongate/core';\nimport { ruleMatchesRequest } from './matcher.js';\n\n/**\n * Evaluates a policy set against an execution request.\n *\n * Pure function: no side effects, no I/O, fully deterministic.\n *\n * Algorithm:\n * 1. Sort rules by priority (ascending - lower number = higher priority)\n * 2. Find the first matching rule\n * 3. If a rule matches, return its effect\n * 4. If no rule matches, return DENY (default-deny)\n */\nexport function evaluatePolicy(\n policySet: PolicySet,\n request: ExecutionRequest,\n): PolicyDecision {\n const startTime = performance.now();\n\n const sortedRules = [...policySet.rules].sort(\n (a, b) => a.priority - b.priority,\n );\n\n for (const rule of sortedRules) {\n if (ruleMatchesRequest(rule, request)) {\n const endTime = performance.now();\n return {\n effect: rule.effect,\n matchedRule: rule,\n reason: `Matched rule \"${rule.id}\": ${rule.description}`,\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n };\n }\n }\n\n const endTime = performance.now();\n return {\n effect: DEFAULT_POLICY_EFFECT as PolicyEffect,\n matchedRule: null,\n reason: 'No matching policy rule found. Default action: DENY.',\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n metadata: {\n evaluatedRules: sortedRules.length,\n ruleIds: sortedRules.map((r) => r.id),\n requestContext: {\n tool: request.toolName,\n arguments: Object.keys(request.arguments ?? {}),\n },\n },\n };\n}\n","import { PolicyRuleSchema, PolicySetSchema } from '@solongate/core';\nimport {\n MAX_RULES_PER_POLICY_SET,\n UNSAFE_CONFIGURATION_WARNINGS,\n} from '@solongate/core';\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly errors: readonly string[];\n readonly warnings: readonly string[];\n}\n\nexport function validatePolicyRule(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicyRuleSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const rule = result.data;\n\n if (rule.toolPattern === '*' && rule.effect === 'ALLOW') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW);\n }\n\n if (rule.minimumTrustLevel === 'TRUSTED') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.TRUSTED_LEVEL_EXTERNAL);\n }\n\n if (!rule.permission || rule.permission === 'EXECUTE') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW);\n }\n\n return { valid: true, errors, warnings };\n}\n\nexport function validatePolicySet(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicySetSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const policySet = result.data;\n\n if (policySet.rules.length > MAX_RULES_PER_POLICY_SET) {\n errors.push(\n `Policy set exceeds maximum of ${MAX_RULES_PER_POLICY_SET} rules`,\n );\n }\n\n const ruleIds = new Set<string>();\n for (const rule of policySet.rules) {\n if (ruleIds.has(rule.id)) {\n errors.push(`Duplicate rule ID: \"${rule.id}\"`);\n }\n ruleIds.add(rule.id);\n }\n\n for (const rule of policySet.rules) {\n const ruleResult = validatePolicyRule(rule);\n warnings.push(...ruleResult.warnings);\n }\n\n const hasDenyRule = policySet.rules.some((r) => r.effect === 'DENY');\n if (!hasDenyRule && policySet.rules.length > 0) {\n warnings.push(\n 'Policy set contains only ALLOW rules. The default-deny fallback is the only protection.',\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import type { PolicyRule, PolicySet } from '@solongate/core';\nimport { UNSAFE_CONFIGURATION_WARNINGS } from '@solongate/core';\n\nexport interface SecurityWarning {\n readonly level: 'WARNING' | 'CRITICAL';\n readonly code: string;\n readonly message: string;\n readonly ruleId?: string;\n readonly recommendation: string;\n}\n\n/** Analyzes a policy set and returns security warnings. Pure function. */\nexport function analyzeSecurityWarnings(\n policySet: PolicySet,\n): readonly SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n for (const rule of policySet.rules) {\n warnings.push(...analyzeRuleWarnings(rule));\n }\n\n const allowRules = policySet.rules.filter(\n (r) => r.effect === 'ALLOW' && r.enabled,\n );\n const wildcardAllows = allowRules.filter((r) => r.toolPattern === '*');\n\n if (wildcardAllows.length > 0) {\n warnings.push({\n level: 'CRITICAL',\n code: 'WILDCARD_ALLOW',\n message: UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW,\n recommendation:\n 'Replace wildcard ALLOW rules with specific tool patterns.',\n });\n }\n\n return warnings;\n}\n\nfunction analyzeRuleWarnings(rule: PolicyRule): SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n if (rule.effect === 'ALLOW' && rule.minimumTrustLevel === 'UNTRUSTED') {\n warnings.push({\n level: 'CRITICAL',\n code: 'ALLOW_UNTRUSTED',\n message: `Rule \"${rule.id}\" allows execution for UNTRUSTED requests. Unverified LLM requests can execute tools.`,\n ruleId: rule.id,\n recommendation:\n 'Set minimumTrustLevel to VERIFIED or higher for ALLOW rules.',\n });\n }\n\n if (rule.effect === 'ALLOW' && (!rule.permission || rule.permission === 'EXECUTE')) {\n warnings.push({\n level: 'WARNING',\n code: 'ALLOW_EXECUTE',\n message: UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW,\n ruleId: rule.id,\n recommendation:\n 'Ensure EXECUTE permissions are intentional and scoped to specific tools.',\n });\n }\n\n return warnings;\n}\n","import type { PolicySet } from '@solongate/core';\nimport { PolicyEffect, Permission, TrustLevel } from '@solongate/core';\n\n/**\n * Creates the default \"deny all\" policy set.\n * This is the starting policy for any new SolonGate deployment.\n */\nexport function createDefaultDenyPolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'default-deny',\n name: 'Default Deny All',\n description:\n 'Denies all tool executions. Add explicit ALLOW rules to grant access to specific tools.',\n version: 1,\n rules: [\n {\n id: 'deny-all-execute',\n description: 'Explicitly deny all tool executions',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-write',\n description: 'Explicitly deny all write operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-read',\n description: 'Explicitly deny all read operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a permissive \"allow all\" policy set.\n * Allows all tool executions — useful for development or when\n * using SolonGate only for monitoring and audit logging.\n */\nexport function createPermissivePolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'permissive',\n name: 'Permissive (Allow All)',\n description: 'Allows all tool executions. SolonGate still provides input validation, rate limiting, and audit logging.',\n version: 1,\n rules: [\n {\n id: 'allow-all-execute',\n description: 'Allow all tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-read',\n description: 'Allow all read operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-write',\n description: 'Allow all write operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a read-only policy set for a specific tool pattern.\n * Allows reads for VERIFIED requests only.\n */\nexport function createReadOnlyPolicySet(toolPattern: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `read-only-${toolPattern}`,\n name: `Read-Only: ${toolPattern}`,\n description: `Allows read access to tools matching \"${toolPattern}\". Denies write and execute.`,\n version: 1,\n rules: [\n {\n id: `allow-read-${toolPattern}`,\n description: `Allow read access to ${toolPattern}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern,\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.VERIFIED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a sandboxed policy set for a given root directory.\n * Allows file operations within rootDir, blocks dangerous commands,\n * denies access to sensitive files.\n */\nexport function createSandboxedPolicySet(rootDir: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `sandbox-${rootDir.replace(/\\//g, '-')}`,\n name: `Sandbox: ${rootDir}`,\n description: `Allows operations within ${rootDir}. Blocks dangerous commands and sensitive file access.`,\n version: 1,\n rules: [\n {\n id: 'deny-dangerous-commands',\n description: 'Block dangerous shell commands',\n effect: PolicyEffect.DENY,\n priority: 50,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n commandConstraints: {\n denied: [\n 'rm -rf *', 'rm -r /*', 'mkfs*', 'dd if=*',\n 'curl*|*bash*', 'wget*|*sh*',\n 'shutdown*', 'reboot*', 'chmod*777*',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-sensitive-paths',\n description: 'Block access to sensitive files',\n effect: PolicyEffect.DENY,\n priority: 51,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n denied: [\n '**/.env*', '**/.ssh/**', '**/.aws/**',\n '**/credentials*', '**/*.pem', '**/*.key',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-sandboxed-files',\n description: `Allow file operations within ${rootDir}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern: 'file_*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n rootDirectory: rootDir,\n allowed: [`${rootDir}/**`],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-execute',\n description: 'Allow all other tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n} from '@solongate/core';\nimport { POLICY_EVALUATION_TIMEOUT_MS } from '@solongate/core';\nimport { evaluatePolicy } from './evaluator.js';\nimport { validatePolicySet, type ValidationResult } from './validator.js';\nimport { analyzeSecurityWarnings, type SecurityWarning } from './warnings.js';\nimport { createDefaultDenyPolicySet } from './defaults.js';\nimport { PolicyStore, type PolicyVersion } from './policy-store.js';\n\n/**\n * PolicyEngine is the primary interface for policy evaluation.\n *\n * Wraps pure evaluation functions with:\n * - Policy set management (load, validate, swap)\n * - Timeout protection\n * - Warning aggregation\n * - Optional versioned policy store\n */\nexport class PolicyEngine {\n private policySet: PolicySet;\n private readonly timeoutMs: number;\n private readonly store: PolicyStore | null;\n\n constructor(options?: {\n policySet?: PolicySet;\n timeoutMs?: number;\n store?: PolicyStore;\n }) {\n this.policySet = options?.policySet ?? createDefaultDenyPolicySet();\n this.timeoutMs = options?.timeoutMs ?? POLICY_EVALUATION_TIMEOUT_MS;\n this.store = options?.store ?? null;\n }\n\n /**\n * Evaluates an execution request against the current policy set.\n * Never throws for denials - denial is a normal outcome, not an error.\n */\n evaluate(request: ExecutionRequest): PolicyDecision {\n const startTime = performance.now();\n const decision = evaluatePolicy(this.policySet, request);\n const elapsed = performance.now() - startTime;\n\n if (elapsed > this.timeoutMs) {\n console.warn(\n `[SolonGate] Policy evaluation took ${elapsed.toFixed(1)}ms ` +\n `(limit: ${this.timeoutMs}ms) for tool \"${request.toolName}\"`,\n );\n }\n\n return decision;\n }\n\n /**\n * Loads a new policy set, replacing the current one.\n * Validates before accepting. Auto-saves version when store is present.\n */\n loadPolicySet(\n policySet: PolicySet,\n options?: { reason?: string; createdBy?: string },\n ): ValidationResult {\n const validation = validatePolicySet(policySet);\n if (!validation.valid) {\n return validation;\n }\n this.policySet = policySet;\n\n if (this.store) {\n this.store.saveVersion(\n policySet,\n options?.reason ?? 'Policy updated',\n options?.createdBy ?? 'system',\n );\n }\n\n return validation;\n }\n\n /**\n * Rolls back to a previous policy version.\n * Only available when a PolicyStore is configured.\n */\n rollback(version: number): PolicyVersion {\n if (!this.store) {\n throw new Error('PolicyStore not configured - cannot rollback');\n }\n\n const policyVersion = this.store.rollback(this.policySet.id, version);\n this.policySet = policyVersion.policySet;\n return policyVersion;\n }\n\n getPolicySet(): Readonly<PolicySet> {\n return this.policySet;\n }\n\n getSecurityWarnings(): readonly SecurityWarning[] {\n return analyzeSecurityWarnings(this.policySet);\n }\n\n getStore(): PolicyStore | null {\n return this.store;\n }\n\n reset(): void {\n this.policySet = createDefaultDenyPolicySet();\n }\n}\n","import type { PolicySet, PolicyRule } from '@solongate/core';\nimport { createHash } from 'node:crypto';\n\n/**\n * A versioned snapshot of a policy set.\n * Immutable once created - modifications create new versions.\n */\nexport interface PolicyVersion {\n readonly version: number;\n readonly policySet: PolicySet;\n readonly hash: string;\n readonly reason: string;\n readonly createdBy: string;\n readonly createdAt: string;\n}\n\n/**\n * Diff between two policy versions.\n */\nexport interface PolicyDiff {\n readonly added: readonly PolicyRule[];\n readonly removed: readonly PolicyRule[];\n readonly modified: readonly { readonly old: PolicyRule; readonly new: PolicyRule }[];\n}\n\n/**\n * In-memory versioned policy store.\n * Stores complete history of policy changes with cryptographic hashes.\n *\n * Security properties:\n * - Immutable versions: once saved, a version cannot be modified\n * - Hash chain: each version includes SHA256 of the policy content\n * - Full history: no version is ever deleted\n */\nexport class PolicyStore {\n private readonly versions = new Map<string, PolicyVersion[]>();\n\n /**\n * Saves a new version of a policy set.\n * The version number auto-increments.\n */\n saveVersion(\n policySet: PolicySet,\n reason: string,\n createdBy: string,\n ): PolicyVersion {\n const id = policySet.id;\n const history = this.versions.get(id) ?? [];\n\n const latestVersion = history.length > 0 ? history[history.length - 1]!.version : 0;\n\n const version: PolicyVersion = {\n version: latestVersion + 1,\n policySet: Object.freeze({ ...policySet }),\n hash: this.computeHash(policySet),\n reason,\n createdBy,\n createdAt: new Date().toISOString(),\n };\n\n const newHistory = [...history, version];\n this.versions.set(id, newHistory);\n\n return version;\n }\n\n /**\n * Gets a specific version of a policy set.\n */\n getVersion(id: string, version: number): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history) return null;\n return history.find((v) => v.version === version) ?? null;\n }\n\n /**\n * Gets the latest version of a policy set.\n */\n getLatest(id: string): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history || history.length === 0) return null;\n return history[history.length - 1]!;\n }\n\n /**\n * Gets the full version history of a policy set.\n */\n getHistory(id: string): readonly PolicyVersion[] {\n return this.versions.get(id) ?? [];\n }\n\n /**\n * Rolls back to a previous version by creating a new version\n * with the same content as the target version.\n */\n rollback(id: string, toVersion: number): PolicyVersion {\n const target = this.getVersion(id, toVersion);\n if (!target) {\n throw new Error(`Version ${toVersion} not found for policy \"${id}\"`);\n }\n\n return this.saveVersion(\n target.policySet,\n `Rollback to version ${toVersion}`,\n 'system',\n );\n }\n\n /**\n * Computes a diff between two policy versions.\n */\n diff(v1: PolicyVersion, v2: PolicyVersion): PolicyDiff {\n const oldRulesMap = new Map(v1.policySet.rules.map((r) => [r.id, r]));\n const newRulesMap = new Map(v2.policySet.rules.map((r) => [r.id, r]));\n\n const added: PolicyRule[] = [];\n const removed: PolicyRule[] = [];\n const modified: { old: PolicyRule; new: PolicyRule }[] = [];\n\n // Find added and modified rules\n for (const [id, newRule] of newRulesMap) {\n const oldRule = oldRulesMap.get(id);\n if (!oldRule) {\n added.push(newRule);\n } else if (JSON.stringify(oldRule) !== JSON.stringify(newRule)) {\n modified.push({ old: oldRule, new: newRule });\n }\n }\n\n // Find removed rules\n for (const [id, oldRule] of oldRulesMap) {\n if (!newRulesMap.has(id)) {\n removed.push(oldRule);\n }\n }\n\n return { added, removed, modified };\n }\n\n /**\n * Computes SHA256 hash of a policy set for integrity verification.\n */\n computeHash(policySet: PolicySet): string {\n const serialized = JSON.stringify(policySet, Object.keys(policySet).sort());\n return createHash('sha256').update(serialized).digest('hex');\n }\n}\n"]}
|