@grwnd/pi-governance 1.5.0 → 1.5.1
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/extensions/index.cjs +43 -2
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +45 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/index.cjs +12 -705
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -705
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
|
@@ -23,6 +23,7 @@ __export(extensions_exports, {
|
|
|
23
23
|
default: () => extensions_default
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(extensions_exports);
|
|
26
|
+
var import_node_fs2 = require("fs");
|
|
26
27
|
|
|
27
28
|
// src/lib/config/loader.ts
|
|
28
29
|
var import_fs = require("fs");
|
|
@@ -1340,7 +1341,45 @@ var piGovernance = (pi) => {
|
|
|
1340
1341
|
const chain = createIdentityChain(config.auth);
|
|
1341
1342
|
identity = await chain.resolve();
|
|
1342
1343
|
const rulesFile = config.policy?.yaml?.rules_file ?? "./governance-rules.yaml";
|
|
1343
|
-
|
|
1344
|
+
if ((0, import_node_fs2.existsSync)(rulesFile)) {
|
|
1345
|
+
policyEngine = new YamlPolicyEngine(rulesFile);
|
|
1346
|
+
} else {
|
|
1347
|
+
policyEngine = new YamlPolicyEngine({
|
|
1348
|
+
roles: {
|
|
1349
|
+
admin: {
|
|
1350
|
+
allowed_tools: ["all"],
|
|
1351
|
+
blocked_tools: [],
|
|
1352
|
+
prompt_template: "admin",
|
|
1353
|
+
execution_mode: "autonomous",
|
|
1354
|
+
human_approval: { required_for: [] },
|
|
1355
|
+
token_budget_daily: -1,
|
|
1356
|
+
allowed_paths: ["**"],
|
|
1357
|
+
blocked_paths: []
|
|
1358
|
+
},
|
|
1359
|
+
project_lead: {
|
|
1360
|
+
allowed_tools: ["all"],
|
|
1361
|
+
blocked_tools: [],
|
|
1362
|
+
prompt_template: "project-lead",
|
|
1363
|
+
execution_mode: "supervised",
|
|
1364
|
+
human_approval: { required_for: ["bash", "write"] },
|
|
1365
|
+
token_budget_daily: -1,
|
|
1366
|
+
allowed_paths: ["**"],
|
|
1367
|
+
blocked_paths: []
|
|
1368
|
+
},
|
|
1369
|
+
analyst: {
|
|
1370
|
+
allowed_tools: ["read", "grep", "find", "ls"],
|
|
1371
|
+
blocked_tools: ["write", "edit", "bash"],
|
|
1372
|
+
prompt_template: "analyst",
|
|
1373
|
+
execution_mode: "supervised",
|
|
1374
|
+
human_approval: { required_for: ["all"] },
|
|
1375
|
+
token_budget_daily: -1,
|
|
1376
|
+
allowed_paths: ["**"],
|
|
1377
|
+
blocked_paths: []
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
});
|
|
1381
|
+
ctx.ui.notify(`Rules file not found: ${rulesFile} \u2014 using built-in defaults`, "warning");
|
|
1382
|
+
}
|
|
1344
1383
|
executionMode = policyEngine.getExecutionMode(identity.role);
|
|
1345
1384
|
const bashOverrides = policyEngine.getBashOverrides(identity.role);
|
|
1346
1385
|
bashClassifier = new BashClassifier(bashOverrides);
|
|
@@ -1372,7 +1411,9 @@ var piGovernance = (pi) => {
|
|
|
1372
1411
|
(newConfig) => {
|
|
1373
1412
|
config = newConfig;
|
|
1374
1413
|
const newRulesFile = newConfig.policy?.yaml?.rules_file ?? "./governance-rules.yaml";
|
|
1375
|
-
|
|
1414
|
+
if ((0, import_node_fs2.existsSync)(newRulesFile)) {
|
|
1415
|
+
policyEngine = new YamlPolicyEngine(newRulesFile);
|
|
1416
|
+
}
|
|
1376
1417
|
const newOverrides = policyEngine.getBashOverrides(identity.role);
|
|
1377
1418
|
bashClassifier = new BashClassifier(newOverrides);
|
|
1378
1419
|
const newDlpCfg = resolveDlpConfig(newConfig.dlp, identity.role);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/extensions/index.ts","../../src/lib/config/loader.ts","../../src/lib/config/schema.ts","../../src/lib/config/defaults.ts","../../src/lib/identity/env-provider.ts","../../src/lib/identity/local-provider.ts","../../src/lib/identity/chain.ts","../../src/lib/policy/yaml-engine.ts","../../src/lib/bash/patterns.ts","../../src/lib/bash/classifier.ts","../../src/lib/audit/logger.ts","../../src/lib/audit/sinks/jsonl.ts","../../src/lib/audit/sinks/webhook.ts","../../src/lib/hitl/cli-approver.ts","../../src/lib/hitl/webhook-approver.ts","../../src/lib/hitl/approval.ts","../../src/lib/budget/tracker.ts","../../src/lib/config/watcher.ts","../../src/lib/dlp/patterns.ts","../../src/lib/dlp/scanner.ts","../../src/lib/dlp/masker.ts"],"sourcesContent":["// Pi Extension API types — locally defined to avoid hard dependency on @mariozechner/pi-coding-agent\n// These match the real Pi extension API surface.\n\ninterface ToolCallEvent {\n toolName: string;\n input: Record<string, unknown>;\n}\n\ninterface ToolResultEvent {\n toolName: string;\n input: Record<string, unknown>;\n output: string;\n isError: boolean;\n}\n\ninterface ExtensionUI {\n confirm(title: string, message: string, opts?: { timeout?: number }): Promise<boolean>;\n notify(msg: string, type?: 'info' | 'warning' | 'error'): void;\n setStatus(key: string, text: string): void;\n}\n\ninterface ExtensionContext {\n ui: ExtensionUI;\n sessionId: string;\n workingDirectory: string;\n}\n\ntype ToolCallHandler = (\n event: ToolCallEvent,\n ctx: ExtensionContext,\n) => Promise<{ block: true; reason: string } | void>;\n\ntype ToolResultHandler = (event: ToolResultEvent, ctx: ExtensionContext) => Promise<void>;\n\ntype SessionHandler = (event: unknown, ctx: ExtensionContext) => Promise<void>;\n\ninterface ExtensionAPI {\n on(event: 'session_start', handler: SessionHandler): void;\n on(event: 'session_shutdown', handler: SessionHandler): void;\n on(event: 'tool_call', handler: ToolCallHandler): void;\n on(event: 'tool_result', handler: ToolResultHandler): void;\n registerCommand(\n name: string,\n opts: {\n description?: string;\n handler: (args: string, ctx: ExtensionContext) => Promise<void>;\n },\n ): void;\n}\n\ntype ExtensionFactory = (pi: ExtensionAPI) => void;\n\n// --- Implementation ---\n\nimport { loadConfig } from '../lib/config/loader.js';\nimport { createIdentityChain } from '../lib/identity/chain.js';\nimport { YamlPolicyEngine } from '../lib/policy/yaml-engine.js';\nimport { BashClassifier } from '../lib/bash/classifier.js';\nimport { AuditLogger } from '../lib/audit/logger.js';\nimport { createApprovalFlow } from '../lib/hitl/approval.js';\nimport { BudgetTracker } from '../lib/budget/tracker.js';\nimport { ConfigWatcher } from '../lib/config/watcher.js';\nimport { DlpScanner } from '../lib/dlp/scanner.js';\nimport { DlpMasker } from '../lib/dlp/masker.js';\nimport type { DlpAction, DlpMatch, DlpScannerConfig } from '../lib/dlp/scanner.js';\nimport type { ApprovalFlow } from '../lib/hitl/approval.js';\nimport type { PolicyEngine, ExecutionMode } from '../lib/policy/engine.js';\nimport type { ResolvedIdentity } from '../lib/identity/provider.js';\nimport type { GovernanceConfig, DlpConfigType } from '../lib/config/schema.js';\n\n// Tools that involve file paths — used for path boundary checks\nconst PATH_TOOLS: Record<string, string> = {\n read: 'path',\n write: 'path',\n edit: 'file_path',\n grep: 'path',\n find: 'path',\n ls: 'path',\n};\n\n// Tools that are write operations for path checking\nconst WRITE_TOOLS = new Set(['write', 'edit']);\n\nfunction summarizeParams(\n toolName: string,\n input: Record<string, unknown>,\n): Record<string, unknown> {\n switch (toolName) {\n case 'bash': {\n const cmd = typeof input['command'] === 'string' ? input['command'] : '';\n return { command: cmd.slice(0, 100) + (cmd.length > 100 ? '...' : '') };\n }\n case 'read':\n return { path: input['path'] };\n case 'write':\n return { path: input['path'] };\n case 'edit':\n return { file_path: input['file_path'] };\n case 'grep':\n return { pattern: input['pattern'], path: input['path'] };\n case 'find':\n case 'ls':\n return { path: input['path'] };\n default:\n return {};\n }\n}\n\nfunction extractPath(toolName: string, input: Record<string, unknown>): string | undefined {\n const key = PATH_TOOLS[toolName];\n if (!key) return undefined;\n const val = input[key];\n return typeof val === 'string' ? val : undefined;\n}\n\n// --- DLP helpers ---\n\nconst ACTION_PRIORITY: Record<DlpAction, number> = { audit: 0, mask: 1, block: 2 };\n\nfunction extractDlpFields(toolName: string, input: Record<string, unknown>): Map<string, string> {\n const fields = new Map<string, string>();\n switch (toolName) {\n case 'bash': {\n const cmd = input['command'];\n if (typeof cmd === 'string') fields.set('command', cmd);\n break;\n }\n case 'write': {\n const content = input['content'];\n if (typeof content === 'string') fields.set('content', content);\n const path = input['path'];\n if (typeof path === 'string') fields.set('path', path);\n break;\n }\n case 'edit': {\n const newStr = input['new_string'];\n if (typeof newStr === 'string') fields.set('new_string', newStr);\n const oldStr = input['old_string'];\n if (typeof oldStr === 'string') fields.set('old_string', oldStr);\n break;\n }\n default: {\n // Scan all string values\n for (const [key, val] of Object.entries(input)) {\n if (typeof val === 'string') fields.set(key, val);\n }\n }\n }\n return fields;\n}\n\nfunction resolveHighestAction(\n scanner: DlpScanner,\n matches: DlpMatch[],\n direction: 'input' | 'output',\n): DlpAction {\n let highest: DlpAction = 'audit';\n for (const match of matches) {\n const action = scanner.getPatternAction(match, direction);\n if (ACTION_PRIORITY[action] > ACTION_PRIORITY[highest]) {\n highest = action;\n }\n }\n return highest;\n}\n\nfunction resolveDlpConfig(\n dlpConfig: DlpConfigType | undefined,\n role: string,\n): DlpScannerConfig | undefined {\n if (!dlpConfig?.enabled) return undefined;\n\n // Apply role overrides\n const roleOverride = dlpConfig.role_overrides?.[role];\n if (roleOverride?.enabled === false) return undefined;\n\n const patternOverrides = new Map<string, DlpAction>();\n\n return {\n enabled: true,\n mode: roleOverride?.mode ?? dlpConfig.mode ?? 'audit',\n on_input: roleOverride?.on_input ?? dlpConfig.on_input,\n on_output: roleOverride?.on_output ?? dlpConfig.on_output,\n severity_threshold: dlpConfig.severity_threshold ?? 'low',\n built_in: {\n secrets: dlpConfig.built_in?.secrets ?? true,\n pii: dlpConfig.built_in?.pii ?? true,\n },\n custom_patterns: (dlpConfig.custom_patterns ?? []).map((cp) => ({\n name: cp.name,\n pattern: cp.pattern,\n severity: cp.severity,\n action: cp.action as DlpAction | undefined,\n })),\n allowlist: dlpConfig.allowlist ?? [],\n pattern_overrides: patternOverrides,\n };\n}\n\nconst piGovernance: ExtensionFactory = (pi) => {\n // State — initialized in session_start\n let config: GovernanceConfig;\n let policyEngine: PolicyEngine;\n let audit: AuditLogger;\n let approvalFlow: ApprovalFlow | undefined;\n let bashClassifier: BashClassifier;\n let identity: ResolvedIdentity;\n let executionMode: ExecutionMode;\n let sessionId: string;\n let budgetTracker: BudgetTracker;\n let configWatcher: ConfigWatcher | undefined;\n let dlpScanner: DlpScanner | undefined;\n let dlpMasker: DlpMasker | undefined;\n\n const stats = {\n allowed: 0,\n denied: 0,\n approvals: 0,\n dryRun: 0,\n budgetExceeded: 0,\n dlpBlocked: 0,\n dlpDetected: 0,\n dlpMasked: 0,\n };\n\n pi.on('session_start', async (_event, ctx) => {\n sessionId = ctx.sessionId;\n\n // 1. Load config\n const loaded = loadConfig();\n config = loaded.config;\n\n // 2. Resolve identity\n const chain = createIdentityChain(config.auth);\n identity = await chain.resolve();\n\n // 3. Create policy engine\n const rulesFile = config.policy?.yaml?.rules_file ?? './governance-rules.yaml';\n policyEngine = new YamlPolicyEngine(rulesFile);\n\n // 4. Get execution mode\n executionMode = policyEngine.getExecutionMode(identity.role);\n\n // 5. Create bash classifier with role overrides\n const bashOverrides = policyEngine.getBashOverrides(identity.role);\n bashClassifier = new BashClassifier(bashOverrides);\n\n // 6. Create audit logger\n audit = new AuditLogger(config.audit);\n\n // 7. Create approval flow if supervised mode\n if (executionMode === 'supervised') {\n try {\n approvalFlow = createApprovalFlow(\n {\n default_mode: config.hitl?.default_mode ?? 'supervised',\n approval_channel: config.hitl?.approval_channel ?? 'cli',\n timeout_seconds: config.hitl?.timeout_seconds ?? 300,\n webhook: config.hitl?.webhook,\n },\n ctx.ui,\n );\n } catch {\n // If CLI UI not available, approval flow stays undefined\n }\n }\n\n // 8. Create budget tracker\n const budget = policyEngine.getTokenBudget(identity.role);\n budgetTracker = new BudgetTracker(budget);\n\n // 9. Initialize DLP scanner/masker if enabled\n const dlpCfg = resolveDlpConfig(config.dlp, identity.role);\n if (dlpCfg) {\n dlpScanner = new DlpScanner(dlpCfg);\n dlpMasker = new DlpMasker(config.dlp?.masking);\n }\n\n // 10. Start config watcher\n if (loaded.source !== 'built-in') {\n configWatcher = new ConfigWatcher(\n loaded.source,\n (newConfig) => {\n config = newConfig;\n const newRulesFile = newConfig.policy?.yaml?.rules_file ?? './governance-rules.yaml';\n policyEngine = new YamlPolicyEngine(newRulesFile);\n const newOverrides = policyEngine.getBashOverrides(identity.role);\n bashClassifier = new BashClassifier(newOverrides);\n // Recreate DLP scanner/masker on config reload\n const newDlpCfg = resolveDlpConfig(newConfig.dlp, identity.role);\n if (newDlpCfg) {\n dlpScanner = new DlpScanner(newDlpCfg);\n dlpMasker = new DlpMasker(newConfig.dlp?.masking);\n } else {\n dlpScanner = undefined;\n dlpMasker = undefined;\n }\n audit.log({\n sessionId,\n event: 'config_reloaded',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n metadata: { source: loaded.source },\n });\n ctx.ui.notify('Governance config reloaded', 'info');\n },\n (error) => {\n ctx.ui.notify(`Config reload failed: ${error.message}`, 'warning');\n },\n );\n configWatcher.start();\n }\n\n // 10. Audit session start\n await audit.log({\n sessionId,\n event: 'session_start',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n metadata: { source: loaded.source, executionMode },\n });\n\n // 11. UI feedback\n ctx.ui.setStatus('governance', `Governance: ${identity.role} (${executionMode})`);\n ctx.ui.notify(\n `Governance active — Role: ${identity.role} | Mode: ${executionMode} | Org: ${identity.orgUnit}`,\n 'info',\n );\n });\n\n pi.on('tool_call', async (event, _ctx) => {\n const { toolName, input } = event;\n const params = summarizeParams(toolName, input);\n\n const baseRecord = {\n sessionId,\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: toolName,\n input: params,\n };\n\n // 1. Dry-run mode — block everything, log as dry_run\n if (executionMode === 'dry_run') {\n stats.dryRun++;\n await audit.log({\n ...baseRecord,\n event: 'tool_dry_run',\n decision: 'blocked',\n reason: 'Dry-run mode',\n });\n return { block: true, reason: 'Dry-run mode: tool execution blocked for observation' };\n }\n\n // 2. Budget check\n if (!budgetTracker.consume()) {\n stats.budgetExceeded++;\n await audit.log({\n ...baseRecord,\n event: 'budget_exceeded',\n decision: 'denied',\n reason: `Budget exhausted (${budgetTracker.used()} invocations used)`,\n });\n return {\n block: true,\n reason: `Tool invocation budget exhausted (${budgetTracker.used()} used). Session limit reached.`,\n };\n }\n\n // 3. Policy: evaluate tool access\n const toolDecision = policyEngine.evaluateTool(identity.role, toolName);\n if (toolDecision === 'deny') {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'tool_denied',\n decision: 'denied',\n reason: 'Policy denied tool',\n });\n return { block: true, reason: `Policy denies ${identity.role} from using ${toolName}` };\n }\n\n // 4. Bash-specific classification\n if (toolName === 'bash') {\n const command = typeof input['command'] === 'string' ? input['command'] : '';\n const classification = bashClassifier.classify(command);\n\n if (classification === 'dangerous') {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'bash_denied',\n decision: 'denied',\n reason: 'Dangerous command',\n });\n return { block: true, reason: `Dangerous bash command blocked: ${command.slice(0, 80)}` };\n }\n\n // needs_review with approval required\n if (\n classification === 'needs_review' &&\n policyEngine.requiresApproval(identity.role, 'bash')\n ) {\n if (approvalFlow) {\n stats.approvals++;\n await audit.log({ ...baseRecord, event: 'approval_requested' });\n\n const result = await approvalFlow.requestApproval(\n { toolName, input },\n { userId: identity.userId, role: identity.role, orgUnit: identity.orgUnit },\n );\n\n if (result.approved) {\n await audit.log({\n ...baseRecord,\n event: 'approval_granted',\n duration: result.duration,\n });\n } else {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'approval_denied',\n reason: result.reason,\n duration: result.duration,\n });\n return { block: true, reason: result.reason ?? 'Approval denied' };\n }\n } else {\n // No approval flow — deny\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'tool_denied',\n decision: 'denied',\n reason: 'Requires approval but no approval channel',\n });\n return {\n block: true,\n reason: 'Bash command requires approval but no approval channel is configured',\n };\n }\n }\n }\n\n // 5. Path boundary check for file tools\n const path = extractPath(toolName, input);\n if (path) {\n const operation = WRITE_TOOLS.has(toolName) ? 'write' : 'read';\n const pathDecision = policyEngine.evaluatePath(\n identity.role,\n identity.orgUnit,\n operation,\n path,\n );\n if (pathDecision === 'deny') {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'path_denied',\n decision: 'denied',\n reason: `Path denied: ${path}`,\n });\n return { block: true, reason: `Access denied to path: ${path}` };\n }\n }\n\n // 6. DLP scan inputs\n if (dlpScanner && dlpMasker) {\n const fields = extractDlpFields(toolName, input);\n const allMatches: DlpMatch[] = [];\n for (const [, fieldValue] of fields) {\n const result = dlpScanner.scan(fieldValue);\n allMatches.push(...result.matches);\n }\n\n if (allMatches.length > 0) {\n const action = resolveHighestAction(dlpScanner, allMatches, 'input');\n const patternNames = [...new Set(allMatches.map((m) => m.patternName))];\n const severities = [...new Set(allMatches.map((m) => m.severity))];\n const dlpMeta = {\n patterns: patternNames,\n severities,\n direction: 'input' as const,\n count: allMatches.length,\n };\n\n if (action === 'block') {\n stats.dlpBlocked++;\n await audit.log({\n ...baseRecord,\n event: 'dlp_blocked',\n decision: 'denied',\n reason: `DLP: ${patternNames.join(', ')} detected in input`,\n metadata: dlpMeta,\n });\n return {\n block: true,\n reason: `DLP blocked: sensitive data detected (${patternNames.join(', ')})`,\n };\n }\n\n if (action === 'mask') {\n stats.dlpMasked++;\n // Mask each field independently to maintain correct positions\n for (const [fieldKey, fieldValue] of fields) {\n const fieldResult = dlpScanner.scan(fieldValue);\n if (fieldResult.hasMatches) {\n (input as Record<string, unknown>)[fieldKey] = dlpMasker.maskText(\n fieldValue,\n fieldResult.matches,\n );\n }\n }\n await audit.log({\n ...baseRecord,\n event: 'dlp_masked',\n metadata: { ...dlpMeta, strategy: dlpMasker['config'].strategy },\n });\n } else {\n // audit-only\n stats.dlpDetected++;\n await audit.log({\n ...baseRecord,\n event: 'dlp_detected',\n metadata: dlpMeta,\n });\n }\n }\n }\n\n // 7. HITL approval for non-bash tools if required\n if (toolName !== 'bash' && policyEngine.requiresApproval(identity.role, toolName)) {\n if (approvalFlow) {\n stats.approvals++;\n await audit.log({ ...baseRecord, event: 'approval_requested' });\n\n const result = await approvalFlow.requestApproval(\n { toolName, input },\n { userId: identity.userId, role: identity.role, orgUnit: identity.orgUnit },\n );\n\n if (result.approved) {\n await audit.log({ ...baseRecord, event: 'approval_granted', duration: result.duration });\n } else {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'approval_denied',\n reason: result.reason,\n duration: result.duration,\n });\n return { block: true, reason: result.reason ?? 'Approval denied' };\n }\n }\n }\n\n // 8. Tool allowed\n stats.allowed++;\n await audit.log({ ...baseRecord, event: 'tool_allowed', decision: 'allowed' });\n return undefined;\n });\n\n pi.on('tool_result', async (event, _ctx) => {\n // DLP scan output before audit\n if (dlpScanner && dlpMasker && event.output) {\n const result = dlpScanner.scan(event.output);\n if (result.hasMatches) {\n const action = resolveHighestAction(dlpScanner, result.matches, 'output');\n const patternNames = [...new Set(result.matches.map((m) => m.patternName))];\n const severities = [...new Set(result.matches.map((m) => m.severity))];\n const dlpMeta = {\n patterns: patternNames,\n severities,\n direction: 'output' as const,\n count: result.matches.length,\n };\n\n if (action === 'mask' || action === 'block') {\n // block degrades to mask for outputs (handler returns void)\n stats.dlpMasked++;\n event.output = dlpMasker.maskText(event.output, result.matches);\n await audit.log({\n sessionId,\n event: 'dlp_masked',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: event.toolName,\n metadata: { ...dlpMeta, strategy: dlpMasker['config'].strategy },\n });\n } else {\n stats.dlpDetected++;\n await audit.log({\n sessionId,\n event: 'dlp_detected',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: event.toolName,\n metadata: dlpMeta,\n });\n }\n }\n }\n\n await audit.log({\n sessionId,\n event: 'tool_result',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: event.toolName,\n input: summarizeParams(event.toolName, event.input),\n metadata: { isError: event.isError },\n });\n });\n\n pi.on('session_shutdown', async (_event, _ctx) => {\n configWatcher?.stop();\n await audit.log({\n sessionId,\n event: 'session_end',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n metadata: {\n stats: { ...stats },\n budget: { used: budgetTracker.used(), remaining: budgetTracker.remaining() },\n summary: Object.fromEntries(audit.getSummary()),\n },\n });\n await audit.flush();\n });\n\n pi.registerCommand('governance', {\n description: 'Governance status and controls',\n handler: async (args, ctx) => {\n const subcommand = args.trim().split(/\\s+/)[0] ?? '';\n\n if (subcommand === 'status') {\n const summary = audit.getSummary();\n const budgetInfo = budgetTracker.isUnlimited()\n ? 'unlimited'\n : `${budgetTracker.used()} / ${budgetTracker.used() + budgetTracker.remaining()} (${budgetTracker.remaining()} remaining)`;\n const lines = [\n `Role: ${identity.role}`,\n `Org Unit: ${identity.orgUnit}`,\n `Mode: ${executionMode}`,\n `Session: ${sessionId}`,\n `Budget: ${budgetInfo}`,\n '',\n 'Session Stats:',\n ` Allowed: ${stats.allowed}`,\n ` Denied: ${stats.denied}`,\n ` Approvals: ${stats.approvals}`,\n ` Dry-run blocks: ${stats.dryRun}`,\n ` Budget exceeded: ${stats.budgetExceeded}`,\n ` DLP blocked: ${stats.dlpBlocked}`,\n ` DLP detected: ${stats.dlpDetected}`,\n ` DLP masked: ${stats.dlpMasked}`,\n '',\n 'Audit Events:',\n ...[...summary.entries()].map(([k, v]) => ` ${k}: ${v}`),\n ];\n ctx.ui.notify(lines.join('\\n'), 'info');\n } else {\n ctx.ui.notify('Usage: /governance status', 'info');\n }\n },\n });\n};\n\nexport default piGovernance;\n\n// Re-export types for consumers\nexport type {\n ExtensionFactory,\n ExtensionAPI,\n ExtensionContext,\n ExtensionUI,\n ToolCallEvent,\n ToolResultEvent,\n};\n","import { existsSync, readFileSync } from 'fs';\nimport { parse as parseYaml } from 'yaml';\nimport { Value } from '@sinclair/typebox/value';\nimport { GovernanceConfigSchema, type GovernanceConfig } from './schema.js';\nimport { DEFAULTS } from './defaults.js';\n\nfunction getConfigPaths(): (string | undefined)[] {\n return [\n process.env['GRWND_GOVERNANCE_CONFIG'],\n '.pi/governance.yaml',\n `${process.env['HOME']}/.pi/agent/governance.yaml`,\n ];\n}\n\nexport function loadConfig(): { config: GovernanceConfig; source: string } {\n for (const path of getConfigPaths()) {\n if (path && existsSync(path)) {\n const raw = readFileSync(path, 'utf-8');\n const parsed = parseYaml(raw);\n\n const resolved = resolveEnvVars(parsed);\n\n const errors = [...Value.Errors(GovernanceConfigSchema, resolved)];\n if (errors.length > 0) {\n throw new ConfigValidationError(\n path,\n errors.map((e) => ({ path: e.path, message: e.message })),\n );\n }\n\n const config = Value.Default(GovernanceConfigSchema, resolved) as GovernanceConfig;\n return { config, source: path };\n }\n }\n\n return { config: DEFAULTS, source: 'built-in' };\n}\n\nfunction resolveEnvVars(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return obj.replace(/\\$\\{(\\w+)\\}/g, (_, name: string) => process.env[name] ?? '');\n }\n if (Array.isArray(obj)) return obj.map(resolveEnvVars);\n if (obj && typeof obj === 'object') {\n return Object.fromEntries(\n Object.entries(obj as Record<string, unknown>).map(([k, v]) => [k, resolveEnvVars(v)]),\n );\n }\n return obj;\n}\n\nexport class ConfigValidationError extends Error {\n constructor(path: string, errors: Array<{ path: string; message: string }>) {\n const details = errors.map((e) => ` ${e.path}: ${e.message}`).join('\\n');\n super(`Invalid governance config at ${path}:\\n${details}`);\n this.name = 'ConfigValidationError';\n }\n}\n","import { Type, type Static } from '@sinclair/typebox';\n\nconst AuthEnvConfig = Type.Object({\n user_var: Type.String({ default: 'GRWND_USER' }),\n role_var: Type.String({ default: 'GRWND_ROLE' }),\n org_unit_var: Type.String({ default: 'GRWND_ORG_UNIT' }),\n});\n\nconst AuthLocalConfig = Type.Object({\n users_file: Type.String({ default: './users.yaml' }),\n});\n\nconst AuthConfig = Type.Object({\n provider: Type.Union([Type.Literal('env'), Type.Literal('local'), Type.Literal('oidc')], {\n default: 'env',\n }),\n env: Type.Optional(AuthEnvConfig),\n local: Type.Optional(AuthLocalConfig),\n});\n\nexport type AuthConfigType = Static<typeof AuthConfig>;\n\nconst YamlPolicyConfig = Type.Object({\n rules_file: Type.String({ default: './governance-rules.yaml' }),\n});\n\nconst OsoPolicyConfig = Type.Object({\n polar_files: Type.Array(Type.String(), {\n default: ['./policies/base.polar', './policies/tools.polar'],\n }),\n});\n\nconst PolicyConfig = Type.Object({\n engine: Type.Union([Type.Literal('yaml'), Type.Literal('oso')], { default: 'yaml' }),\n yaml: Type.Optional(YamlPolicyConfig),\n oso: Type.Optional(OsoPolicyConfig),\n});\n\nconst TemplatesConfig = Type.Object({\n directory: Type.String({ default: './templates/' }),\n default: Type.String({ default: 'project-lead' }),\n});\n\nconst HitlWebhookConfig = Type.Object({\n url: Type.String(),\n});\n\nconst HitlConfig = Type.Object({\n default_mode: Type.Union(\n [Type.Literal('autonomous'), Type.Literal('supervised'), Type.Literal('dry_run')],\n { default: 'supervised' },\n ),\n approval_channel: Type.Union([Type.Literal('cli'), Type.Literal('webhook')], { default: 'cli' }),\n timeout_seconds: Type.Number({ default: 300, minimum: 10, maximum: 3600 }),\n webhook: Type.Optional(HitlWebhookConfig),\n});\n\nconst JsonlSinkConfig = Type.Object({\n type: Type.Literal('jsonl'),\n path: Type.String({ default: '~/.pi/agent/audit.jsonl' }),\n});\n\nconst WebhookSinkConfig = Type.Object({\n type: Type.Literal('webhook'),\n url: Type.String(),\n});\n\nconst PostgresSinkConfig = Type.Object({\n type: Type.Literal('postgres'),\n connection: Type.String(),\n});\n\nconst AuditSinkConfig = Type.Union([JsonlSinkConfig, WebhookSinkConfig, PostgresSinkConfig]);\n\nconst AuditConfig = Type.Object({\n sinks: Type.Array(AuditSinkConfig, {\n default: [{ type: 'jsonl', path: '~/.pi/agent/audit.jsonl' }],\n }),\n});\n\nconst OrgUnitOverride = Type.Object({\n hitl: Type.Optional(Type.Partial(HitlConfig)),\n policy: Type.Optional(\n Type.Object({\n extra_polar: Type.Optional(Type.String()),\n extra_rules: Type.Optional(Type.String()),\n }),\n ),\n});\n\n// --- DLP (Data Loss Prevention) ---\n\nconst DlpMaskingConfig = Type.Object({\n strategy: Type.Union([Type.Literal('partial'), Type.Literal('full'), Type.Literal('hash')], {\n default: 'partial',\n }),\n show_chars: Type.Optional(Type.Number({ default: 4, minimum: 0 })),\n placeholder: Type.Optional(Type.String({ default: '***' })),\n});\n\nconst DlpCustomPatternConfig = Type.Object({\n name: Type.String(),\n pattern: Type.String(),\n severity: Type.Union([\n Type.Literal('low'),\n Type.Literal('medium'),\n Type.Literal('high'),\n Type.Literal('critical'),\n ]),\n action: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n});\n\nconst DlpAllowlistEntryConfig = Type.Object({\n pattern: Type.String(),\n});\n\nconst DlpRoleOverrideConfig = Type.Object({\n enabled: Type.Optional(Type.Boolean()),\n mode: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n on_input: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n on_output: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n});\n\nconst DlpConfig = Type.Object({\n enabled: Type.Boolean({ default: false }),\n mode: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')], {\n default: 'audit',\n }),\n ),\n on_input: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n on_output: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n masking: Type.Optional(DlpMaskingConfig),\n severity_threshold: Type.Optional(\n Type.Union(\n [Type.Literal('low'), Type.Literal('medium'), Type.Literal('high'), Type.Literal('critical')],\n { default: 'low' },\n ),\n ),\n built_in: Type.Optional(\n Type.Object({\n secrets: Type.Boolean({ default: true }),\n pii: Type.Boolean({ default: true }),\n }),\n ),\n custom_patterns: Type.Optional(Type.Array(DlpCustomPatternConfig)),\n allowlist: Type.Optional(Type.Array(DlpAllowlistEntryConfig)),\n role_overrides: Type.Optional(Type.Record(Type.String(), DlpRoleOverrideConfig)),\n});\n\nexport type DlpConfigType = Static<typeof DlpConfig>;\n\nexport const GovernanceConfigSchema = Type.Object({\n auth: Type.Optional(AuthConfig),\n policy: Type.Optional(PolicyConfig),\n templates: Type.Optional(TemplatesConfig),\n hitl: Type.Optional(HitlConfig),\n audit: Type.Optional(AuditConfig),\n dlp: Type.Optional(DlpConfig),\n org_units: Type.Optional(Type.Record(Type.String(), OrgUnitOverride)),\n});\n\nexport type GovernanceConfig = Static<typeof GovernanceConfigSchema>;\n","import type { GovernanceConfig } from './schema.js';\n\nexport const DEFAULTS: GovernanceConfig = {\n auth: {\n provider: 'env',\n env: {\n user_var: 'GRWND_USER',\n role_var: 'GRWND_ROLE',\n org_unit_var: 'GRWND_ORG_UNIT',\n },\n },\n policy: {\n engine: 'yaml',\n yaml: {\n rules_file: './governance-rules.yaml',\n },\n },\n templates: {\n directory: './templates/',\n default: 'project-lead',\n },\n hitl: {\n default_mode: 'supervised',\n approval_channel: 'cli',\n timeout_seconds: 300,\n },\n audit: {\n sinks: [{ type: 'jsonl', path: '~/.pi/agent/audit.jsonl' }],\n },\n dlp: {\n enabled: false,\n },\n};\n","import type { IdentityProvider, ResolvedIdentity } from './provider.js';\n\nexport class EnvIdentityProvider implements IdentityProvider {\n name = 'env';\n\n constructor(\n private userVar: string = 'GRWND_USER',\n private roleVar: string = 'GRWND_ROLE',\n private orgUnitVar: string = 'GRWND_ORG_UNIT',\n ) {}\n\n async resolve(): Promise<ResolvedIdentity | null> {\n const userId = process.env[this.userVar];\n const role = process.env[this.roleVar];\n const orgUnit = process.env[this.orgUnitVar];\n\n if (!userId || !role) return null;\n\n return {\n userId,\n role,\n orgUnit: orgUnit ?? 'default',\n source: 'env',\n };\n }\n}\n","import { readFileSync } from 'fs';\nimport { parse as parseYaml } from 'yaml';\nimport type { IdentityProvider, ResolvedIdentity } from './provider.js';\n\ninterface UserEntry {\n role: string;\n org_unit?: string;\n}\n\nexport class LocalIdentityProvider implements IdentityProvider {\n name = 'local';\n private users: Record<string, UserEntry>;\n\n constructor(usersFilePath: string) {\n const raw = readFileSync(usersFilePath, 'utf-8');\n this.users = parseYaml(raw) as Record<string, UserEntry>;\n }\n\n async resolve(): Promise<ResolvedIdentity | null> {\n // Try to determine the current system username\n const username = process.env.USER || process.env.USERNAME;\n if (!username) return null;\n\n const entry = this.users[username];\n if (!entry) return null;\n\n return {\n userId: username,\n role: entry.role,\n orgUnit: entry.org_unit ?? 'default',\n source: 'local',\n };\n }\n}\n","import type { IdentityProvider, ResolvedIdentity } from './provider.js';\nimport type { AuthConfigType } from '../config/schema.js';\nimport { EnvIdentityProvider } from './env-provider.js';\nimport { LocalIdentityProvider } from './local-provider.js';\n\nexport class IdentityChain {\n private providers: IdentityProvider[];\n\n constructor(providers: IdentityProvider[]) {\n this.providers = providers;\n }\n\n async resolve(): Promise<ResolvedIdentity> {\n for (const provider of this.providers) {\n const identity = await provider.resolve();\n if (identity) return identity;\n }\n\n // Fallback: default restricted identity\n return {\n userId: 'unknown',\n role: 'analyst', // most restrictive role by default\n orgUnit: 'default',\n source: 'fallback',\n };\n }\n}\n\nexport function createIdentityChain(config?: AuthConfigType): IdentityChain {\n const providers: IdentityProvider[] = [];\n\n // Always try env first (fastest, works in CI)\n providers.push(\n new EnvIdentityProvider(\n config?.env?.user_var,\n config?.env?.role_var,\n config?.env?.org_unit_var,\n ),\n );\n\n // Then try local file if configured\n if (config?.provider === 'local' && config.local?.users_file) {\n try {\n providers.push(new LocalIdentityProvider(config.local.users_file));\n } catch {\n // users file not found — skip this provider\n }\n }\n\n return new IdentityChain(providers);\n}\n","import { readFileSync } from 'fs';\nimport { parse as parseYaml } from 'yaml';\nimport { minimatch } from 'minimatch';\nimport type {\n PolicyEngine,\n PolicyDecision,\n PathOperation,\n ExecutionMode,\n BashOverrides,\n} from './engine.js';\n\nexport interface YamlRole {\n allowed_tools: string[];\n blocked_tools: string[];\n prompt_template: string;\n execution_mode: ExecutionMode;\n human_approval: {\n required_for: string[];\n auto_approve?: string[];\n };\n token_budget_daily: number;\n allowed_paths: string[];\n blocked_paths: string[];\n bash_overrides?: {\n additional_blocked?: string[];\n additional_allowed?: string[];\n };\n}\n\nexport interface YamlRules {\n roles: Record<string, YamlRole>;\n}\n\nexport class YamlPolicyEngine implements PolicyEngine {\n private rules: YamlRules;\n\n constructor(rulesFilePathOrRules: string | YamlRules) {\n if (typeof rulesFilePathOrRules === 'string') {\n const raw = readFileSync(rulesFilePathOrRules, 'utf-8');\n this.rules = parseYaml(raw) as YamlRules;\n } else {\n this.rules = rulesFilePathOrRules;\n }\n }\n\n private getRole(role: string): YamlRole {\n const r = this.rules.roles[role];\n if (!r) {\n throw new Error(\n `Unknown role: ${role}. Available roles: ${Object.keys(this.rules.roles).join(', ')}`,\n );\n }\n return r;\n }\n\n evaluateTool(role: string, tool: string): PolicyDecision {\n const r = this.getRole(role);\n\n // Check blocked list first\n if (r.blocked_tools.includes(tool)) return 'deny';\n\n // Check allowed list\n if (r.allowed_tools.includes('all') || r.allowed_tools.includes(tool)) {\n return 'allow';\n }\n\n // Not in either list — deny by default\n return 'deny';\n }\n\n evaluatePath(\n role: string,\n _orgUnit: string,\n _operation: PathOperation,\n path: string,\n ): PolicyDecision {\n const r = this.getRole(role);\n\n // Check blocked paths first (takes precedence)\n for (const pattern of r.blocked_paths) {\n if (minimatch(path, pattern, { dot: true })) {\n return 'deny';\n }\n }\n\n // Check allowed paths\n for (const pattern of r.allowed_paths) {\n const resolved = pattern.replace('{{project_path}}', process.cwd());\n if (minimatch(path, resolved, { dot: true })) {\n return 'allow';\n }\n }\n\n // Not in allowed paths — deny\n return 'deny';\n }\n\n requiresApproval(role: string, tool: string): boolean {\n const r = this.getRole(role);\n\n // Auto-approve takes precedence\n if (r.human_approval.auto_approve?.includes(tool)) return false;\n\n // Check required list\n if (r.human_approval.required_for.includes('all')) return true;\n return r.human_approval.required_for.includes(tool);\n }\n\n getExecutionMode(role: string): ExecutionMode {\n return this.getRole(role).execution_mode;\n }\n\n getTemplateName(role: string): string {\n return this.getRole(role).prompt_template;\n }\n\n getBashOverrides(role: string): BashOverrides {\n const r = this.getRole(role);\n const overrides = r.bash_overrides;\n if (!overrides) return {};\n\n return {\n additionalBlocked: overrides.additional_blocked?.map((p) => new RegExp(p)),\n additionalAllowed: overrides.additional_allowed?.map((p) => new RegExp(p)),\n };\n }\n\n getTokenBudget(role: string): number {\n return this.getRole(role).token_budget_daily;\n }\n}\n","export const SAFE_PATTERNS: RegExp[] = [\n // File viewing\n /^(cat|head|tail|less|more)\\s/,\n /^(file|stat|wc|md5sum|sha256sum)\\s/,\n\n // Directory listing\n /^(ls|ll|la|tree|du|df)\\b/,\n /^(pwd|cd)\\b/,\n\n // Searching\n /^(grep|rg|ag|ack|find|fd|locate)\\s/,\n /^(which|whereis|type|command)\\s/,\n\n // Text processing (read-only)\n /^(sort|uniq|cut|awk|sed)\\s.*(?!-i)/, // sed without -i (in-place)\n /^(tr|diff|comm|join|paste)\\s/,\n /^(jq|yq|xmlstarlet)\\s/,\n\n // Git (read-only operations)\n /^git\\s+(log|status|diff|show|blame|branch|tag|remote|stash list)\\b/,\n /^git\\s+(ls-files|ls-tree|rev-parse|describe)\\b/,\n\n // System info\n /^(whoami|id|groups|uname|hostname|date|uptime|env|printenv)\\b/,\n /^(echo|printf)\\s/,\n\n // Package info (not install)\n /^(npm|yarn|pnpm)\\s+(list|ls|info|show|view|outdated|audit)\\b/,\n /^pip\\s+(list|show|freeze)\\b/,\n /^(node|python|ruby|go)\\s+--version\\b/,\n /^(node|python|ruby)\\s+-e\\s/,\n\n // Networking (read-only)\n /^(ping|dig|nslookup|host|traceroute|tracepath)\\s/,\n /^curl\\s.*--head\\b/,\n /^curl\\s.*-I\\b/,\n\n // Additional file viewing / inspection\n /^(basename|dirname|realpath|readlink)\\s/,\n /^(xxd|od|hexdump)\\s/,\n /^(strings|nm|objdump)\\s/,\n\n // Additional search / navigation\n /^(xargs)\\s/,\n /^(tee)\\s/,\n\n // Additional text processing (read-only)\n /^(fmt|fold|column|expand|unexpand)\\s/,\n /^(tac|rev|nl)\\s/,\n /^(yes|seq|shuf)\\s/,\n\n // Additional system info\n /^(lsof|ps|top|htop|vmstat|iostat|free|df)\\b/,\n /^(lscpu|lsblk|lsusb|lspci)\\b/,\n /^(nproc|getconf)\\b/,\n\n // Additional git read-only\n /^git\\s+(config\\s+--get|config\\s+-l|shortlog|reflog|cherry)\\b/,\n /^git\\s+(cat-file|count-objects|fsck|verify-pack)\\b/,\n];\n\nexport const DANGEROUS_PATTERNS: RegExp[] = [\n // Destructive file operations\n /\\brm\\s+(-[a-zA-Z]*r|-[a-zA-Z]*f|--recursive|--force)\\b/,\n /\\brm\\s+-[a-zA-Z]*rf\\b/,\n /\\bshred\\b/,\n\n // Privilege escalation\n /\\bsudo\\b/,\n /\\bsu\\s+-?\\s*\\w/,\n /\\bdoas\\b/,\n\n // Permission/ownership changes\n /\\bchmod\\b/,\n /\\bchown\\b/,\n /\\bchgrp\\b/,\n\n // Disk/partition operations\n /\\bdd\\b.*\\bof=/,\n /\\bmkfs\\b/,\n /\\bfdisk\\b/,\n /\\bparted\\b/,\n /\\bmount\\b/,\n /\\bumount\\b/,\n\n // Remote code execution\n /\\bcurl\\b.*\\|\\s*(bash|sh|zsh|python|perl|ruby)\\b/,\n /\\bwget\\b.*\\|\\s*(bash|sh|zsh|python|perl|ruby)\\b/,\n /\\bcurl\\b.*>\\s*.*\\.sh\\s*&&/,\n\n // Remote access\n /\\bssh\\b/,\n /\\bscp\\b/,\n /\\brsync\\b.*:\\//,\n /\\bnc\\s+(-[a-zA-Z]*l|-[a-zA-Z]*p|--listen)\\b/,\n /\\bncat\\b/,\n /\\bsocat\\b/,\n /\\btelnet\\b/,\n\n // System modification\n /\\bsystemctl\\s+(start|stop|restart|enable|disable)\\b/,\n /\\bservice\\s+\\w+\\s+(start|stop|restart)\\b/,\n /\\biptables\\b/,\n /\\bufw\\b/,\n /\\bfirewall-cmd\\b/,\n\n // Package installation (can run arbitrary post-install scripts)\n /\\bnpm\\s+(install|i|add|ci)\\b/,\n /\\byarn\\s+(add|install)\\b/,\n /\\bpnpm\\s+(add|install|i)\\b/,\n /\\bpip\\s+install\\b/,\n /\\bapt(-get)?\\s+install\\b/,\n /\\bbrew\\s+install\\b/,\n /\\bcargo\\s+install\\b/,\n\n // Environment variable manipulation (can leak secrets)\n /\\bexport\\b.*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,\n\n // Cron / scheduled tasks\n /\\bcrontab\\b/,\n /\\bat\\s+/,\n\n // Container escape vectors\n /\\bdocker\\s+(run|exec|build|push|pull)\\b/,\n /\\bkubectl\\s+(exec|run|apply|delete)\\b/,\n\n // Process manipulation\n /\\bkill\\b/,\n /\\bkillall\\b/,\n /\\bpkill\\b/,\n\n // History manipulation\n /\\bhistory\\s+-c\\b/,\n /\\bunset\\s+HISTFILE\\b/,\n\n // Compiler/build (can execute arbitrary code)\n /\\bmake\\s/,\n /\\bgcc\\b/,\n /\\bg\\+\\+/,\n];\n","import { SAFE_PATTERNS, DANGEROUS_PATTERNS } from './patterns.js';\nimport type { BashOverrides } from '../policy/engine.js';\n\nexport type BashClassification = 'safe' | 'dangerous' | 'needs_review';\n\nexport class BashClassifier {\n private safePatterns: RegExp[];\n private dangerousPatterns: RegExp[];\n\n constructor(overrides?: BashOverrides) {\n this.safePatterns = [...SAFE_PATTERNS, ...(overrides?.additionalAllowed ?? [])];\n this.dangerousPatterns = [...DANGEROUS_PATTERNS, ...(overrides?.additionalBlocked ?? [])];\n }\n\n classify(command: string): BashClassification {\n const trimmed = command.trim();\n\n // Check dangerous patterns against the full unsplit command first.\n // This catches patterns like \"curl ... | bash\" that span pipe boundaries.\n for (const pattern of this.dangerousPatterns) {\n if (pattern.test(trimmed)) return 'dangerous';\n }\n\n // Multi-command detection: if the command contains pipes, semicolons,\n // or && / ||, classify each segment independently and return the\n // most restrictive classification\n const segments = this.splitCommand(trimmed);\n\n if (segments.length > 1) {\n const classifications = segments.map((s) => this.classifySingle(s));\n if (classifications.includes('dangerous')) return 'dangerous';\n if (classifications.includes('needs_review')) return 'needs_review';\n return 'safe';\n }\n\n return this.classifySingle(trimmed);\n }\n\n private classifySingle(command: string): BashClassification {\n const trimmed = command.trim();\n\n // Check dangerous first (takes precedence)\n for (const pattern of this.dangerousPatterns) {\n if (pattern.test(trimmed)) return 'dangerous';\n }\n\n // Check safe\n for (const pattern of this.safePatterns) {\n if (pattern.test(trimmed)) return 'safe';\n }\n\n // Default: needs review\n return 'needs_review';\n }\n\n private splitCommand(command: string): string[] {\n // Split on pipes, semicolons, && and || while respecting quotes\n // This is a simplified parser — not a full shell parser\n const segments: string[] = [];\n let current = '';\n let inSingleQuote = false;\n let inDoubleQuote = false;\n let escaped = false;\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i]!;\n\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n\n if (char === '\\\\') {\n escaped = true;\n current += char;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n current += char;\n continue;\n }\n\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n current += char;\n continue;\n }\n\n if (!inSingleQuote && !inDoubleQuote) {\n if (char === '|' && command[i + 1] !== '|') {\n segments.push(current.trim());\n current = '';\n continue;\n }\n if (char === ';') {\n segments.push(current.trim());\n current = '';\n continue;\n }\n if (char === '&' && command[i + 1] === '&') {\n segments.push(current.trim());\n current = '';\n i++; // skip second &\n continue;\n }\n if (char === '|' && command[i + 1] === '|') {\n segments.push(current.trim());\n current = '';\n i++; // skip second |\n continue;\n }\n }\n\n current += char;\n }\n\n if (current.trim()) segments.push(current.trim());\n return segments.filter((s) => s.length > 0);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { AuditRecord, AuditEventType } from './schema.js';\nimport type { AuditSink } from './sinks/sink.js';\nimport { JsonlAuditSink } from './sinks/jsonl.js';\nimport { WebhookAuditSink } from './sinks/webhook.js';\n\ninterface AuditSinkConfig {\n type: 'jsonl' | 'webhook' | 'postgres';\n path?: string;\n url?: string;\n connection?: string;\n}\n\ninterface AuditConfig {\n sinks: AuditSinkConfig[];\n}\n\nexport class AuditLogger {\n private sinks: AuditSink[];\n private counts: Map<AuditEventType, number> = new Map();\n\n constructor(config?: AuditConfig) {\n const sinkConfigs = config?.sinks ?? [\n { type: 'jsonl' as const, path: '~/.pi/agent/audit.jsonl' },\n ];\n this.sinks = [];\n\n for (const sc of sinkConfigs) {\n if (sc.type === 'jsonl') {\n this.sinks.push(new JsonlAuditSink(sc.path ?? '~/.pi/agent/audit.jsonl'));\n } else if (sc.type === 'webhook' && sc.url) {\n this.sinks.push(new WebhookAuditSink(sc.url));\n }\n // postgres: skip for now\n }\n\n // Ensure at least one sink\n if (this.sinks.length === 0) {\n this.sinks.push(new JsonlAuditSink('~/.pi/agent/audit.jsonl'));\n }\n }\n\n async log(record: Omit<AuditRecord, 'id' | 'timestamp'>): Promise<void> {\n const full: AuditRecord = {\n ...record,\n id: randomUUID(),\n timestamp: new Date().toISOString(),\n };\n\n this.counts.set(full.event, (this.counts.get(full.event) ?? 0) + 1);\n\n await Promise.all(this.sinks.map((s) => s.write(full as unknown as Record<string, unknown>)));\n }\n\n async flush(): Promise<void> {\n await Promise.all(this.sinks.map((s) => s.flush()));\n }\n\n getSummary(): Map<AuditEventType, number> {\n return new Map(this.counts);\n }\n}\n","import { appendFile, mkdir } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { AuditSink } from './sink.js';\n\nexport class JsonlAuditSink implements AuditSink {\n private path: string;\n private buffer: Record<string, unknown>[] = [];\n private readonly flushThreshold = 10;\n\n constructor(path: string) {\n this.path = path.replace(/^~/, homedir());\n }\n\n async write(record: Record<string, unknown>): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const lines = this.buffer.map((r) => JSON.stringify(r)).join('\\n') + '\\n';\n this.buffer = [];\n await mkdir(dirname(this.path), { recursive: true });\n await appendFile(this.path, lines, 'utf-8');\n }\n}\n","import type { AuditSink } from './sink.js';\n\nexport class WebhookAuditSink implements AuditSink {\n private url: string;\n private buffer: Record<string, unknown>[] = [];\n private readonly flushThreshold = 10;\n\n constructor(url: string) {\n this.url = url;\n }\n\n async write(record: Record<string, unknown>): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const records = [...this.buffer];\n this.buffer = [];\n\n try {\n await this.send(records);\n } catch {\n // Retry once\n try {\n await this.send(records);\n } catch {\n // Drop records after second failure\n }\n }\n }\n\n private async send(records: Record<string, unknown>[]): Promise<void> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(records),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Webhook returned ${response.status}`);\n }\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n","import type { ApprovalFlow, ApprovalResult, GovernanceToolCall, ConfirmUI } from './approval.js';\n\nexport class CliApprover implements ApprovalFlow {\n private ui: ConfirmUI;\n private timeoutSeconds: number;\n\n constructor(ui: ConfirmUI, timeoutSeconds: number = 300) {\n this.ui = ui;\n this.timeoutSeconds = timeoutSeconds;\n }\n\n async requestApproval(\n toolCall: GovernanceToolCall,\n context: { userId: string; role: string; orgUnit: string },\n ): Promise<ApprovalResult> {\n const title = `Approval Required: ${toolCall.toolName}`;\n const inputSummary = Object.entries(toolCall.input)\n .map(\n ([k, v]) =>\n ` ${k}: ${typeof v === 'string' ? v.slice(0, 200) : JSON.stringify(v).slice(0, 200)}`,\n )\n .join('\\n');\n const message = `User: ${context.userId} (${context.role})\\nOrg: ${context.orgUnit}\\n\\nTool: ${toolCall.toolName}\\nInput:\\n${inputSummary}`;\n\n const start = Date.now();\n\n try {\n const approved = await this.ui.confirm(title, message, {\n timeout: this.timeoutSeconds * 1000,\n });\n\n return {\n approved,\n approver: 'cli',\n duration: Date.now() - start,\n reason: approved ? undefined : 'Denied by user',\n };\n } catch {\n // Timeout or error — deny\n return {\n approved: false,\n approver: 'cli',\n duration: Date.now() - start,\n reason: 'Approval timed out',\n };\n }\n }\n}\n","import type { ApprovalFlow, ApprovalResult, GovernanceToolCall } from './approval.js';\n\nexport class WebhookApprover implements ApprovalFlow {\n private url: string;\n private timeoutMs: number;\n\n constructor(url: string, timeoutSeconds: number = 300) {\n this.url = url;\n this.timeoutMs = timeoutSeconds * 1000;\n }\n\n async requestApproval(\n toolCall: GovernanceToolCall,\n context: { userId: string; role: string; orgUnit: string },\n ): Promise<ApprovalResult> {\n const start = Date.now();\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n toolCall: { toolName: toolCall.toolName, input: toolCall.input },\n context,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n return {\n approved: false,\n approver: 'webhook',\n duration: Date.now() - start,\n reason: `Webhook returned ${response.status}`,\n };\n }\n\n const body = (await response.json()) as { approved: boolean; reason?: string };\n\n return {\n approved: body.approved,\n approver: 'webhook',\n duration: Date.now() - start,\n reason: body.reason,\n };\n } catch (err) {\n return {\n approved: false,\n approver: 'webhook',\n duration: Date.now() - start,\n reason:\n err instanceof Error && err.name === 'AbortError'\n ? 'Webhook timed out'\n : 'Webhook request failed',\n };\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n","import { CliApprover } from './cli-approver.js';\nimport { WebhookApprover } from './webhook-approver.js';\n\nexport interface GovernanceToolCall {\n toolName: string;\n input: Record<string, unknown>;\n}\n\nexport interface ApprovalResult {\n approved: boolean;\n reason?: string;\n approver: string;\n duration: number;\n}\n\nexport interface ApprovalFlow {\n requestApproval(\n toolCall: GovernanceToolCall,\n context: { userId: string; role: string; orgUnit: string },\n ): Promise<ApprovalResult>;\n}\n\nexport interface ConfirmUI {\n confirm(title: string, message: string, opts?: { timeout?: number }): Promise<boolean>;\n}\n\nexport interface HitlConfig {\n default_mode: 'autonomous' | 'supervised' | 'dry_run';\n approval_channel: 'cli' | 'webhook';\n timeout_seconds: number;\n webhook?: { url: string };\n}\n\nexport function createApprovalFlow(config: HitlConfig, ui?: ConfirmUI): ApprovalFlow {\n if (config.approval_channel === 'webhook' && config.webhook?.url) {\n return new WebhookApprover(config.webhook.url, config.timeout_seconds);\n }\n\n // Fall back to CLI (also handles webhook without URL)\n if (!ui) {\n throw new Error('CLI approval channel requires a ConfirmUI (ExtensionContext.ui)');\n }\n\n return new CliApprover(ui, config.timeout_seconds);\n}\n","/**\n * Tracks tool invocation count as a proxy for token budget.\n * The budget value represents max invocations per session; -1 means unlimited.\n */\nexport class BudgetTracker {\n private _used = 0;\n private readonly _budget: number;\n\n constructor(budget: number) {\n this._budget = budget;\n }\n\n /** Returns false if consuming would exceed the budget. On success, increments the counter. */\n consume(amount = 1): boolean {\n if (this._budget === -1) {\n this._used += amount;\n return true;\n }\n if (this._used + amount > this._budget) return false;\n this._used += amount;\n return true;\n }\n\n remaining(): number {\n if (this._budget === -1) return Infinity;\n return Math.max(0, this._budget - this._used);\n }\n\n used(): number {\n return this._used;\n }\n\n isUnlimited(): boolean {\n return this._budget === -1;\n }\n}\n","import { watch, readFileSync, type FSWatcher } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { Value } from '@sinclair/typebox/value';\nimport { GovernanceConfigSchema, type GovernanceConfig } from './schema.js';\n\n/**\n * Watches a governance config file for changes and triggers a validated reload.\n * Uses fs.watch() with a 500ms debounce to avoid rapid reloads.\n */\nexport class ConfigWatcher {\n private watcher: FSWatcher | undefined;\n private debounceTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly configPath: string;\n private readonly onChange: (config: GovernanceConfig) => void;\n private readonly onError?: (error: Error) => void;\n\n constructor(\n configPath: string,\n onChange: (config: GovernanceConfig) => void,\n onError?: (error: Error) => void,\n ) {\n this.configPath = configPath;\n this.onChange = onChange;\n this.onError = onError;\n }\n\n start(): void {\n if (this.watcher) return;\n this.watcher = watch(this.configPath, () => this.handleChange());\n }\n\n stop(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = undefined;\n }\n if (this.watcher) {\n this.watcher.close();\n this.watcher = undefined;\n }\n }\n\n private handleChange(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => this.reload(), 500);\n }\n\n private reload(): void {\n try {\n const raw = readFileSync(this.configPath, 'utf-8');\n const parsed = parseYaml(raw);\n const errors = [...Value.Errors(GovernanceConfigSchema, parsed)];\n if (errors.length > 0) {\n const msg = errors.map((e) => `${e.path}: ${e.message}`).join('; ');\n this.onError?.(new Error(`Config validation failed: ${msg}`));\n return;\n }\n const config = Value.Default(GovernanceConfigSchema, parsed) as GovernanceConfig;\n this.onChange(config);\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }\n}\n","export type DlpSeverity = 'low' | 'medium' | 'high' | 'critical';\nexport type DlpCategory = 'secret' | 'pii' | 'custom';\n\nexport interface DlpPatternDef {\n name: string;\n pattern: RegExp;\n severity: DlpSeverity;\n category: DlpCategory;\n}\n\nexport const SECRET_PATTERNS: DlpPatternDef[] = [\n // AWS\n {\n name: 'aws_access_key',\n pattern: /\\b(AKIA[0-9A-Z]{16})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n {\n name: 'aws_secret_key',\n pattern: /\\b([A-Za-z0-9/+=]{40})(?=\\s|$|\"|')/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // GitHub\n {\n name: 'github_pat',\n pattern: /\\b(ghp_[A-Za-z0-9]{36,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n {\n name: 'github_oauth',\n pattern: /\\b(gho_[A-Za-z0-9]{36,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n {\n name: 'github_app_token',\n pattern: /\\b(ghu_[A-Za-z0-9]{36,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Anthropic\n {\n name: 'anthropic_api_key',\n pattern: /\\b(sk-ant-api03-[A-Za-z0-9_-]{90,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // OpenAI\n {\n name: 'openai_api_key',\n pattern: /\\b(sk-[A-Za-z0-9]{20,}T3BlbkFJ[A-Za-z0-9]{20,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // JWT\n {\n name: 'jwt_token',\n pattern: /\\b(eyJ[A-Za-z0-9_-]{10,}\\.eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Private key headers\n {\n name: 'private_key',\n pattern: /-----BEGIN\\s+(RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // Database connection strings\n {\n name: 'database_url',\n pattern: /\\b((?:postgres|mysql|mongodb|redis):\\/\\/[^\\s'\"]{10,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Slack\n {\n name: 'slack_token',\n pattern: /\\b(xox[bpras]-[A-Za-z0-9-]{10,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Stripe\n {\n name: 'stripe_key',\n pattern: /\\b([rs]k_(?:live|test)_[A-Za-z0-9]{20,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // npm\n {\n name: 'npm_token',\n pattern: /\\b(npm_[A-Za-z0-9]{36,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // SendGrid\n {\n name: 'sendgrid_key',\n pattern: /\\b(SG\\.[A-Za-z0-9_-]{22,}\\.[A-Za-z0-9_-]{22,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Generic API key patterns (env-var style assignments)\n {\n name: 'generic_api_key',\n pattern:\n /\\b(?:API_KEY|API_SECRET|ACCESS_TOKEN|AUTH_TOKEN|SECRET_KEY)\\s*[=:]\\s*['\"]?([A-Za-z0-9_-]{16,})['\"]?/gi,\n severity: 'medium',\n category: 'secret',\n },\n\n // High-entropy string near keyword context\n {\n name: 'generic_secret_assignment',\n pattern: /\\b(?:password|passwd|secret|token|credential)\\s*[=:]\\s*['\"]([^'\"]{8,})['\"]?/gi,\n severity: 'medium',\n category: 'secret',\n },\n];\n\nexport const PII_PATTERNS: DlpPatternDef[] = [\n // SSN (US)\n {\n name: 'ssn',\n pattern: /\\b(\\d{3}-\\d{2}-\\d{4})\\b/g,\n severity: 'critical',\n category: 'pii',\n },\n\n // Credit card numbers\n {\n name: 'credit_card',\n pattern:\n /\\b(4\\d{3}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}|5[1-5]\\d{2}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}|3[47]\\d{2}[\\s-]?\\d{6}[\\s-]?\\d{5}|6(?:011|5\\d{2})[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4})\\b/g,\n severity: 'critical',\n category: 'pii',\n },\n\n // Email address\n {\n name: 'email',\n pattern: /\\b([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})\\b/g,\n severity: 'low',\n category: 'pii',\n },\n\n // US phone number\n {\n name: 'phone_us',\n pattern: /\\b(\\+?1?[-.\\s]?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4})\\b/g,\n severity: 'medium',\n category: 'pii',\n },\n\n // IPv4 address\n {\n name: 'ipv4',\n pattern:\n /\\b((?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?))\\b/g,\n severity: 'low',\n category: 'pii',\n },\n];\n","import { SECRET_PATTERNS, PII_PATTERNS } from './patterns.js';\nimport type { DlpPatternDef, DlpSeverity, DlpCategory } from './patterns.js';\n\nexport type DlpAction = 'audit' | 'mask' | 'block';\n\nexport interface DlpMatch {\n patternName: string;\n category: DlpCategory;\n severity: DlpSeverity;\n start: number;\n end: number;\n matched: string;\n}\n\nexport interface DlpScanResult {\n hasMatches: boolean;\n matches: DlpMatch[];\n}\n\nexport interface DlpCustomPattern {\n name: string;\n pattern: string;\n severity: DlpSeverity;\n action?: DlpAction;\n}\n\nexport interface DlpAllowlistEntry {\n pattern: string;\n}\n\nexport interface DlpScannerConfig {\n enabled: boolean;\n mode: DlpAction;\n on_input?: DlpAction;\n on_output?: DlpAction;\n severity_threshold: DlpSeverity;\n built_in: { secrets: boolean; pii: boolean };\n custom_patterns: DlpCustomPattern[];\n allowlist: DlpAllowlistEntry[];\n pattern_overrides: Map<string, DlpAction>;\n}\n\nconst SEVERITY_ORDER: Record<DlpSeverity, number> = {\n low: 0,\n medium: 1,\n high: 2,\n critical: 3,\n};\n\ninterface CompiledPattern {\n def: DlpPatternDef;\n action?: DlpAction;\n}\n\nexport class DlpScanner {\n private patterns: CompiledPattern[];\n private allowlistRegexps: RegExp[];\n private severityThreshold: number;\n private config: DlpScannerConfig;\n\n constructor(config: DlpScannerConfig) {\n this.config = config;\n this.severityThreshold = SEVERITY_ORDER[config.severity_threshold];\n this.patterns = [];\n this.allowlistRegexps = [];\n\n // Compile built-in patterns\n if (config.built_in.secrets) {\n for (const def of SECRET_PATTERNS) {\n this.patterns.push({ def });\n }\n }\n if (config.built_in.pii) {\n for (const def of PII_PATTERNS) {\n this.patterns.push({ def });\n }\n }\n\n // Compile custom patterns\n for (const cp of config.custom_patterns) {\n const def: DlpPatternDef = {\n name: cp.name,\n pattern: new RegExp(cp.pattern, 'g'),\n severity: cp.severity,\n category: 'custom',\n };\n this.patterns.push({ def, action: cp.action });\n }\n\n // Compile pattern overrides from config\n for (const compiled of this.patterns) {\n const override = config.pattern_overrides.get(compiled.def.name);\n if (override) {\n compiled.action = override;\n }\n }\n\n // Compile allowlist\n for (const entry of config.allowlist) {\n this.allowlistRegexps.push(new RegExp(entry.pattern));\n }\n }\n\n scan(text: string): DlpScanResult {\n if (!this.config.enabled || text.length === 0) {\n return { hasMatches: false, matches: [] };\n }\n\n const matches: DlpMatch[] = [];\n\n for (const compiled of this.patterns) {\n // Skip patterns below severity threshold\n if (SEVERITY_ORDER[compiled.def.severity] < this.severityThreshold) {\n continue;\n }\n\n // Reset the regex (global flag means lastIndex needs reset)\n const regex = new RegExp(compiled.def.pattern.source, compiled.def.pattern.flags);\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n // Use the first capturing group if present, otherwise the full match\n const matched = match[1] ?? match[0];\n const start = match[1] ? match.index + match[0].indexOf(match[1]) : match.index;\n const end = start + matched.length;\n\n // Check allowlist\n if (this.isAllowlisted(matched)) {\n continue;\n }\n\n matches.push({\n patternName: compiled.def.name,\n category: compiled.def.category,\n severity: compiled.def.severity,\n start,\n end,\n matched,\n });\n }\n }\n\n return { hasMatches: matches.length > 0, matches };\n }\n\n getAction(direction: 'input' | 'output'): DlpAction {\n if (direction === 'input' && this.config.on_input) {\n return this.config.on_input;\n }\n if (direction === 'output' && this.config.on_output) {\n return this.config.on_output;\n }\n return this.config.mode;\n }\n\n getPatternAction(match: DlpMatch, direction: 'input' | 'output'): DlpAction {\n // Check per-pattern override first\n const compiled = this.patterns.find((p) => p.def.name === match.patternName);\n if (compiled?.action) {\n return compiled.action;\n }\n\n // Fall back to directional override or global mode\n return this.getAction(direction);\n }\n\n private isAllowlisted(value: string): boolean {\n for (const re of this.allowlistRegexps) {\n if (re.test(value)) return true;\n }\n return false;\n }\n}\n\nexport function compareSeverity(a: DlpSeverity, b: DlpSeverity): number {\n return SEVERITY_ORDER[a] - SEVERITY_ORDER[b];\n}\n","import { createHash } from 'node:crypto';\nimport type { DlpMatch } from './scanner.js';\n\nexport interface MaskingConfig {\n strategy: 'partial' | 'full' | 'hash';\n show_chars: number;\n placeholder: string;\n}\n\nconst DEFAULT_CONFIG: MaskingConfig = {\n strategy: 'partial',\n show_chars: 4,\n placeholder: '***',\n};\n\nexport class DlpMasker {\n private config: MaskingConfig;\n\n constructor(config?: Partial<MaskingConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n maskValue(value: string): string {\n switch (this.config.strategy) {\n case 'full':\n return this.config.placeholder;\n case 'hash': {\n const hash = createHash('sha256').update(value).digest('hex').slice(0, 8);\n return `[REDACTED:${hash}]`;\n }\n case 'partial':\n default: {\n if (value.length <= this.config.show_chars) {\n return this.config.placeholder;\n }\n return this.config.placeholder + value.slice(-this.config.show_chars);\n }\n }\n }\n\n maskText(text: string, matches: DlpMatch[]): string {\n if (matches.length === 0) return text;\n\n // Sort by position descending to avoid index shifting\n const sorted = [...matches].sort((a, b) => b.start - a.start);\n\n let result = text;\n for (const match of sorted) {\n const masked = this.maskValue(match.matched);\n result = result.slice(0, match.start) + masked + result.slice(match.end);\n }\n return result;\n }\n}\n"],"mappings":"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","names":["parseYaml","import_fs","import_yaml","parseYaml","import_fs","import_yaml","parseYaml","import_yaml","import_value","parseYaml","import_node_crypto"]}
|
|
1
|
+
{"version":3,"sources":["../../src/extensions/index.ts","../../src/lib/config/loader.ts","../../src/lib/config/schema.ts","../../src/lib/config/defaults.ts","../../src/lib/identity/env-provider.ts","../../src/lib/identity/local-provider.ts","../../src/lib/identity/chain.ts","../../src/lib/policy/yaml-engine.ts","../../src/lib/bash/patterns.ts","../../src/lib/bash/classifier.ts","../../src/lib/audit/logger.ts","../../src/lib/audit/sinks/jsonl.ts","../../src/lib/audit/sinks/webhook.ts","../../src/lib/hitl/cli-approver.ts","../../src/lib/hitl/webhook-approver.ts","../../src/lib/hitl/approval.ts","../../src/lib/budget/tracker.ts","../../src/lib/config/watcher.ts","../../src/lib/dlp/patterns.ts","../../src/lib/dlp/scanner.ts","../../src/lib/dlp/masker.ts"],"sourcesContent":["// Pi Extension API types — locally defined to avoid hard dependency on @mariozechner/pi-coding-agent\n// These match the real Pi extension API surface.\n\ninterface ToolCallEvent {\n toolName: string;\n input: Record<string, unknown>;\n}\n\ninterface ToolResultEvent {\n toolName: string;\n input: Record<string, unknown>;\n output: string;\n isError: boolean;\n}\n\ninterface ExtensionUI {\n confirm(title: string, message: string, opts?: { timeout?: number }): Promise<boolean>;\n notify(msg: string, type?: 'info' | 'warning' | 'error'): void;\n setStatus(key: string, text: string): void;\n}\n\ninterface ExtensionContext {\n ui: ExtensionUI;\n sessionId: string;\n workingDirectory: string;\n}\n\ntype ToolCallHandler = (\n event: ToolCallEvent,\n ctx: ExtensionContext,\n) => Promise<{ block: true; reason: string } | void>;\n\ntype ToolResultHandler = (event: ToolResultEvent, ctx: ExtensionContext) => Promise<void>;\n\ntype SessionHandler = (event: unknown, ctx: ExtensionContext) => Promise<void>;\n\ninterface ExtensionAPI {\n on(event: 'session_start', handler: SessionHandler): void;\n on(event: 'session_shutdown', handler: SessionHandler): void;\n on(event: 'tool_call', handler: ToolCallHandler): void;\n on(event: 'tool_result', handler: ToolResultHandler): void;\n registerCommand(\n name: string,\n opts: {\n description?: string;\n handler: (args: string, ctx: ExtensionContext) => Promise<void>;\n },\n ): void;\n}\n\ntype ExtensionFactory = (pi: ExtensionAPI) => void;\n\n// --- Implementation ---\n\nimport { existsSync } from 'node:fs';\nimport { loadConfig } from '../lib/config/loader.js';\nimport { createIdentityChain } from '../lib/identity/chain.js';\nimport { YamlPolicyEngine } from '../lib/policy/yaml-engine.js';\nimport { BashClassifier } from '../lib/bash/classifier.js';\nimport { AuditLogger } from '../lib/audit/logger.js';\nimport { createApprovalFlow } from '../lib/hitl/approval.js';\nimport { BudgetTracker } from '../lib/budget/tracker.js';\nimport { ConfigWatcher } from '../lib/config/watcher.js';\nimport { DlpScanner } from '../lib/dlp/scanner.js';\nimport { DlpMasker } from '../lib/dlp/masker.js';\nimport type { DlpAction, DlpMatch, DlpScannerConfig } from '../lib/dlp/scanner.js';\nimport type { ApprovalFlow } from '../lib/hitl/approval.js';\nimport type { PolicyEngine, ExecutionMode } from '../lib/policy/engine.js';\nimport type { ResolvedIdentity } from '../lib/identity/provider.js';\nimport type { GovernanceConfig, DlpConfigType } from '../lib/config/schema.js';\n\n// Tools that involve file paths — used for path boundary checks\nconst PATH_TOOLS: Record<string, string> = {\n read: 'path',\n write: 'path',\n edit: 'file_path',\n grep: 'path',\n find: 'path',\n ls: 'path',\n};\n\n// Tools that are write operations for path checking\nconst WRITE_TOOLS = new Set(['write', 'edit']);\n\nfunction summarizeParams(\n toolName: string,\n input: Record<string, unknown>,\n): Record<string, unknown> {\n switch (toolName) {\n case 'bash': {\n const cmd = typeof input['command'] === 'string' ? input['command'] : '';\n return { command: cmd.slice(0, 100) + (cmd.length > 100 ? '...' : '') };\n }\n case 'read':\n return { path: input['path'] };\n case 'write':\n return { path: input['path'] };\n case 'edit':\n return { file_path: input['file_path'] };\n case 'grep':\n return { pattern: input['pattern'], path: input['path'] };\n case 'find':\n case 'ls':\n return { path: input['path'] };\n default:\n return {};\n }\n}\n\nfunction extractPath(toolName: string, input: Record<string, unknown>): string | undefined {\n const key = PATH_TOOLS[toolName];\n if (!key) return undefined;\n const val = input[key];\n return typeof val === 'string' ? val : undefined;\n}\n\n// --- DLP helpers ---\n\nconst ACTION_PRIORITY: Record<DlpAction, number> = { audit: 0, mask: 1, block: 2 };\n\nfunction extractDlpFields(toolName: string, input: Record<string, unknown>): Map<string, string> {\n const fields = new Map<string, string>();\n switch (toolName) {\n case 'bash': {\n const cmd = input['command'];\n if (typeof cmd === 'string') fields.set('command', cmd);\n break;\n }\n case 'write': {\n const content = input['content'];\n if (typeof content === 'string') fields.set('content', content);\n const path = input['path'];\n if (typeof path === 'string') fields.set('path', path);\n break;\n }\n case 'edit': {\n const newStr = input['new_string'];\n if (typeof newStr === 'string') fields.set('new_string', newStr);\n const oldStr = input['old_string'];\n if (typeof oldStr === 'string') fields.set('old_string', oldStr);\n break;\n }\n default: {\n // Scan all string values\n for (const [key, val] of Object.entries(input)) {\n if (typeof val === 'string') fields.set(key, val);\n }\n }\n }\n return fields;\n}\n\nfunction resolveHighestAction(\n scanner: DlpScanner,\n matches: DlpMatch[],\n direction: 'input' | 'output',\n): DlpAction {\n let highest: DlpAction = 'audit';\n for (const match of matches) {\n const action = scanner.getPatternAction(match, direction);\n if (ACTION_PRIORITY[action] > ACTION_PRIORITY[highest]) {\n highest = action;\n }\n }\n return highest;\n}\n\nfunction resolveDlpConfig(\n dlpConfig: DlpConfigType | undefined,\n role: string,\n): DlpScannerConfig | undefined {\n if (!dlpConfig?.enabled) return undefined;\n\n // Apply role overrides\n const roleOverride = dlpConfig.role_overrides?.[role];\n if (roleOverride?.enabled === false) return undefined;\n\n const patternOverrides = new Map<string, DlpAction>();\n\n return {\n enabled: true,\n mode: roleOverride?.mode ?? dlpConfig.mode ?? 'audit',\n on_input: roleOverride?.on_input ?? dlpConfig.on_input,\n on_output: roleOverride?.on_output ?? dlpConfig.on_output,\n severity_threshold: dlpConfig.severity_threshold ?? 'low',\n built_in: {\n secrets: dlpConfig.built_in?.secrets ?? true,\n pii: dlpConfig.built_in?.pii ?? true,\n },\n custom_patterns: (dlpConfig.custom_patterns ?? []).map((cp) => ({\n name: cp.name,\n pattern: cp.pattern,\n severity: cp.severity,\n action: cp.action as DlpAction | undefined,\n })),\n allowlist: dlpConfig.allowlist ?? [],\n pattern_overrides: patternOverrides,\n };\n}\n\nconst piGovernance: ExtensionFactory = (pi) => {\n // State — initialized in session_start\n let config: GovernanceConfig;\n let policyEngine: PolicyEngine;\n let audit: AuditLogger;\n let approvalFlow: ApprovalFlow | undefined;\n let bashClassifier: BashClassifier;\n let identity: ResolvedIdentity;\n let executionMode: ExecutionMode;\n let sessionId: string;\n let budgetTracker: BudgetTracker;\n let configWatcher: ConfigWatcher | undefined;\n let dlpScanner: DlpScanner | undefined;\n let dlpMasker: DlpMasker | undefined;\n\n const stats = {\n allowed: 0,\n denied: 0,\n approvals: 0,\n dryRun: 0,\n budgetExceeded: 0,\n dlpBlocked: 0,\n dlpDetected: 0,\n dlpMasked: 0,\n };\n\n pi.on('session_start', async (_event, ctx) => {\n sessionId = ctx.sessionId;\n\n // 1. Load config\n const loaded = loadConfig();\n config = loaded.config;\n\n // 2. Resolve identity\n const chain = createIdentityChain(config.auth);\n identity = await chain.resolve();\n\n // 3. Create policy engine\n const rulesFile = config.policy?.yaml?.rules_file ?? './governance-rules.yaml';\n if (existsSync(rulesFile)) {\n policyEngine = new YamlPolicyEngine(rulesFile);\n } else {\n // No rules file found — use permissive defaults so the extension doesn't crash\n policyEngine = new YamlPolicyEngine({\n roles: {\n admin: {\n allowed_tools: ['all'],\n blocked_tools: [],\n prompt_template: 'admin',\n execution_mode: 'autonomous',\n human_approval: { required_for: [] },\n token_budget_daily: -1,\n allowed_paths: ['**'],\n blocked_paths: [],\n },\n project_lead: {\n allowed_tools: ['all'],\n blocked_tools: [],\n prompt_template: 'project-lead',\n execution_mode: 'supervised',\n human_approval: { required_for: ['bash', 'write'] },\n token_budget_daily: -1,\n allowed_paths: ['**'],\n blocked_paths: [],\n },\n analyst: {\n allowed_tools: ['read', 'grep', 'find', 'ls'],\n blocked_tools: ['write', 'edit', 'bash'],\n prompt_template: 'analyst',\n execution_mode: 'supervised',\n human_approval: { required_for: ['all'] },\n token_budget_daily: -1,\n allowed_paths: ['**'],\n blocked_paths: [],\n },\n },\n });\n ctx.ui.notify(`Rules file not found: ${rulesFile} — using built-in defaults`, 'warning');\n }\n\n // 4. Get execution mode\n executionMode = policyEngine.getExecutionMode(identity.role);\n\n // 5. Create bash classifier with role overrides\n const bashOverrides = policyEngine.getBashOverrides(identity.role);\n bashClassifier = new BashClassifier(bashOverrides);\n\n // 6. Create audit logger\n audit = new AuditLogger(config.audit);\n\n // 7. Create approval flow if supervised mode\n if (executionMode === 'supervised') {\n try {\n approvalFlow = createApprovalFlow(\n {\n default_mode: config.hitl?.default_mode ?? 'supervised',\n approval_channel: config.hitl?.approval_channel ?? 'cli',\n timeout_seconds: config.hitl?.timeout_seconds ?? 300,\n webhook: config.hitl?.webhook,\n },\n ctx.ui,\n );\n } catch {\n // If CLI UI not available, approval flow stays undefined\n }\n }\n\n // 8. Create budget tracker\n const budget = policyEngine.getTokenBudget(identity.role);\n budgetTracker = new BudgetTracker(budget);\n\n // 9. Initialize DLP scanner/masker if enabled\n const dlpCfg = resolveDlpConfig(config.dlp, identity.role);\n if (dlpCfg) {\n dlpScanner = new DlpScanner(dlpCfg);\n dlpMasker = new DlpMasker(config.dlp?.masking);\n }\n\n // 10. Start config watcher\n if (loaded.source !== 'built-in') {\n configWatcher = new ConfigWatcher(\n loaded.source,\n (newConfig) => {\n config = newConfig;\n const newRulesFile = newConfig.policy?.yaml?.rules_file ?? './governance-rules.yaml';\n if (existsSync(newRulesFile)) {\n policyEngine = new YamlPolicyEngine(newRulesFile);\n }\n const newOverrides = policyEngine.getBashOverrides(identity.role);\n bashClassifier = new BashClassifier(newOverrides);\n // Recreate DLP scanner/masker on config reload\n const newDlpCfg = resolveDlpConfig(newConfig.dlp, identity.role);\n if (newDlpCfg) {\n dlpScanner = new DlpScanner(newDlpCfg);\n dlpMasker = new DlpMasker(newConfig.dlp?.masking);\n } else {\n dlpScanner = undefined;\n dlpMasker = undefined;\n }\n audit.log({\n sessionId,\n event: 'config_reloaded',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n metadata: { source: loaded.source },\n });\n ctx.ui.notify('Governance config reloaded', 'info');\n },\n (error) => {\n ctx.ui.notify(`Config reload failed: ${error.message}`, 'warning');\n },\n );\n configWatcher.start();\n }\n\n // 10. Audit session start\n await audit.log({\n sessionId,\n event: 'session_start',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n metadata: { source: loaded.source, executionMode },\n });\n\n // 11. UI feedback\n ctx.ui.setStatus('governance', `Governance: ${identity.role} (${executionMode})`);\n ctx.ui.notify(\n `Governance active — Role: ${identity.role} | Mode: ${executionMode} | Org: ${identity.orgUnit}`,\n 'info',\n );\n });\n\n pi.on('tool_call', async (event, _ctx) => {\n const { toolName, input } = event;\n const params = summarizeParams(toolName, input);\n\n const baseRecord = {\n sessionId,\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: toolName,\n input: params,\n };\n\n // 1. Dry-run mode — block everything, log as dry_run\n if (executionMode === 'dry_run') {\n stats.dryRun++;\n await audit.log({\n ...baseRecord,\n event: 'tool_dry_run',\n decision: 'blocked',\n reason: 'Dry-run mode',\n });\n return { block: true, reason: 'Dry-run mode: tool execution blocked for observation' };\n }\n\n // 2. Budget check\n if (!budgetTracker.consume()) {\n stats.budgetExceeded++;\n await audit.log({\n ...baseRecord,\n event: 'budget_exceeded',\n decision: 'denied',\n reason: `Budget exhausted (${budgetTracker.used()} invocations used)`,\n });\n return {\n block: true,\n reason: `Tool invocation budget exhausted (${budgetTracker.used()} used). Session limit reached.`,\n };\n }\n\n // 3. Policy: evaluate tool access\n const toolDecision = policyEngine.evaluateTool(identity.role, toolName);\n if (toolDecision === 'deny') {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'tool_denied',\n decision: 'denied',\n reason: 'Policy denied tool',\n });\n return { block: true, reason: `Policy denies ${identity.role} from using ${toolName}` };\n }\n\n // 4. Bash-specific classification\n if (toolName === 'bash') {\n const command = typeof input['command'] === 'string' ? input['command'] : '';\n const classification = bashClassifier.classify(command);\n\n if (classification === 'dangerous') {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'bash_denied',\n decision: 'denied',\n reason: 'Dangerous command',\n });\n return { block: true, reason: `Dangerous bash command blocked: ${command.slice(0, 80)}` };\n }\n\n // needs_review with approval required\n if (\n classification === 'needs_review' &&\n policyEngine.requiresApproval(identity.role, 'bash')\n ) {\n if (approvalFlow) {\n stats.approvals++;\n await audit.log({ ...baseRecord, event: 'approval_requested' });\n\n const result = await approvalFlow.requestApproval(\n { toolName, input },\n { userId: identity.userId, role: identity.role, orgUnit: identity.orgUnit },\n );\n\n if (result.approved) {\n await audit.log({\n ...baseRecord,\n event: 'approval_granted',\n duration: result.duration,\n });\n } else {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'approval_denied',\n reason: result.reason,\n duration: result.duration,\n });\n return { block: true, reason: result.reason ?? 'Approval denied' };\n }\n } else {\n // No approval flow — deny\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'tool_denied',\n decision: 'denied',\n reason: 'Requires approval but no approval channel',\n });\n return {\n block: true,\n reason: 'Bash command requires approval but no approval channel is configured',\n };\n }\n }\n }\n\n // 5. Path boundary check for file tools\n const path = extractPath(toolName, input);\n if (path) {\n const operation = WRITE_TOOLS.has(toolName) ? 'write' : 'read';\n const pathDecision = policyEngine.evaluatePath(\n identity.role,\n identity.orgUnit,\n operation,\n path,\n );\n if (pathDecision === 'deny') {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'path_denied',\n decision: 'denied',\n reason: `Path denied: ${path}`,\n });\n return { block: true, reason: `Access denied to path: ${path}` };\n }\n }\n\n // 6. DLP scan inputs\n if (dlpScanner && dlpMasker) {\n const fields = extractDlpFields(toolName, input);\n const allMatches: DlpMatch[] = [];\n for (const [, fieldValue] of fields) {\n const result = dlpScanner.scan(fieldValue);\n allMatches.push(...result.matches);\n }\n\n if (allMatches.length > 0) {\n const action = resolveHighestAction(dlpScanner, allMatches, 'input');\n const patternNames = [...new Set(allMatches.map((m) => m.patternName))];\n const severities = [...new Set(allMatches.map((m) => m.severity))];\n const dlpMeta = {\n patterns: patternNames,\n severities,\n direction: 'input' as const,\n count: allMatches.length,\n };\n\n if (action === 'block') {\n stats.dlpBlocked++;\n await audit.log({\n ...baseRecord,\n event: 'dlp_blocked',\n decision: 'denied',\n reason: `DLP: ${patternNames.join(', ')} detected in input`,\n metadata: dlpMeta,\n });\n return {\n block: true,\n reason: `DLP blocked: sensitive data detected (${patternNames.join(', ')})`,\n };\n }\n\n if (action === 'mask') {\n stats.dlpMasked++;\n // Mask each field independently to maintain correct positions\n for (const [fieldKey, fieldValue] of fields) {\n const fieldResult = dlpScanner.scan(fieldValue);\n if (fieldResult.hasMatches) {\n (input as Record<string, unknown>)[fieldKey] = dlpMasker.maskText(\n fieldValue,\n fieldResult.matches,\n );\n }\n }\n await audit.log({\n ...baseRecord,\n event: 'dlp_masked',\n metadata: { ...dlpMeta, strategy: dlpMasker['config'].strategy },\n });\n } else {\n // audit-only\n stats.dlpDetected++;\n await audit.log({\n ...baseRecord,\n event: 'dlp_detected',\n metadata: dlpMeta,\n });\n }\n }\n }\n\n // 7. HITL approval for non-bash tools if required\n if (toolName !== 'bash' && policyEngine.requiresApproval(identity.role, toolName)) {\n if (approvalFlow) {\n stats.approvals++;\n await audit.log({ ...baseRecord, event: 'approval_requested' });\n\n const result = await approvalFlow.requestApproval(\n { toolName, input },\n { userId: identity.userId, role: identity.role, orgUnit: identity.orgUnit },\n );\n\n if (result.approved) {\n await audit.log({ ...baseRecord, event: 'approval_granted', duration: result.duration });\n } else {\n stats.denied++;\n await audit.log({\n ...baseRecord,\n event: 'approval_denied',\n reason: result.reason,\n duration: result.duration,\n });\n return { block: true, reason: result.reason ?? 'Approval denied' };\n }\n }\n }\n\n // 8. Tool allowed\n stats.allowed++;\n await audit.log({ ...baseRecord, event: 'tool_allowed', decision: 'allowed' });\n return undefined;\n });\n\n pi.on('tool_result', async (event, _ctx) => {\n // DLP scan output before audit\n if (dlpScanner && dlpMasker && event.output) {\n const result = dlpScanner.scan(event.output);\n if (result.hasMatches) {\n const action = resolveHighestAction(dlpScanner, result.matches, 'output');\n const patternNames = [...new Set(result.matches.map((m) => m.patternName))];\n const severities = [...new Set(result.matches.map((m) => m.severity))];\n const dlpMeta = {\n patterns: patternNames,\n severities,\n direction: 'output' as const,\n count: result.matches.length,\n };\n\n if (action === 'mask' || action === 'block') {\n // block degrades to mask for outputs (handler returns void)\n stats.dlpMasked++;\n event.output = dlpMasker.maskText(event.output, result.matches);\n await audit.log({\n sessionId,\n event: 'dlp_masked',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: event.toolName,\n metadata: { ...dlpMeta, strategy: dlpMasker['config'].strategy },\n });\n } else {\n stats.dlpDetected++;\n await audit.log({\n sessionId,\n event: 'dlp_detected',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: event.toolName,\n metadata: dlpMeta,\n });\n }\n }\n }\n\n await audit.log({\n sessionId,\n event: 'tool_result',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n tool: event.toolName,\n input: summarizeParams(event.toolName, event.input),\n metadata: { isError: event.isError },\n });\n });\n\n pi.on('session_shutdown', async (_event, _ctx) => {\n configWatcher?.stop();\n await audit.log({\n sessionId,\n event: 'session_end',\n userId: identity.userId,\n role: identity.role,\n orgUnit: identity.orgUnit,\n metadata: {\n stats: { ...stats },\n budget: { used: budgetTracker.used(), remaining: budgetTracker.remaining() },\n summary: Object.fromEntries(audit.getSummary()),\n },\n });\n await audit.flush();\n });\n\n pi.registerCommand('governance', {\n description: 'Governance status and controls',\n handler: async (args, ctx) => {\n const subcommand = args.trim().split(/\\s+/)[0] ?? '';\n\n if (subcommand === 'status') {\n const summary = audit.getSummary();\n const budgetInfo = budgetTracker.isUnlimited()\n ? 'unlimited'\n : `${budgetTracker.used()} / ${budgetTracker.used() + budgetTracker.remaining()} (${budgetTracker.remaining()} remaining)`;\n const lines = [\n `Role: ${identity.role}`,\n `Org Unit: ${identity.orgUnit}`,\n `Mode: ${executionMode}`,\n `Session: ${sessionId}`,\n `Budget: ${budgetInfo}`,\n '',\n 'Session Stats:',\n ` Allowed: ${stats.allowed}`,\n ` Denied: ${stats.denied}`,\n ` Approvals: ${stats.approvals}`,\n ` Dry-run blocks: ${stats.dryRun}`,\n ` Budget exceeded: ${stats.budgetExceeded}`,\n ` DLP blocked: ${stats.dlpBlocked}`,\n ` DLP detected: ${stats.dlpDetected}`,\n ` DLP masked: ${stats.dlpMasked}`,\n '',\n 'Audit Events:',\n ...[...summary.entries()].map(([k, v]) => ` ${k}: ${v}`),\n ];\n ctx.ui.notify(lines.join('\\n'), 'info');\n } else {\n ctx.ui.notify('Usage: /governance status', 'info');\n }\n },\n });\n};\n\nexport default piGovernance;\n\n// Re-export types for consumers\nexport type {\n ExtensionFactory,\n ExtensionAPI,\n ExtensionContext,\n ExtensionUI,\n ToolCallEvent,\n ToolResultEvent,\n};\n","import { existsSync, readFileSync } from 'fs';\nimport { parse as parseYaml } from 'yaml';\nimport { Value } from '@sinclair/typebox/value';\nimport { GovernanceConfigSchema, type GovernanceConfig } from './schema.js';\nimport { DEFAULTS } from './defaults.js';\n\nfunction getConfigPaths(): (string | undefined)[] {\n return [\n process.env['GRWND_GOVERNANCE_CONFIG'],\n '.pi/governance.yaml',\n `${process.env['HOME']}/.pi/agent/governance.yaml`,\n ];\n}\n\nexport function loadConfig(): { config: GovernanceConfig; source: string } {\n for (const path of getConfigPaths()) {\n if (path && existsSync(path)) {\n const raw = readFileSync(path, 'utf-8');\n const parsed = parseYaml(raw);\n\n const resolved = resolveEnvVars(parsed);\n\n const errors = [...Value.Errors(GovernanceConfigSchema, resolved)];\n if (errors.length > 0) {\n throw new ConfigValidationError(\n path,\n errors.map((e) => ({ path: e.path, message: e.message })),\n );\n }\n\n const config = Value.Default(GovernanceConfigSchema, resolved) as GovernanceConfig;\n return { config, source: path };\n }\n }\n\n return { config: DEFAULTS, source: 'built-in' };\n}\n\nfunction resolveEnvVars(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return obj.replace(/\\$\\{(\\w+)\\}/g, (_, name: string) => process.env[name] ?? '');\n }\n if (Array.isArray(obj)) return obj.map(resolveEnvVars);\n if (obj && typeof obj === 'object') {\n return Object.fromEntries(\n Object.entries(obj as Record<string, unknown>).map(([k, v]) => [k, resolveEnvVars(v)]),\n );\n }\n return obj;\n}\n\nexport class ConfigValidationError extends Error {\n constructor(path: string, errors: Array<{ path: string; message: string }>) {\n const details = errors.map((e) => ` ${e.path}: ${e.message}`).join('\\n');\n super(`Invalid governance config at ${path}:\\n${details}`);\n this.name = 'ConfigValidationError';\n }\n}\n","import { Type, type Static } from '@sinclair/typebox';\n\nconst AuthEnvConfig = Type.Object({\n user_var: Type.String({ default: 'GRWND_USER' }),\n role_var: Type.String({ default: 'GRWND_ROLE' }),\n org_unit_var: Type.String({ default: 'GRWND_ORG_UNIT' }),\n});\n\nconst AuthLocalConfig = Type.Object({\n users_file: Type.String({ default: './users.yaml' }),\n});\n\nconst AuthConfig = Type.Object({\n provider: Type.Union([Type.Literal('env'), Type.Literal('local'), Type.Literal('oidc')], {\n default: 'env',\n }),\n env: Type.Optional(AuthEnvConfig),\n local: Type.Optional(AuthLocalConfig),\n});\n\nexport type AuthConfigType = Static<typeof AuthConfig>;\n\nconst YamlPolicyConfig = Type.Object({\n rules_file: Type.String({ default: './governance-rules.yaml' }),\n});\n\nconst OsoPolicyConfig = Type.Object({\n polar_files: Type.Array(Type.String(), {\n default: ['./policies/base.polar', './policies/tools.polar'],\n }),\n});\n\nconst PolicyConfig = Type.Object({\n engine: Type.Union([Type.Literal('yaml'), Type.Literal('oso')], { default: 'yaml' }),\n yaml: Type.Optional(YamlPolicyConfig),\n oso: Type.Optional(OsoPolicyConfig),\n});\n\nconst TemplatesConfig = Type.Object({\n directory: Type.String({ default: './templates/' }),\n default: Type.String({ default: 'project-lead' }),\n});\n\nconst HitlWebhookConfig = Type.Object({\n url: Type.String(),\n});\n\nconst HitlConfig = Type.Object({\n default_mode: Type.Union(\n [Type.Literal('autonomous'), Type.Literal('supervised'), Type.Literal('dry_run')],\n { default: 'supervised' },\n ),\n approval_channel: Type.Union([Type.Literal('cli'), Type.Literal('webhook')], { default: 'cli' }),\n timeout_seconds: Type.Number({ default: 300, minimum: 10, maximum: 3600 }),\n webhook: Type.Optional(HitlWebhookConfig),\n});\n\nconst JsonlSinkConfig = Type.Object({\n type: Type.Literal('jsonl'),\n path: Type.String({ default: '~/.pi/agent/audit.jsonl' }),\n});\n\nconst WebhookSinkConfig = Type.Object({\n type: Type.Literal('webhook'),\n url: Type.String(),\n});\n\nconst PostgresSinkConfig = Type.Object({\n type: Type.Literal('postgres'),\n connection: Type.String(),\n});\n\nconst AuditSinkConfig = Type.Union([JsonlSinkConfig, WebhookSinkConfig, PostgresSinkConfig]);\n\nconst AuditConfig = Type.Object({\n sinks: Type.Array(AuditSinkConfig, {\n default: [{ type: 'jsonl', path: '~/.pi/agent/audit.jsonl' }],\n }),\n});\n\nconst OrgUnitOverride = Type.Object({\n hitl: Type.Optional(Type.Partial(HitlConfig)),\n policy: Type.Optional(\n Type.Object({\n extra_polar: Type.Optional(Type.String()),\n extra_rules: Type.Optional(Type.String()),\n }),\n ),\n});\n\n// --- DLP (Data Loss Prevention) ---\n\nconst DlpMaskingConfig = Type.Object({\n strategy: Type.Union([Type.Literal('partial'), Type.Literal('full'), Type.Literal('hash')], {\n default: 'partial',\n }),\n show_chars: Type.Optional(Type.Number({ default: 4, minimum: 0 })),\n placeholder: Type.Optional(Type.String({ default: '***' })),\n});\n\nconst DlpCustomPatternConfig = Type.Object({\n name: Type.String(),\n pattern: Type.String(),\n severity: Type.Union([\n Type.Literal('low'),\n Type.Literal('medium'),\n Type.Literal('high'),\n Type.Literal('critical'),\n ]),\n action: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n});\n\nconst DlpAllowlistEntryConfig = Type.Object({\n pattern: Type.String(),\n});\n\nconst DlpRoleOverrideConfig = Type.Object({\n enabled: Type.Optional(Type.Boolean()),\n mode: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n on_input: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n on_output: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n});\n\nconst DlpConfig = Type.Object({\n enabled: Type.Boolean({ default: false }),\n mode: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')], {\n default: 'audit',\n }),\n ),\n on_input: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n on_output: Type.Optional(\n Type.Union([Type.Literal('audit'), Type.Literal('mask'), Type.Literal('block')]),\n ),\n masking: Type.Optional(DlpMaskingConfig),\n severity_threshold: Type.Optional(\n Type.Union(\n [Type.Literal('low'), Type.Literal('medium'), Type.Literal('high'), Type.Literal('critical')],\n { default: 'low' },\n ),\n ),\n built_in: Type.Optional(\n Type.Object({\n secrets: Type.Boolean({ default: true }),\n pii: Type.Boolean({ default: true }),\n }),\n ),\n custom_patterns: Type.Optional(Type.Array(DlpCustomPatternConfig)),\n allowlist: Type.Optional(Type.Array(DlpAllowlistEntryConfig)),\n role_overrides: Type.Optional(Type.Record(Type.String(), DlpRoleOverrideConfig)),\n});\n\nexport type DlpConfigType = Static<typeof DlpConfig>;\n\nexport const GovernanceConfigSchema = Type.Object({\n auth: Type.Optional(AuthConfig),\n policy: Type.Optional(PolicyConfig),\n templates: Type.Optional(TemplatesConfig),\n hitl: Type.Optional(HitlConfig),\n audit: Type.Optional(AuditConfig),\n dlp: Type.Optional(DlpConfig),\n org_units: Type.Optional(Type.Record(Type.String(), OrgUnitOverride)),\n});\n\nexport type GovernanceConfig = Static<typeof GovernanceConfigSchema>;\n","import type { GovernanceConfig } from './schema.js';\n\nexport const DEFAULTS: GovernanceConfig = {\n auth: {\n provider: 'env',\n env: {\n user_var: 'GRWND_USER',\n role_var: 'GRWND_ROLE',\n org_unit_var: 'GRWND_ORG_UNIT',\n },\n },\n policy: {\n engine: 'yaml',\n yaml: {\n rules_file: './governance-rules.yaml',\n },\n },\n templates: {\n directory: './templates/',\n default: 'project-lead',\n },\n hitl: {\n default_mode: 'supervised',\n approval_channel: 'cli',\n timeout_seconds: 300,\n },\n audit: {\n sinks: [{ type: 'jsonl', path: '~/.pi/agent/audit.jsonl' }],\n },\n dlp: {\n enabled: false,\n },\n};\n","import type { IdentityProvider, ResolvedIdentity } from './provider.js';\n\nexport class EnvIdentityProvider implements IdentityProvider {\n name = 'env';\n\n constructor(\n private userVar: string = 'GRWND_USER',\n private roleVar: string = 'GRWND_ROLE',\n private orgUnitVar: string = 'GRWND_ORG_UNIT',\n ) {}\n\n async resolve(): Promise<ResolvedIdentity | null> {\n const userId = process.env[this.userVar];\n const role = process.env[this.roleVar];\n const orgUnit = process.env[this.orgUnitVar];\n\n if (!userId || !role) return null;\n\n return {\n userId,\n role,\n orgUnit: orgUnit ?? 'default',\n source: 'env',\n };\n }\n}\n","import { readFileSync } from 'fs';\nimport { parse as parseYaml } from 'yaml';\nimport type { IdentityProvider, ResolvedIdentity } from './provider.js';\n\ninterface UserEntry {\n role: string;\n org_unit?: string;\n}\n\nexport class LocalIdentityProvider implements IdentityProvider {\n name = 'local';\n private users: Record<string, UserEntry>;\n\n constructor(usersFilePath: string) {\n const raw = readFileSync(usersFilePath, 'utf-8');\n this.users = parseYaml(raw) as Record<string, UserEntry>;\n }\n\n async resolve(): Promise<ResolvedIdentity | null> {\n // Try to determine the current system username\n const username = process.env.USER || process.env.USERNAME;\n if (!username) return null;\n\n const entry = this.users[username];\n if (!entry) return null;\n\n return {\n userId: username,\n role: entry.role,\n orgUnit: entry.org_unit ?? 'default',\n source: 'local',\n };\n }\n}\n","import type { IdentityProvider, ResolvedIdentity } from './provider.js';\nimport type { AuthConfigType } from '../config/schema.js';\nimport { EnvIdentityProvider } from './env-provider.js';\nimport { LocalIdentityProvider } from './local-provider.js';\n\nexport class IdentityChain {\n private providers: IdentityProvider[];\n\n constructor(providers: IdentityProvider[]) {\n this.providers = providers;\n }\n\n async resolve(): Promise<ResolvedIdentity> {\n for (const provider of this.providers) {\n const identity = await provider.resolve();\n if (identity) return identity;\n }\n\n // Fallback: default restricted identity\n return {\n userId: 'unknown',\n role: 'analyst', // most restrictive role by default\n orgUnit: 'default',\n source: 'fallback',\n };\n }\n}\n\nexport function createIdentityChain(config?: AuthConfigType): IdentityChain {\n const providers: IdentityProvider[] = [];\n\n // Always try env first (fastest, works in CI)\n providers.push(\n new EnvIdentityProvider(\n config?.env?.user_var,\n config?.env?.role_var,\n config?.env?.org_unit_var,\n ),\n );\n\n // Then try local file if configured\n if (config?.provider === 'local' && config.local?.users_file) {\n try {\n providers.push(new LocalIdentityProvider(config.local.users_file));\n } catch {\n // users file not found — skip this provider\n }\n }\n\n return new IdentityChain(providers);\n}\n","import { readFileSync } from 'fs';\nimport { parse as parseYaml } from 'yaml';\nimport { minimatch } from 'minimatch';\nimport type {\n PolicyEngine,\n PolicyDecision,\n PathOperation,\n ExecutionMode,\n BashOverrides,\n} from './engine.js';\n\nexport interface YamlRole {\n allowed_tools: string[];\n blocked_tools: string[];\n prompt_template: string;\n execution_mode: ExecutionMode;\n human_approval: {\n required_for: string[];\n auto_approve?: string[];\n };\n token_budget_daily: number;\n allowed_paths: string[];\n blocked_paths: string[];\n bash_overrides?: {\n additional_blocked?: string[];\n additional_allowed?: string[];\n };\n}\n\nexport interface YamlRules {\n roles: Record<string, YamlRole>;\n}\n\nexport class YamlPolicyEngine implements PolicyEngine {\n private rules: YamlRules;\n\n constructor(rulesFilePathOrRules: string | YamlRules) {\n if (typeof rulesFilePathOrRules === 'string') {\n const raw = readFileSync(rulesFilePathOrRules, 'utf-8');\n this.rules = parseYaml(raw) as YamlRules;\n } else {\n this.rules = rulesFilePathOrRules;\n }\n }\n\n private getRole(role: string): YamlRole {\n const r = this.rules.roles[role];\n if (!r) {\n throw new Error(\n `Unknown role: ${role}. Available roles: ${Object.keys(this.rules.roles).join(', ')}`,\n );\n }\n return r;\n }\n\n evaluateTool(role: string, tool: string): PolicyDecision {\n const r = this.getRole(role);\n\n // Check blocked list first\n if (r.blocked_tools.includes(tool)) return 'deny';\n\n // Check allowed list\n if (r.allowed_tools.includes('all') || r.allowed_tools.includes(tool)) {\n return 'allow';\n }\n\n // Not in either list — deny by default\n return 'deny';\n }\n\n evaluatePath(\n role: string,\n _orgUnit: string,\n _operation: PathOperation,\n path: string,\n ): PolicyDecision {\n const r = this.getRole(role);\n\n // Check blocked paths first (takes precedence)\n for (const pattern of r.blocked_paths) {\n if (minimatch(path, pattern, { dot: true })) {\n return 'deny';\n }\n }\n\n // Check allowed paths\n for (const pattern of r.allowed_paths) {\n const resolved = pattern.replace('{{project_path}}', process.cwd());\n if (minimatch(path, resolved, { dot: true })) {\n return 'allow';\n }\n }\n\n // Not in allowed paths — deny\n return 'deny';\n }\n\n requiresApproval(role: string, tool: string): boolean {\n const r = this.getRole(role);\n\n // Auto-approve takes precedence\n if (r.human_approval.auto_approve?.includes(tool)) return false;\n\n // Check required list\n if (r.human_approval.required_for.includes('all')) return true;\n return r.human_approval.required_for.includes(tool);\n }\n\n getExecutionMode(role: string): ExecutionMode {\n return this.getRole(role).execution_mode;\n }\n\n getTemplateName(role: string): string {\n return this.getRole(role).prompt_template;\n }\n\n getBashOverrides(role: string): BashOverrides {\n const r = this.getRole(role);\n const overrides = r.bash_overrides;\n if (!overrides) return {};\n\n return {\n additionalBlocked: overrides.additional_blocked?.map((p) => new RegExp(p)),\n additionalAllowed: overrides.additional_allowed?.map((p) => new RegExp(p)),\n };\n }\n\n getTokenBudget(role: string): number {\n return this.getRole(role).token_budget_daily;\n }\n}\n","export const SAFE_PATTERNS: RegExp[] = [\n // File viewing\n /^(cat|head|tail|less|more)\\s/,\n /^(file|stat|wc|md5sum|sha256sum)\\s/,\n\n // Directory listing\n /^(ls|ll|la|tree|du|df)\\b/,\n /^(pwd|cd)\\b/,\n\n // Searching\n /^(grep|rg|ag|ack|find|fd|locate)\\s/,\n /^(which|whereis|type|command)\\s/,\n\n // Text processing (read-only)\n /^(sort|uniq|cut|awk|sed)\\s.*(?!-i)/, // sed without -i (in-place)\n /^(tr|diff|comm|join|paste)\\s/,\n /^(jq|yq|xmlstarlet)\\s/,\n\n // Git (read-only operations)\n /^git\\s+(log|status|diff|show|blame|branch|tag|remote|stash list)\\b/,\n /^git\\s+(ls-files|ls-tree|rev-parse|describe)\\b/,\n\n // System info\n /^(whoami|id|groups|uname|hostname|date|uptime|env|printenv)\\b/,\n /^(echo|printf)\\s/,\n\n // Package info (not install)\n /^(npm|yarn|pnpm)\\s+(list|ls|info|show|view|outdated|audit)\\b/,\n /^pip\\s+(list|show|freeze)\\b/,\n /^(node|python|ruby|go)\\s+--version\\b/,\n /^(node|python|ruby)\\s+-e\\s/,\n\n // Networking (read-only)\n /^(ping|dig|nslookup|host|traceroute|tracepath)\\s/,\n /^curl\\s.*--head\\b/,\n /^curl\\s.*-I\\b/,\n\n // Additional file viewing / inspection\n /^(basename|dirname|realpath|readlink)\\s/,\n /^(xxd|od|hexdump)\\s/,\n /^(strings|nm|objdump)\\s/,\n\n // Additional search / navigation\n /^(xargs)\\s/,\n /^(tee)\\s/,\n\n // Additional text processing (read-only)\n /^(fmt|fold|column|expand|unexpand)\\s/,\n /^(tac|rev|nl)\\s/,\n /^(yes|seq|shuf)\\s/,\n\n // Additional system info\n /^(lsof|ps|top|htop|vmstat|iostat|free|df)\\b/,\n /^(lscpu|lsblk|lsusb|lspci)\\b/,\n /^(nproc|getconf)\\b/,\n\n // Additional git read-only\n /^git\\s+(config\\s+--get|config\\s+-l|shortlog|reflog|cherry)\\b/,\n /^git\\s+(cat-file|count-objects|fsck|verify-pack)\\b/,\n];\n\nexport const DANGEROUS_PATTERNS: RegExp[] = [\n // Destructive file operations\n /\\brm\\s+(-[a-zA-Z]*r|-[a-zA-Z]*f|--recursive|--force)\\b/,\n /\\brm\\s+-[a-zA-Z]*rf\\b/,\n /\\bshred\\b/,\n\n // Privilege escalation\n /\\bsudo\\b/,\n /\\bsu\\s+-?\\s*\\w/,\n /\\bdoas\\b/,\n\n // Permission/ownership changes\n /\\bchmod\\b/,\n /\\bchown\\b/,\n /\\bchgrp\\b/,\n\n // Disk/partition operations\n /\\bdd\\b.*\\bof=/,\n /\\bmkfs\\b/,\n /\\bfdisk\\b/,\n /\\bparted\\b/,\n /\\bmount\\b/,\n /\\bumount\\b/,\n\n // Remote code execution\n /\\bcurl\\b.*\\|\\s*(bash|sh|zsh|python|perl|ruby)\\b/,\n /\\bwget\\b.*\\|\\s*(bash|sh|zsh|python|perl|ruby)\\b/,\n /\\bcurl\\b.*>\\s*.*\\.sh\\s*&&/,\n\n // Remote access\n /\\bssh\\b/,\n /\\bscp\\b/,\n /\\brsync\\b.*:\\//,\n /\\bnc\\s+(-[a-zA-Z]*l|-[a-zA-Z]*p|--listen)\\b/,\n /\\bncat\\b/,\n /\\bsocat\\b/,\n /\\btelnet\\b/,\n\n // System modification\n /\\bsystemctl\\s+(start|stop|restart|enable|disable)\\b/,\n /\\bservice\\s+\\w+\\s+(start|stop|restart)\\b/,\n /\\biptables\\b/,\n /\\bufw\\b/,\n /\\bfirewall-cmd\\b/,\n\n // Package installation (can run arbitrary post-install scripts)\n /\\bnpm\\s+(install|i|add|ci)\\b/,\n /\\byarn\\s+(add|install)\\b/,\n /\\bpnpm\\s+(add|install|i)\\b/,\n /\\bpip\\s+install\\b/,\n /\\bapt(-get)?\\s+install\\b/,\n /\\bbrew\\s+install\\b/,\n /\\bcargo\\s+install\\b/,\n\n // Environment variable manipulation (can leak secrets)\n /\\bexport\\b.*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,\n\n // Cron / scheduled tasks\n /\\bcrontab\\b/,\n /\\bat\\s+/,\n\n // Container escape vectors\n /\\bdocker\\s+(run|exec|build|push|pull)\\b/,\n /\\bkubectl\\s+(exec|run|apply|delete)\\b/,\n\n // Process manipulation\n /\\bkill\\b/,\n /\\bkillall\\b/,\n /\\bpkill\\b/,\n\n // History manipulation\n /\\bhistory\\s+-c\\b/,\n /\\bunset\\s+HISTFILE\\b/,\n\n // Compiler/build (can execute arbitrary code)\n /\\bmake\\s/,\n /\\bgcc\\b/,\n /\\bg\\+\\+/,\n];\n","import { SAFE_PATTERNS, DANGEROUS_PATTERNS } from './patterns.js';\nimport type { BashOverrides } from '../policy/engine.js';\n\nexport type BashClassification = 'safe' | 'dangerous' | 'needs_review';\n\nexport class BashClassifier {\n private safePatterns: RegExp[];\n private dangerousPatterns: RegExp[];\n\n constructor(overrides?: BashOverrides) {\n this.safePatterns = [...SAFE_PATTERNS, ...(overrides?.additionalAllowed ?? [])];\n this.dangerousPatterns = [...DANGEROUS_PATTERNS, ...(overrides?.additionalBlocked ?? [])];\n }\n\n classify(command: string): BashClassification {\n const trimmed = command.trim();\n\n // Check dangerous patterns against the full unsplit command first.\n // This catches patterns like \"curl ... | bash\" that span pipe boundaries.\n for (const pattern of this.dangerousPatterns) {\n if (pattern.test(trimmed)) return 'dangerous';\n }\n\n // Multi-command detection: if the command contains pipes, semicolons,\n // or && / ||, classify each segment independently and return the\n // most restrictive classification\n const segments = this.splitCommand(trimmed);\n\n if (segments.length > 1) {\n const classifications = segments.map((s) => this.classifySingle(s));\n if (classifications.includes('dangerous')) return 'dangerous';\n if (classifications.includes('needs_review')) return 'needs_review';\n return 'safe';\n }\n\n return this.classifySingle(trimmed);\n }\n\n private classifySingle(command: string): BashClassification {\n const trimmed = command.trim();\n\n // Check dangerous first (takes precedence)\n for (const pattern of this.dangerousPatterns) {\n if (pattern.test(trimmed)) return 'dangerous';\n }\n\n // Check safe\n for (const pattern of this.safePatterns) {\n if (pattern.test(trimmed)) return 'safe';\n }\n\n // Default: needs review\n return 'needs_review';\n }\n\n private splitCommand(command: string): string[] {\n // Split on pipes, semicolons, && and || while respecting quotes\n // This is a simplified parser — not a full shell parser\n const segments: string[] = [];\n let current = '';\n let inSingleQuote = false;\n let inDoubleQuote = false;\n let escaped = false;\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i]!;\n\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n\n if (char === '\\\\') {\n escaped = true;\n current += char;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n current += char;\n continue;\n }\n\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n current += char;\n continue;\n }\n\n if (!inSingleQuote && !inDoubleQuote) {\n if (char === '|' && command[i + 1] !== '|') {\n segments.push(current.trim());\n current = '';\n continue;\n }\n if (char === ';') {\n segments.push(current.trim());\n current = '';\n continue;\n }\n if (char === '&' && command[i + 1] === '&') {\n segments.push(current.trim());\n current = '';\n i++; // skip second &\n continue;\n }\n if (char === '|' && command[i + 1] === '|') {\n segments.push(current.trim());\n current = '';\n i++; // skip second |\n continue;\n }\n }\n\n current += char;\n }\n\n if (current.trim()) segments.push(current.trim());\n return segments.filter((s) => s.length > 0);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { AuditRecord, AuditEventType } from './schema.js';\nimport type { AuditSink } from './sinks/sink.js';\nimport { JsonlAuditSink } from './sinks/jsonl.js';\nimport { WebhookAuditSink } from './sinks/webhook.js';\n\ninterface AuditSinkConfig {\n type: 'jsonl' | 'webhook' | 'postgres';\n path?: string;\n url?: string;\n connection?: string;\n}\n\ninterface AuditConfig {\n sinks: AuditSinkConfig[];\n}\n\nexport class AuditLogger {\n private sinks: AuditSink[];\n private counts: Map<AuditEventType, number> = new Map();\n\n constructor(config?: AuditConfig) {\n const sinkConfigs = config?.sinks ?? [\n { type: 'jsonl' as const, path: '~/.pi/agent/audit.jsonl' },\n ];\n this.sinks = [];\n\n for (const sc of sinkConfigs) {\n if (sc.type === 'jsonl') {\n this.sinks.push(new JsonlAuditSink(sc.path ?? '~/.pi/agent/audit.jsonl'));\n } else if (sc.type === 'webhook' && sc.url) {\n this.sinks.push(new WebhookAuditSink(sc.url));\n }\n // postgres: skip for now\n }\n\n // Ensure at least one sink\n if (this.sinks.length === 0) {\n this.sinks.push(new JsonlAuditSink('~/.pi/agent/audit.jsonl'));\n }\n }\n\n async log(record: Omit<AuditRecord, 'id' | 'timestamp'>): Promise<void> {\n const full: AuditRecord = {\n ...record,\n id: randomUUID(),\n timestamp: new Date().toISOString(),\n };\n\n this.counts.set(full.event, (this.counts.get(full.event) ?? 0) + 1);\n\n await Promise.all(this.sinks.map((s) => s.write(full as unknown as Record<string, unknown>)));\n }\n\n async flush(): Promise<void> {\n await Promise.all(this.sinks.map((s) => s.flush()));\n }\n\n getSummary(): Map<AuditEventType, number> {\n return new Map(this.counts);\n }\n}\n","import { appendFile, mkdir } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { AuditSink } from './sink.js';\n\nexport class JsonlAuditSink implements AuditSink {\n private path: string;\n private buffer: Record<string, unknown>[] = [];\n private readonly flushThreshold = 10;\n\n constructor(path: string) {\n this.path = path.replace(/^~/, homedir());\n }\n\n async write(record: Record<string, unknown>): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const lines = this.buffer.map((r) => JSON.stringify(r)).join('\\n') + '\\n';\n this.buffer = [];\n await mkdir(dirname(this.path), { recursive: true });\n await appendFile(this.path, lines, 'utf-8');\n }\n}\n","import type { AuditSink } from './sink.js';\n\nexport class WebhookAuditSink implements AuditSink {\n private url: string;\n private buffer: Record<string, unknown>[] = [];\n private readonly flushThreshold = 10;\n\n constructor(url: string) {\n this.url = url;\n }\n\n async write(record: Record<string, unknown>): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const records = [...this.buffer];\n this.buffer = [];\n\n try {\n await this.send(records);\n } catch {\n // Retry once\n try {\n await this.send(records);\n } catch {\n // Drop records after second failure\n }\n }\n }\n\n private async send(records: Record<string, unknown>[]): Promise<void> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(records),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Webhook returned ${response.status}`);\n }\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n","import type { ApprovalFlow, ApprovalResult, GovernanceToolCall, ConfirmUI } from './approval.js';\n\nexport class CliApprover implements ApprovalFlow {\n private ui: ConfirmUI;\n private timeoutSeconds: number;\n\n constructor(ui: ConfirmUI, timeoutSeconds: number = 300) {\n this.ui = ui;\n this.timeoutSeconds = timeoutSeconds;\n }\n\n async requestApproval(\n toolCall: GovernanceToolCall,\n context: { userId: string; role: string; orgUnit: string },\n ): Promise<ApprovalResult> {\n const title = `Approval Required: ${toolCall.toolName}`;\n const inputSummary = Object.entries(toolCall.input)\n .map(\n ([k, v]) =>\n ` ${k}: ${typeof v === 'string' ? v.slice(0, 200) : JSON.stringify(v).slice(0, 200)}`,\n )\n .join('\\n');\n const message = `User: ${context.userId} (${context.role})\\nOrg: ${context.orgUnit}\\n\\nTool: ${toolCall.toolName}\\nInput:\\n${inputSummary}`;\n\n const start = Date.now();\n\n try {\n const approved = await this.ui.confirm(title, message, {\n timeout: this.timeoutSeconds * 1000,\n });\n\n return {\n approved,\n approver: 'cli',\n duration: Date.now() - start,\n reason: approved ? undefined : 'Denied by user',\n };\n } catch {\n // Timeout or error — deny\n return {\n approved: false,\n approver: 'cli',\n duration: Date.now() - start,\n reason: 'Approval timed out',\n };\n }\n }\n}\n","import type { ApprovalFlow, ApprovalResult, GovernanceToolCall } from './approval.js';\n\nexport class WebhookApprover implements ApprovalFlow {\n private url: string;\n private timeoutMs: number;\n\n constructor(url: string, timeoutSeconds: number = 300) {\n this.url = url;\n this.timeoutMs = timeoutSeconds * 1000;\n }\n\n async requestApproval(\n toolCall: GovernanceToolCall,\n context: { userId: string; role: string; orgUnit: string },\n ): Promise<ApprovalResult> {\n const start = Date.now();\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n toolCall: { toolName: toolCall.toolName, input: toolCall.input },\n context,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n return {\n approved: false,\n approver: 'webhook',\n duration: Date.now() - start,\n reason: `Webhook returned ${response.status}`,\n };\n }\n\n const body = (await response.json()) as { approved: boolean; reason?: string };\n\n return {\n approved: body.approved,\n approver: 'webhook',\n duration: Date.now() - start,\n reason: body.reason,\n };\n } catch (err) {\n return {\n approved: false,\n approver: 'webhook',\n duration: Date.now() - start,\n reason:\n err instanceof Error && err.name === 'AbortError'\n ? 'Webhook timed out'\n : 'Webhook request failed',\n };\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n","import { CliApprover } from './cli-approver.js';\nimport { WebhookApprover } from './webhook-approver.js';\n\nexport interface GovernanceToolCall {\n toolName: string;\n input: Record<string, unknown>;\n}\n\nexport interface ApprovalResult {\n approved: boolean;\n reason?: string;\n approver: string;\n duration: number;\n}\n\nexport interface ApprovalFlow {\n requestApproval(\n toolCall: GovernanceToolCall,\n context: { userId: string; role: string; orgUnit: string },\n ): Promise<ApprovalResult>;\n}\n\nexport interface ConfirmUI {\n confirm(title: string, message: string, opts?: { timeout?: number }): Promise<boolean>;\n}\n\nexport interface HitlConfig {\n default_mode: 'autonomous' | 'supervised' | 'dry_run';\n approval_channel: 'cli' | 'webhook';\n timeout_seconds: number;\n webhook?: { url: string };\n}\n\nexport function createApprovalFlow(config: HitlConfig, ui?: ConfirmUI): ApprovalFlow {\n if (config.approval_channel === 'webhook' && config.webhook?.url) {\n return new WebhookApprover(config.webhook.url, config.timeout_seconds);\n }\n\n // Fall back to CLI (also handles webhook without URL)\n if (!ui) {\n throw new Error('CLI approval channel requires a ConfirmUI (ExtensionContext.ui)');\n }\n\n return new CliApprover(ui, config.timeout_seconds);\n}\n","/**\n * Tracks tool invocation count as a proxy for token budget.\n * The budget value represents max invocations per session; -1 means unlimited.\n */\nexport class BudgetTracker {\n private _used = 0;\n private readonly _budget: number;\n\n constructor(budget: number) {\n this._budget = budget;\n }\n\n /** Returns false if consuming would exceed the budget. On success, increments the counter. */\n consume(amount = 1): boolean {\n if (this._budget === -1) {\n this._used += amount;\n return true;\n }\n if (this._used + amount > this._budget) return false;\n this._used += amount;\n return true;\n }\n\n remaining(): number {\n if (this._budget === -1) return Infinity;\n return Math.max(0, this._budget - this._used);\n }\n\n used(): number {\n return this._used;\n }\n\n isUnlimited(): boolean {\n return this._budget === -1;\n }\n}\n","import { watch, readFileSync, type FSWatcher } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { Value } from '@sinclair/typebox/value';\nimport { GovernanceConfigSchema, type GovernanceConfig } from './schema.js';\n\n/**\n * Watches a governance config file for changes and triggers a validated reload.\n * Uses fs.watch() with a 500ms debounce to avoid rapid reloads.\n */\nexport class ConfigWatcher {\n private watcher: FSWatcher | undefined;\n private debounceTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly configPath: string;\n private readonly onChange: (config: GovernanceConfig) => void;\n private readonly onError?: (error: Error) => void;\n\n constructor(\n configPath: string,\n onChange: (config: GovernanceConfig) => void,\n onError?: (error: Error) => void,\n ) {\n this.configPath = configPath;\n this.onChange = onChange;\n this.onError = onError;\n }\n\n start(): void {\n if (this.watcher) return;\n this.watcher = watch(this.configPath, () => this.handleChange());\n }\n\n stop(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = undefined;\n }\n if (this.watcher) {\n this.watcher.close();\n this.watcher = undefined;\n }\n }\n\n private handleChange(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => this.reload(), 500);\n }\n\n private reload(): void {\n try {\n const raw = readFileSync(this.configPath, 'utf-8');\n const parsed = parseYaml(raw);\n const errors = [...Value.Errors(GovernanceConfigSchema, parsed)];\n if (errors.length > 0) {\n const msg = errors.map((e) => `${e.path}: ${e.message}`).join('; ');\n this.onError?.(new Error(`Config validation failed: ${msg}`));\n return;\n }\n const config = Value.Default(GovernanceConfigSchema, parsed) as GovernanceConfig;\n this.onChange(config);\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }\n}\n","export type DlpSeverity = 'low' | 'medium' | 'high' | 'critical';\nexport type DlpCategory = 'secret' | 'pii' | 'custom';\n\nexport interface DlpPatternDef {\n name: string;\n pattern: RegExp;\n severity: DlpSeverity;\n category: DlpCategory;\n}\n\nexport const SECRET_PATTERNS: DlpPatternDef[] = [\n // AWS\n {\n name: 'aws_access_key',\n pattern: /\\b(AKIA[0-9A-Z]{16})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n {\n name: 'aws_secret_key',\n pattern: /\\b([A-Za-z0-9/+=]{40})(?=\\s|$|\"|')/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // GitHub\n {\n name: 'github_pat',\n pattern: /\\b(ghp_[A-Za-z0-9]{36,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n {\n name: 'github_oauth',\n pattern: /\\b(gho_[A-Za-z0-9]{36,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n {\n name: 'github_app_token',\n pattern: /\\b(ghu_[A-Za-z0-9]{36,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Anthropic\n {\n name: 'anthropic_api_key',\n pattern: /\\b(sk-ant-api03-[A-Za-z0-9_-]{90,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // OpenAI\n {\n name: 'openai_api_key',\n pattern: /\\b(sk-[A-Za-z0-9]{20,}T3BlbkFJ[A-Za-z0-9]{20,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // JWT\n {\n name: 'jwt_token',\n pattern: /\\b(eyJ[A-Za-z0-9_-]{10,}\\.eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Private key headers\n {\n name: 'private_key',\n pattern: /-----BEGIN\\s+(RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // Database connection strings\n {\n name: 'database_url',\n pattern: /\\b((?:postgres|mysql|mongodb|redis):\\/\\/[^\\s'\"]{10,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Slack\n {\n name: 'slack_token',\n pattern: /\\b(xox[bpras]-[A-Za-z0-9-]{10,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Stripe\n {\n name: 'stripe_key',\n pattern: /\\b([rs]k_(?:live|test)_[A-Za-z0-9]{20,})\\b/g,\n severity: 'critical',\n category: 'secret',\n },\n\n // npm\n {\n name: 'npm_token',\n pattern: /\\b(npm_[A-Za-z0-9]{36,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // SendGrid\n {\n name: 'sendgrid_key',\n pattern: /\\b(SG\\.[A-Za-z0-9_-]{22,}\\.[A-Za-z0-9_-]{22,})\\b/g,\n severity: 'high',\n category: 'secret',\n },\n\n // Generic API key patterns (env-var style assignments)\n {\n name: 'generic_api_key',\n pattern:\n /\\b(?:API_KEY|API_SECRET|ACCESS_TOKEN|AUTH_TOKEN|SECRET_KEY)\\s*[=:]\\s*['\"]?([A-Za-z0-9_-]{16,})['\"]?/gi,\n severity: 'medium',\n category: 'secret',\n },\n\n // High-entropy string near keyword context\n {\n name: 'generic_secret_assignment',\n pattern: /\\b(?:password|passwd|secret|token|credential)\\s*[=:]\\s*['\"]([^'\"]{8,})['\"]?/gi,\n severity: 'medium',\n category: 'secret',\n },\n];\n\nexport const PII_PATTERNS: DlpPatternDef[] = [\n // SSN (US)\n {\n name: 'ssn',\n pattern: /\\b(\\d{3}-\\d{2}-\\d{4})\\b/g,\n severity: 'critical',\n category: 'pii',\n },\n\n // Credit card numbers\n {\n name: 'credit_card',\n pattern:\n /\\b(4\\d{3}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}|5[1-5]\\d{2}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}|3[47]\\d{2}[\\s-]?\\d{6}[\\s-]?\\d{5}|6(?:011|5\\d{2})[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4})\\b/g,\n severity: 'critical',\n category: 'pii',\n },\n\n // Email address\n {\n name: 'email',\n pattern: /\\b([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})\\b/g,\n severity: 'low',\n category: 'pii',\n },\n\n // US phone number\n {\n name: 'phone_us',\n pattern: /\\b(\\+?1?[-.\\s]?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4})\\b/g,\n severity: 'medium',\n category: 'pii',\n },\n\n // IPv4 address\n {\n name: 'ipv4',\n pattern:\n /\\b((?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?))\\b/g,\n severity: 'low',\n category: 'pii',\n },\n];\n","import { SECRET_PATTERNS, PII_PATTERNS } from './patterns.js';\nimport type { DlpPatternDef, DlpSeverity, DlpCategory } from './patterns.js';\n\nexport type DlpAction = 'audit' | 'mask' | 'block';\n\nexport interface DlpMatch {\n patternName: string;\n category: DlpCategory;\n severity: DlpSeverity;\n start: number;\n end: number;\n matched: string;\n}\n\nexport interface DlpScanResult {\n hasMatches: boolean;\n matches: DlpMatch[];\n}\n\nexport interface DlpCustomPattern {\n name: string;\n pattern: string;\n severity: DlpSeverity;\n action?: DlpAction;\n}\n\nexport interface DlpAllowlistEntry {\n pattern: string;\n}\n\nexport interface DlpScannerConfig {\n enabled: boolean;\n mode: DlpAction;\n on_input?: DlpAction;\n on_output?: DlpAction;\n severity_threshold: DlpSeverity;\n built_in: { secrets: boolean; pii: boolean };\n custom_patterns: DlpCustomPattern[];\n allowlist: DlpAllowlistEntry[];\n pattern_overrides: Map<string, DlpAction>;\n}\n\nconst SEVERITY_ORDER: Record<DlpSeverity, number> = {\n low: 0,\n medium: 1,\n high: 2,\n critical: 3,\n};\n\ninterface CompiledPattern {\n def: DlpPatternDef;\n action?: DlpAction;\n}\n\nexport class DlpScanner {\n private patterns: CompiledPattern[];\n private allowlistRegexps: RegExp[];\n private severityThreshold: number;\n private config: DlpScannerConfig;\n\n constructor(config: DlpScannerConfig) {\n this.config = config;\n this.severityThreshold = SEVERITY_ORDER[config.severity_threshold];\n this.patterns = [];\n this.allowlistRegexps = [];\n\n // Compile built-in patterns\n if (config.built_in.secrets) {\n for (const def of SECRET_PATTERNS) {\n this.patterns.push({ def });\n }\n }\n if (config.built_in.pii) {\n for (const def of PII_PATTERNS) {\n this.patterns.push({ def });\n }\n }\n\n // Compile custom patterns\n for (const cp of config.custom_patterns) {\n const def: DlpPatternDef = {\n name: cp.name,\n pattern: new RegExp(cp.pattern, 'g'),\n severity: cp.severity,\n category: 'custom',\n };\n this.patterns.push({ def, action: cp.action });\n }\n\n // Compile pattern overrides from config\n for (const compiled of this.patterns) {\n const override = config.pattern_overrides.get(compiled.def.name);\n if (override) {\n compiled.action = override;\n }\n }\n\n // Compile allowlist\n for (const entry of config.allowlist) {\n this.allowlistRegexps.push(new RegExp(entry.pattern));\n }\n }\n\n scan(text: string): DlpScanResult {\n if (!this.config.enabled || text.length === 0) {\n return { hasMatches: false, matches: [] };\n }\n\n const matches: DlpMatch[] = [];\n\n for (const compiled of this.patterns) {\n // Skip patterns below severity threshold\n if (SEVERITY_ORDER[compiled.def.severity] < this.severityThreshold) {\n continue;\n }\n\n // Reset the regex (global flag means lastIndex needs reset)\n const regex = new RegExp(compiled.def.pattern.source, compiled.def.pattern.flags);\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n // Use the first capturing group if present, otherwise the full match\n const matched = match[1] ?? match[0];\n const start = match[1] ? match.index + match[0].indexOf(match[1]) : match.index;\n const end = start + matched.length;\n\n // Check allowlist\n if (this.isAllowlisted(matched)) {\n continue;\n }\n\n matches.push({\n patternName: compiled.def.name,\n category: compiled.def.category,\n severity: compiled.def.severity,\n start,\n end,\n matched,\n });\n }\n }\n\n return { hasMatches: matches.length > 0, matches };\n }\n\n getAction(direction: 'input' | 'output'): DlpAction {\n if (direction === 'input' && this.config.on_input) {\n return this.config.on_input;\n }\n if (direction === 'output' && this.config.on_output) {\n return this.config.on_output;\n }\n return this.config.mode;\n }\n\n getPatternAction(match: DlpMatch, direction: 'input' | 'output'): DlpAction {\n // Check per-pattern override first\n const compiled = this.patterns.find((p) => p.def.name === match.patternName);\n if (compiled?.action) {\n return compiled.action;\n }\n\n // Fall back to directional override or global mode\n return this.getAction(direction);\n }\n\n private isAllowlisted(value: string): boolean {\n for (const re of this.allowlistRegexps) {\n if (re.test(value)) return true;\n }\n return false;\n }\n}\n\nexport function compareSeverity(a: DlpSeverity, b: DlpSeverity): number {\n return SEVERITY_ORDER[a] - SEVERITY_ORDER[b];\n}\n","import { createHash } from 'node:crypto';\nimport type { DlpMatch } from './scanner.js';\n\nexport interface MaskingConfig {\n strategy: 'partial' | 'full' | 'hash';\n show_chars: number;\n placeholder: string;\n}\n\nconst DEFAULT_CONFIG: MaskingConfig = {\n strategy: 'partial',\n show_chars: 4,\n placeholder: '***',\n};\n\nexport class DlpMasker {\n private config: MaskingConfig;\n\n constructor(config?: Partial<MaskingConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n maskValue(value: string): string {\n switch (this.config.strategy) {\n case 'full':\n return this.config.placeholder;\n case 'hash': {\n const hash = createHash('sha256').update(value).digest('hex').slice(0, 8);\n return `[REDACTED:${hash}]`;\n }\n case 'partial':\n default: {\n if (value.length <= this.config.show_chars) {\n return this.config.placeholder;\n }\n return this.config.placeholder + value.slice(-this.config.show_chars);\n }\n }\n }\n\n maskText(text: string, matches: DlpMatch[]): string {\n if (matches.length === 0) return text;\n\n // Sort by position descending to avoid index shifting\n const sorted = [...matches].sort((a, b) => b.start - a.start);\n\n let result = text;\n for (const match of sorted) {\n const masked = this.maskValue(match.matched);\n result = result.slice(0, match.start) + masked + result.slice(match.end);\n }\n return result;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsDA,IAAAA,kBAA2B;;;ACtD3B,gBAAyC;AACzC,kBAAmC;AACnC,mBAAsB;;;ACFtB,qBAAkC;AAElC,IAAM,gBAAgB,oBAAK,OAAO;AAAA,EAChC,UAAU,oBAAK,OAAO,EAAE,SAAS,aAAa,CAAC;AAAA,EAC/C,UAAU,oBAAK,OAAO,EAAE,SAAS,aAAa,CAAC;AAAA,EAC/C,cAAc,oBAAK,OAAO,EAAE,SAAS,iBAAiB,CAAC;AACzD,CAAC;AAED,IAAM,kBAAkB,oBAAK,OAAO;AAAA,EAClC,YAAY,oBAAK,OAAO,EAAE,SAAS,eAAe,CAAC;AACrD,CAAC;AAED,IAAM,aAAa,oBAAK,OAAO;AAAA,EAC7B,UAAU,oBAAK,MAAM,CAAC,oBAAK,QAAQ,KAAK,GAAG,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,CAAC,GAAG;AAAA,IACvF,SAAS;AAAA,EACX,CAAC;AAAA,EACD,KAAK,oBAAK,SAAS,aAAa;AAAA,EAChC,OAAO,oBAAK,SAAS,eAAe;AACtC,CAAC;AAID,IAAM,mBAAmB,oBAAK,OAAO;AAAA,EACnC,YAAY,oBAAK,OAAO,EAAE,SAAS,0BAA0B,CAAC;AAChE,CAAC;AAED,IAAM,kBAAkB,oBAAK,OAAO;AAAA,EAClC,aAAa,oBAAK,MAAM,oBAAK,OAAO,GAAG;AAAA,IACrC,SAAS,CAAC,yBAAyB,wBAAwB;AAAA,EAC7D,CAAC;AACH,CAAC;AAED,IAAM,eAAe,oBAAK,OAAO;AAAA,EAC/B,QAAQ,oBAAK,MAAM,CAAC,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,KAAK,CAAC,GAAG,EAAE,SAAS,OAAO,CAAC;AAAA,EACnF,MAAM,oBAAK,SAAS,gBAAgB;AAAA,EACpC,KAAK,oBAAK,SAAS,eAAe;AACpC,CAAC;AAED,IAAM,kBAAkB,oBAAK,OAAO;AAAA,EAClC,WAAW,oBAAK,OAAO,EAAE,SAAS,eAAe,CAAC;AAAA,EAClD,SAAS,oBAAK,OAAO,EAAE,SAAS,eAAe,CAAC;AAClD,CAAC;AAED,IAAM,oBAAoB,oBAAK,OAAO;AAAA,EACpC,KAAK,oBAAK,OAAO;AACnB,CAAC;AAED,IAAM,aAAa,oBAAK,OAAO;AAAA,EAC7B,cAAc,oBAAK;AAAA,IACjB,CAAC,oBAAK,QAAQ,YAAY,GAAG,oBAAK,QAAQ,YAAY,GAAG,oBAAK,QAAQ,SAAS,CAAC;AAAA,IAChF,EAAE,SAAS,aAAa;AAAA,EAC1B;AAAA,EACA,kBAAkB,oBAAK,MAAM,CAAC,oBAAK,QAAQ,KAAK,GAAG,oBAAK,QAAQ,SAAS,CAAC,GAAG,EAAE,SAAS,MAAM,CAAC;AAAA,EAC/F,iBAAiB,oBAAK,OAAO,EAAE,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,CAAC;AAAA,EACzE,SAAS,oBAAK,SAAS,iBAAiB;AAC1C,CAAC;AAED,IAAM,kBAAkB,oBAAK,OAAO;AAAA,EAClC,MAAM,oBAAK,QAAQ,OAAO;AAAA,EAC1B,MAAM,oBAAK,OAAO,EAAE,SAAS,0BAA0B,CAAC;AAC1D,CAAC;AAED,IAAM,oBAAoB,oBAAK,OAAO;AAAA,EACpC,MAAM,oBAAK,QAAQ,SAAS;AAAA,EAC5B,KAAK,oBAAK,OAAO;AACnB,CAAC;AAED,IAAM,qBAAqB,oBAAK,OAAO;AAAA,EACrC,MAAM,oBAAK,QAAQ,UAAU;AAAA,EAC7B,YAAY,oBAAK,OAAO;AAC1B,CAAC;AAED,IAAM,kBAAkB,oBAAK,MAAM,CAAC,iBAAiB,mBAAmB,kBAAkB,CAAC;AAE3F,IAAM,cAAc,oBAAK,OAAO;AAAA,EAC9B,OAAO,oBAAK,MAAM,iBAAiB;AAAA,IACjC,SAAS,CAAC,EAAE,MAAM,SAAS,MAAM,0BAA0B,CAAC;AAAA,EAC9D,CAAC;AACH,CAAC;AAED,IAAM,kBAAkB,oBAAK,OAAO;AAAA,EAClC,MAAM,oBAAK,SAAS,oBAAK,QAAQ,UAAU,CAAC;AAAA,EAC5C,QAAQ,oBAAK;AAAA,IACX,oBAAK,OAAO;AAAA,MACV,aAAa,oBAAK,SAAS,oBAAK,OAAO,CAAC;AAAA,MACxC,aAAa,oBAAK,SAAS,oBAAK,OAAO,CAAC;AAAA,IAC1C,CAAC;AAAA,EACH;AACF,CAAC;AAID,IAAM,mBAAmB,oBAAK,OAAO;AAAA,EACnC,UAAU,oBAAK,MAAM,CAAC,oBAAK,QAAQ,SAAS,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,MAAM,CAAC,GAAG;AAAA,IAC1F,SAAS;AAAA,EACX,CAAC;AAAA,EACD,YAAY,oBAAK,SAAS,oBAAK,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC,CAAC;AAAA,EACjE,aAAa,oBAAK,SAAS,oBAAK,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED,IAAM,yBAAyB,oBAAK,OAAO;AAAA,EACzC,MAAM,oBAAK,OAAO;AAAA,EAClB,SAAS,oBAAK,OAAO;AAAA,EACrB,UAAU,oBAAK,MAAM;AAAA,IACnB,oBAAK,QAAQ,KAAK;AAAA,IAClB,oBAAK,QAAQ,QAAQ;AAAA,IACrB,oBAAK,QAAQ,MAAM;AAAA,IACnB,oBAAK,QAAQ,UAAU;AAAA,EACzB,CAAC;AAAA,EACD,QAAQ,oBAAK;AAAA,IACX,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,CAAC;AAAA,EACjF;AACF,CAAC;AAED,IAAM,0BAA0B,oBAAK,OAAO;AAAA,EAC1C,SAAS,oBAAK,OAAO;AACvB,CAAC;AAED,IAAM,wBAAwB,oBAAK,OAAO;AAAA,EACxC,SAAS,oBAAK,SAAS,oBAAK,QAAQ,CAAC;AAAA,EACrC,MAAM,oBAAK;AAAA,IACT,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,CAAC;AAAA,EACjF;AAAA,EACA,UAAU,oBAAK;AAAA,IACb,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,CAAC;AAAA,EACjF;AAAA,EACA,WAAW,oBAAK;AAAA,IACd,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,CAAC;AAAA,EACjF;AACF,CAAC;AAED,IAAM,YAAY,oBAAK,OAAO;AAAA,EAC5B,SAAS,oBAAK,QAAQ,EAAE,SAAS,MAAM,CAAC;AAAA,EACxC,MAAM,oBAAK;AAAA,IACT,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,GAAG;AAAA,MAC/E,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EACA,UAAU,oBAAK;AAAA,IACb,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,CAAC;AAAA,EACjF;AAAA,EACA,WAAW,oBAAK;AAAA,IACd,oBAAK,MAAM,CAAC,oBAAK,QAAQ,OAAO,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,OAAO,CAAC,CAAC;AAAA,EACjF;AAAA,EACA,SAAS,oBAAK,SAAS,gBAAgB;AAAA,EACvC,oBAAoB,oBAAK;AAAA,IACvB,oBAAK;AAAA,MACH,CAAC,oBAAK,QAAQ,KAAK,GAAG,oBAAK,QAAQ,QAAQ,GAAG,oBAAK,QAAQ,MAAM,GAAG,oBAAK,QAAQ,UAAU,CAAC;AAAA,MAC5F,EAAE,SAAS,MAAM;AAAA,IACnB;AAAA,EACF;AAAA,EACA,UAAU,oBAAK;AAAA,IACb,oBAAK,OAAO;AAAA,MACV,SAAS,oBAAK,QAAQ,EAAE,SAAS,KAAK,CAAC;AAAA,MACvC,KAAK,oBAAK,QAAQ,EAAE,SAAS,KAAK,CAAC;AAAA,IACrC,CAAC;AAAA,EACH;AAAA,EACA,iBAAiB,oBAAK,SAAS,oBAAK,MAAM,sBAAsB,CAAC;AAAA,EACjE,WAAW,oBAAK,SAAS,oBAAK,MAAM,uBAAuB,CAAC;AAAA,EAC5D,gBAAgB,oBAAK,SAAS,oBAAK,OAAO,oBAAK,OAAO,GAAG,qBAAqB,CAAC;AACjF,CAAC;AAIM,IAAM,yBAAyB,oBAAK,OAAO;AAAA,EAChD,MAAM,oBAAK,SAAS,UAAU;AAAA,EAC9B,QAAQ,oBAAK,SAAS,YAAY;AAAA,EAClC,WAAW,oBAAK,SAAS,eAAe;AAAA,EACxC,MAAM,oBAAK,SAAS,UAAU;AAAA,EAC9B,OAAO,oBAAK,SAAS,WAAW;AAAA,EAChC,KAAK,oBAAK,SAAS,SAAS;AAAA,EAC5B,WAAW,oBAAK,SAAS,oBAAK,OAAO,oBAAK,OAAO,GAAG,eAAe,CAAC;AACtE,CAAC;;;AC1KM,IAAM,WAA6B;AAAA,EACxC,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,KAAK;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,MACV,cAAc;AAAA,IAChB;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,MACJ,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT,WAAW;AAAA,IACX,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,IACL,OAAO,CAAC,EAAE,MAAM,SAAS,MAAM,0BAA0B,CAAC;AAAA,EAC5D;AAAA,EACA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AACF;;;AF1BA,SAAS,iBAAyC;AAChD,SAAO;AAAA,IACL,QAAQ,IAAI,yBAAyB;AAAA,IACrC;AAAA,IACA,GAAG,QAAQ,IAAI,MAAM,CAAC;AAAA,EACxB;AACF;AAEO,SAAS,aAA2D;AACzE,aAAW,QAAQ,eAAe,GAAG;AACnC,QAAI,YAAQ,sBAAW,IAAI,GAAG;AAC5B,YAAM,UAAM,wBAAa,MAAM,OAAO;AACtC,YAAM,aAAS,YAAAC,OAAU,GAAG;AAE5B,YAAM,WAAW,eAAe,MAAM;AAEtC,YAAM,SAAS,CAAC,GAAG,mBAAM,OAAO,wBAAwB,QAAQ,CAAC;AACjE,UAAI,OAAO,SAAS,GAAG;AACrB,cAAM,IAAI;AAAA,UACR;AAAA,UACA,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,EAAE;AAAA,QAC1D;AAAA,MACF;AAEA,YAAM,SAAS,mBAAM,QAAQ,wBAAwB,QAAQ;AAC7D,aAAO,EAAE,QAAQ,QAAQ,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,UAAU,QAAQ,WAAW;AAChD;AAEA,SAAS,eAAe,KAAuB;AAC7C,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,IAAI,QAAQ,gBAAgB,CAAC,GAAG,SAAiB,QAAQ,IAAI,IAAI,KAAK,EAAE;AAAA,EACjF;AACA,MAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI,IAAI,cAAc;AACrD,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,GAA8B,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC;AAAA,IACvF;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/C,YAAY,MAAc,QAAkD;AAC1E,UAAM,UAAU,OAAO,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACxE,UAAM,gCAAgC,IAAI;AAAA,EAAM,OAAO,EAAE;AACzD,SAAK,OAAO;AAAA,EACd;AACF;;;AGvDO,IAAM,sBAAN,MAAsD;AAAA,EAG3D,YACU,UAAkB,cAClB,UAAkB,cAClB,aAAqB,kBAC7B;AAHQ;AACA;AACA;AAAA,EACP;AAAA,EANH,OAAO;AAAA,EAQP,MAAM,UAA4C;AAChD,UAAM,SAAS,QAAQ,IAAI,KAAK,OAAO;AACvC,UAAM,OAAO,QAAQ,IAAI,KAAK,OAAO;AACrC,UAAM,UAAU,QAAQ,IAAI,KAAK,UAAU;AAE3C,QAAI,CAAC,UAAU,CAAC,KAAM,QAAO;AAE7B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS,WAAW;AAAA,MACpB,QAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ACzBA,IAAAC,aAA6B;AAC7B,IAAAC,eAAmC;AAQ5B,IAAM,wBAAN,MAAwD;AAAA,EAC7D,OAAO;AAAA,EACC;AAAA,EAER,YAAY,eAAuB;AACjC,UAAM,UAAM,yBAAa,eAAe,OAAO;AAC/C,SAAK,YAAQ,aAAAC,OAAU,GAAG;AAAA,EAC5B;AAAA,EAEA,MAAM,UAA4C;AAEhD,UAAM,WAAW,QAAQ,IAAI,QAAQ,QAAQ,IAAI;AACjD,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,QAAQ,KAAK,MAAM,QAAQ;AACjC,QAAI,CAAC,MAAO,QAAO;AAEnB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM,YAAY;AAAA,MAC3B,QAAQ;AAAA,IACV;AAAA,EACF;AACF;;;AC5BO,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EAER,YAAY,WAA+B;AACzC,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,UAAqC;AACzC,eAAW,YAAY,KAAK,WAAW;AACrC,YAAM,WAAW,MAAM,SAAS,QAAQ;AACxC,UAAI,SAAU,QAAO;AAAA,IACvB;AAGA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,QAAwC;AAC1E,QAAM,YAAgC,CAAC;AAGvC,YAAU;AAAA,IACR,IAAI;AAAA,MACF,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAGA,MAAI,QAAQ,aAAa,WAAW,OAAO,OAAO,YAAY;AAC5D,QAAI;AACF,gBAAU,KAAK,IAAI,sBAAsB,OAAO,MAAM,UAAU,CAAC;AAAA,IACnE,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,IAAI,cAAc,SAAS;AACpC;;;AClDA,IAAAC,aAA6B;AAC7B,IAAAC,eAAmC;AACnC,uBAA0B;AA+BnB,IAAM,mBAAN,MAA+C;AAAA,EAC5C;AAAA,EAER,YAAY,sBAA0C;AACpD,QAAI,OAAO,yBAAyB,UAAU;AAC5C,YAAM,UAAM,yBAAa,sBAAsB,OAAO;AACtD,WAAK,YAAQ,aAAAC,OAAU,GAAG;AAAA,IAC5B,OAAO;AACL,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,QAAQ,MAAwB;AACtC,UAAM,IAAI,KAAK,MAAM,MAAM,IAAI;AAC/B,QAAI,CAAC,GAAG;AACN,YAAM,IAAI;AAAA,QACR,iBAAiB,IAAI,sBAAsB,OAAO,KAAK,KAAK,MAAM,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,MACrF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,MAAc,MAA8B;AACvD,UAAM,IAAI,KAAK,QAAQ,IAAI;AAG3B,QAAI,EAAE,cAAc,SAAS,IAAI,EAAG,QAAO;AAG3C,QAAI,EAAE,cAAc,SAAS,KAAK,KAAK,EAAE,cAAc,SAAS,IAAI,GAAG;AACrE,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA,EAEA,aACE,MACA,UACA,YACA,MACgB;AAChB,UAAM,IAAI,KAAK,QAAQ,IAAI;AAG3B,eAAW,WAAW,EAAE,eAAe;AACrC,cAAI,4BAAU,MAAM,SAAS,EAAE,KAAK,KAAK,CAAC,GAAG;AAC3C,eAAO;AAAA,MACT;AAAA,IACF;AAGA,eAAW,WAAW,EAAE,eAAe;AACrC,YAAM,WAAW,QAAQ,QAAQ,oBAAoB,QAAQ,IAAI,CAAC;AAClE,cAAI,4BAAU,MAAM,UAAU,EAAE,KAAK,KAAK,CAAC,GAAG;AAC5C,eAAO;AAAA,MACT;AAAA,IACF;AAGA,WAAO;AAAA,EACT;AAAA,EAEA,iBAAiB,MAAc,MAAuB;AACpD,UAAM,IAAI,KAAK,QAAQ,IAAI;AAG3B,QAAI,EAAE,eAAe,cAAc,SAAS,IAAI,EAAG,QAAO;AAG1D,QAAI,EAAE,eAAe,aAAa,SAAS,KAAK,EAAG,QAAO;AAC1D,WAAO,EAAE,eAAe,aAAa,SAAS,IAAI;AAAA,EACpD;AAAA,EAEA,iBAAiB,MAA6B;AAC5C,WAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,EAC5B;AAAA,EAEA,gBAAgB,MAAsB;AACpC,WAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,EAC5B;AAAA,EAEA,iBAAiB,MAA6B;AAC5C,UAAM,IAAI,KAAK,QAAQ,IAAI;AAC3B,UAAM,YAAY,EAAE;AACpB,QAAI,CAAC,UAAW,QAAO,CAAC;AAExB,WAAO;AAAA,MACL,mBAAmB,UAAU,oBAAoB,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC;AAAA,MACzE,mBAAmB,UAAU,oBAAoB,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,eAAe,MAAsB;AACnC,WAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,EAC5B;AACF;;;AClIO,IAAM,gBAA0B;AAAA;AAAA,EAErC;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AACF;AAEO,IAAM,qBAA+B;AAAA;AAAA,EAE1C;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AACF;;;ACtIO,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA;AAAA,EAER,YAAY,WAA2B;AACrC,SAAK,eAAe,CAAC,GAAG,eAAe,GAAI,WAAW,qBAAqB,CAAC,CAAE;AAC9E,SAAK,oBAAoB,CAAC,GAAG,oBAAoB,GAAI,WAAW,qBAAqB,CAAC,CAAE;AAAA,EAC1F;AAAA,EAEA,SAAS,SAAqC;AAC5C,UAAM,UAAU,QAAQ,KAAK;AAI7B,eAAW,WAAW,KAAK,mBAAmB;AAC5C,UAAI,QAAQ,KAAK,OAAO,EAAG,QAAO;AAAA,IACpC;AAKA,UAAM,WAAW,KAAK,aAAa,OAAO;AAE1C,QAAI,SAAS,SAAS,GAAG;AACvB,YAAM,kBAAkB,SAAS,IAAI,CAAC,MAAM,KAAK,eAAe,CAAC,CAAC;AAClE,UAAI,gBAAgB,SAAS,WAAW,EAAG,QAAO;AAClD,UAAI,gBAAgB,SAAS,cAAc,EAAG,QAAO;AACrD,aAAO;AAAA,IACT;AAEA,WAAO,KAAK,eAAe,OAAO;AAAA,EACpC;AAAA,EAEQ,eAAe,SAAqC;AAC1D,UAAM,UAAU,QAAQ,KAAK;AAG7B,eAAW,WAAW,KAAK,mBAAmB;AAC5C,UAAI,QAAQ,KAAK,OAAO,EAAG,QAAO;AAAA,IACpC;AAGA,eAAW,WAAW,KAAK,cAAc;AACvC,UAAI,QAAQ,KAAK,OAAO,EAAG,QAAO;AAAA,IACpC;AAGA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,SAA2B;AAG9C,UAAM,WAAqB,CAAC;AAC5B,QAAI,UAAU;AACd,QAAI,gBAAgB;AACpB,QAAI,gBAAgB;AACpB,QAAI,UAAU;AAEd,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAM,OAAO,QAAQ,CAAC;AAEtB,UAAI,SAAS;AACX,mBAAW;AACX,kBAAU;AACV;AAAA,MACF;AAEA,UAAI,SAAS,MAAM;AACjB,kBAAU;AACV,mBAAW;AACX;AAAA,MACF;AAEA,UAAI,SAAS,OAAO,CAAC,eAAe;AAClC,wBAAgB,CAAC;AACjB,mBAAW;AACX;AAAA,MACF;AAEA,UAAI,SAAS,OAAO,CAAC,eAAe;AAClC,wBAAgB,CAAC;AACjB,mBAAW;AACX;AAAA,MACF;AAEA,UAAI,CAAC,iBAAiB,CAAC,eAAe;AACpC,YAAI,SAAS,OAAO,QAAQ,IAAI,CAAC,MAAM,KAAK;AAC1C,mBAAS,KAAK,QAAQ,KAAK,CAAC;AAC5B,oBAAU;AACV;AAAA,QACF;AACA,YAAI,SAAS,KAAK;AAChB,mBAAS,KAAK,QAAQ,KAAK,CAAC;AAC5B,oBAAU;AACV;AAAA,QACF;AACA,YAAI,SAAS,OAAO,QAAQ,IAAI,CAAC,MAAM,KAAK;AAC1C,mBAAS,KAAK,QAAQ,KAAK,CAAC;AAC5B,oBAAU;AACV;AACA;AAAA,QACF;AACA,YAAI,SAAS,OAAO,QAAQ,IAAI,CAAC,MAAM,KAAK;AAC1C,mBAAS,KAAK,QAAQ,KAAK,CAAC;AAC5B,oBAAU;AACV;AACA;AAAA,QACF;AAAA,MACF;AAEA,iBAAW;AAAA,IACb;AAEA,QAAI,QAAQ,KAAK,EAAG,UAAS,KAAK,QAAQ,KAAK,CAAC;AAChD,WAAO,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EAC5C;AACF;;;AC1HA,yBAA2B;;;ACA3B,sBAAkC;AAClC,uBAAwB;AACxB,qBAAwB;AAGjB,IAAM,iBAAN,MAA0C;AAAA,EACvC;AAAA,EACA,SAAoC,CAAC;AAAA,EAC5B,iBAAiB;AAAA,EAElC,YAAY,MAAc;AACxB,SAAK,OAAO,KAAK,QAAQ,UAAM,wBAAQ,CAAC;AAAA,EAC1C;AAAA,EAEA,MAAM,MAAM,QAAgD;AAC1D,SAAK,OAAO,KAAK,MAAM;AACvB,QAAI,KAAK,OAAO,UAAU,KAAK,gBAAgB;AAC7C,YAAM,KAAK,MAAM;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,OAAO,WAAW,EAAG;AAC9B,UAAM,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI;AACrE,SAAK,SAAS,CAAC;AACf,cAAM,2BAAM,0BAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACnD,cAAM,4BAAW,KAAK,MAAM,OAAO,OAAO;AAAA,EAC5C;AACF;;;AC1BO,IAAM,mBAAN,MAA4C;AAAA,EACzC;AAAA,EACA,SAAoC,CAAC;AAAA,EAC5B,iBAAiB;AAAA,EAElC,YAAY,KAAa;AACvB,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,MAAM,MAAM,QAAgD;AAC1D,SAAK,OAAO,KAAK,MAAM;AACvB,QAAI,KAAK,OAAO,UAAU,KAAK,gBAAgB;AAC7C,YAAM,KAAK,MAAM;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,OAAO,WAAW,EAAG;AAC9B,UAAM,UAAU,CAAC,GAAG,KAAK,MAAM;AAC/B,SAAK,SAAS,CAAC;AAEf,QAAI;AACF,YAAM,KAAK,KAAK,OAAO;AAAA,IACzB,QAAQ;AAEN,UAAI;AACF,cAAM,KAAK,KAAK,OAAO;AAAA,MACzB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,KAAK,SAAmD;AACpE,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,GAAM;AAE3D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,KAAK;AAAA,QACrC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,EAAE;AAAA,MACvD;AAAA,IACF,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AACF;;;AFrCO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA,SAAsC,oBAAI,IAAI;AAAA,EAEtD,YAAY,QAAsB;AAChC,UAAM,cAAc,QAAQ,SAAS;AAAA,MACnC,EAAE,MAAM,SAAkB,MAAM,0BAA0B;AAAA,IAC5D;AACA,SAAK,QAAQ,CAAC;AAEd,eAAW,MAAM,aAAa;AAC5B,UAAI,GAAG,SAAS,SAAS;AACvB,aAAK,MAAM,KAAK,IAAI,eAAe,GAAG,QAAQ,yBAAyB,CAAC;AAAA,MAC1E,WAAW,GAAG,SAAS,aAAa,GAAG,KAAK;AAC1C,aAAK,MAAM,KAAK,IAAI,iBAAiB,GAAG,GAAG,CAAC;AAAA,MAC9C;AAAA,IAEF;AAGA,QAAI,KAAK,MAAM,WAAW,GAAG;AAC3B,WAAK,MAAM,KAAK,IAAI,eAAe,yBAAyB,CAAC;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,QAA8D;AACtE,UAAM,OAAoB;AAAA,MACxB,GAAG;AAAA,MACH,QAAI,+BAAW;AAAA,MACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAEA,SAAK,OAAO,IAAI,KAAK,QAAQ,KAAK,OAAO,IAAI,KAAK,KAAK,KAAK,KAAK,CAAC;AAElE,UAAM,QAAQ,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,IAA0C,CAAC,CAAC;AAAA,EAC9F;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,QAAQ,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAAA,EACpD;AAAA,EAEA,aAA0C;AACxC,WAAO,IAAI,IAAI,KAAK,MAAM;AAAA,EAC5B;AACF;;;AG3DO,IAAM,cAAN,MAA0C;AAAA,EACvC;AAAA,EACA;AAAA,EAER,YAAY,IAAe,iBAAyB,KAAK;AACvD,SAAK,KAAK;AACV,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,MAAM,gBACJ,UACA,SACyB;AACzB,UAAM,QAAQ,sBAAsB,SAAS,QAAQ;AACrD,UAAM,eAAe,OAAO,QAAQ,SAAS,KAAK,EAC/C;AAAA,MACC,CAAC,CAAC,GAAG,CAAC,MACJ,KAAK,CAAC,KAAK,OAAO,MAAM,WAAW,EAAE,MAAM,GAAG,GAAG,IAAI,KAAK,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,IACxF,EACC,KAAK,IAAI;AACZ,UAAM,UAAU,SAAS,QAAQ,MAAM,KAAK,QAAQ,IAAI;AAAA,OAAW,QAAQ,OAAO;AAAA;AAAA,QAAa,SAAS,QAAQ;AAAA;AAAA,EAAa,YAAY;AAEzI,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,GAAG,QAAQ,OAAO,SAAS;AAAA,QACrD,SAAS,KAAK,iBAAiB;AAAA,MACjC,CAAC;AAED,aAAO;AAAA,QACL;AAAA,QACA,UAAU;AAAA,QACV,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,QAAQ,WAAW,SAAY;AAAA,MACjC;AAAA,IACF,QAAQ;AAEN,aAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;;;AC7CO,IAAM,kBAAN,MAA8C;AAAA,EAC3C;AAAA,EACA;AAAA,EAER,YAAY,KAAa,iBAAyB,KAAK;AACrD,SAAK,MAAM;AACX,SAAK,YAAY,iBAAiB;AAAA,EACpC;AAAA,EAEA,MAAM,gBACJ,UACA,SACyB;AACzB,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AAEnE,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,KAAK;AAAA,QACrC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB,UAAU,EAAE,UAAU,SAAS,UAAU,OAAO,SAAS,MAAM;AAAA,UAC/D;AAAA,QACF,CAAC;AAAA,QACD,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,eAAO;AAAA,UACL,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU,KAAK,IAAI,IAAI;AAAA,UACvB,QAAQ,oBAAoB,SAAS,MAAM;AAAA,QAC7C;AAAA,MACF;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,UAAU;AAAA,QACV,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,QAAQ,KAAK;AAAA,MACf;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,QACE,eAAe,SAAS,IAAI,SAAS,eACjC,sBACA;AAAA,MACR;AAAA,IACF,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AACF;;;AC5BO,SAAS,mBAAmB,QAAoB,IAA8B;AACnF,MAAI,OAAO,qBAAqB,aAAa,OAAO,SAAS,KAAK;AAChE,WAAO,IAAI,gBAAgB,OAAO,QAAQ,KAAK,OAAO,eAAe;AAAA,EACvE;AAGA,MAAI,CAAC,IAAI;AACP,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AAEA,SAAO,IAAI,YAAY,IAAI,OAAO,eAAe;AACnD;;;ACxCO,IAAM,gBAAN,MAAoB;AAAA,EACjB,QAAQ;AAAA,EACC;AAAA,EAEjB,YAAY,QAAgB;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA,EAGA,QAAQ,SAAS,GAAY;AAC3B,QAAI,KAAK,YAAY,IAAI;AACvB,WAAK,SAAS;AACd,aAAO;AAAA,IACT;AACA,QAAI,KAAK,QAAQ,SAAS,KAAK,QAAS,QAAO;AAC/C,SAAK,SAAS;AACd,WAAO;AAAA,EACT;AAAA,EAEA,YAAoB;AAClB,QAAI,KAAK,YAAY,GAAI,QAAO;AAChC,WAAO,KAAK,IAAI,GAAG,KAAK,UAAU,KAAK,KAAK;AAAA,EAC9C;AAAA,EAEA,OAAe;AACb,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,YAAY;AAAA,EAC1B;AACF;;;ACnCA,qBAAoD;AACpD,IAAAC,eAAmC;AACnC,IAAAC,gBAAsB;AAOf,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EACA;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YACE,YACA,UACA,SACA;AACA,SAAK,aAAa;AAClB,SAAK,WAAW;AAChB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,QAAS;AAClB,SAAK,cAAU,sBAAM,KAAK,YAAY,MAAM,KAAK,aAAa,CAAC;AAAA,EACjE;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,eAAe;AACtB,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AACA,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,MAAM;AACnB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,SAAK,gBAAgB,WAAW,MAAM,KAAK,OAAO,GAAG,GAAG;AAAA,EAC1D;AAAA,EAEQ,SAAe;AACrB,QAAI;AACF,YAAM,UAAM,6BAAa,KAAK,YAAY,OAAO;AACjD,YAAM,aAAS,aAAAC,OAAU,GAAG;AAC5B,YAAM,SAAS,CAAC,GAAG,oBAAM,OAAO,wBAAwB,MAAM,CAAC;AAC/D,UAAI,OAAO,SAAS,GAAG;AACrB,cAAM,MAAM,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAClE,aAAK,UAAU,IAAI,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAC5D;AAAA,MACF;AACA,YAAM,SAAS,oBAAM,QAAQ,wBAAwB,MAAM;AAC3D,WAAK,SAAS,MAAM;AAAA,IACtB,SAAS,KAAK;AACZ,WAAK,UAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,IACpE;AAAA,EACF;AACF;;;ACrDO,IAAM,kBAAmC;AAAA;AAAA,EAE9C;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SACE;AAAA,IACF,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,eAAgC;AAAA;AAAA,EAE3C;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SACE;AAAA,IACF,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,SACE;AAAA,IACF,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACF;;;ACvIA,IAAM,iBAA8C;AAAA,EAClD,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AACZ;AAOO,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA0B;AACpC,SAAK,SAAS;AACd,SAAK,oBAAoB,eAAe,OAAO,kBAAkB;AACjE,SAAK,WAAW,CAAC;AACjB,SAAK,mBAAmB,CAAC;AAGzB,QAAI,OAAO,SAAS,SAAS;AAC3B,iBAAW,OAAO,iBAAiB;AACjC,aAAK,SAAS,KAAK,EAAE,IAAI,CAAC;AAAA,MAC5B;AAAA,IACF;AACA,QAAI,OAAO,SAAS,KAAK;AACvB,iBAAW,OAAO,cAAc;AAC9B,aAAK,SAAS,KAAK,EAAE,IAAI,CAAC;AAAA,MAC5B;AAAA,IACF;AAGA,eAAW,MAAM,OAAO,iBAAiB;AACvC,YAAM,MAAqB;AAAA,QACzB,MAAM,GAAG;AAAA,QACT,SAAS,IAAI,OAAO,GAAG,SAAS,GAAG;AAAA,QACnC,UAAU,GAAG;AAAA,QACb,UAAU;AAAA,MACZ;AACA,WAAK,SAAS,KAAK,EAAE,KAAK,QAAQ,GAAG,OAAO,CAAC;AAAA,IAC/C;AAGA,eAAW,YAAY,KAAK,UAAU;AACpC,YAAM,WAAW,OAAO,kBAAkB,IAAI,SAAS,IAAI,IAAI;AAC/D,UAAI,UAAU;AACZ,iBAAS,SAAS;AAAA,MACpB;AAAA,IACF;AAGA,eAAW,SAAS,OAAO,WAAW;AACpC,WAAK,iBAAiB,KAAK,IAAI,OAAO,MAAM,OAAO,CAAC;AAAA,IACtD;AAAA,EACF;AAAA,EAEA,KAAK,MAA6B;AAChC,QAAI,CAAC,KAAK,OAAO,WAAW,KAAK,WAAW,GAAG;AAC7C,aAAO,EAAE,YAAY,OAAO,SAAS,CAAC,EAAE;AAAA,IAC1C;AAEA,UAAM,UAAsB,CAAC;AAE7B,eAAW,YAAY,KAAK,UAAU;AAEpC,UAAI,eAAe,SAAS,IAAI,QAAQ,IAAI,KAAK,mBAAmB;AAClE;AAAA,MACF;AAGA,YAAM,QAAQ,IAAI,OAAO,SAAS,IAAI,QAAQ,QAAQ,SAAS,IAAI,QAAQ,KAAK;AAEhF,UAAI;AACJ,cAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAE1C,cAAM,UAAU,MAAM,CAAC,KAAK,MAAM,CAAC;AACnC,cAAM,QAAQ,MAAM,CAAC,IAAI,MAAM,QAAQ,MAAM,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,IAAI,MAAM;AAC1E,cAAM,MAAM,QAAQ,QAAQ;AAG5B,YAAI,KAAK,cAAc,OAAO,GAAG;AAC/B;AAAA,QACF;AAEA,gBAAQ,KAAK;AAAA,UACX,aAAa,SAAS,IAAI;AAAA,UAC1B,UAAU,SAAS,IAAI;AAAA,UACvB,UAAU,SAAS,IAAI;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO,EAAE,YAAY,QAAQ,SAAS,GAAG,QAAQ;AAAA,EACnD;AAAA,EAEA,UAAU,WAA0C;AAClD,QAAI,cAAc,WAAW,KAAK,OAAO,UAAU;AACjD,aAAO,KAAK,OAAO;AAAA,IACrB;AACA,QAAI,cAAc,YAAY,KAAK,OAAO,WAAW;AACnD,aAAO,KAAK,OAAO;AAAA,IACrB;AACA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,iBAAiB,OAAiB,WAA0C;AAE1E,UAAM,WAAW,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,IAAI,SAAS,MAAM,WAAW;AAC3E,QAAI,UAAU,QAAQ;AACpB,aAAO,SAAS;AAAA,IAClB;AAGA,WAAO,KAAK,UAAU,SAAS;AAAA,EACjC;AAAA,EAEQ,cAAc,OAAwB;AAC5C,eAAW,MAAM,KAAK,kBAAkB;AACtC,UAAI,GAAG,KAAK,KAAK,EAAG,QAAO;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AACF;;;AC5KA,IAAAC,sBAA2B;AAS3B,IAAM,iBAAgC;AAAA,EACpC,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AACf;AAEO,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EAER,YAAY,QAAiC;AAC3C,SAAK,SAAS,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAAA,EAC/C;AAAA,EAEA,UAAU,OAAuB;AAC/B,YAAQ,KAAK,OAAO,UAAU;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,OAAO;AAAA,MACrB,KAAK,QAAQ;AACX,cAAM,WAAO,gCAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC;AACxE,eAAO,aAAa,IAAI;AAAA,MAC1B;AAAA,MACA,KAAK;AAAA,MACL,SAAS;AACP,YAAI,MAAM,UAAU,KAAK,OAAO,YAAY;AAC1C,iBAAO,KAAK,OAAO;AAAA,QACrB;AACA,eAAO,KAAK,OAAO,cAAc,MAAM,MAAM,CAAC,KAAK,OAAO,UAAU;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS,MAAc,SAA6B;AAClD,QAAI,QAAQ,WAAW,EAAG,QAAO;AAGjC,UAAM,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAE5D,QAAI,SAAS;AACb,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,KAAK,UAAU,MAAM,OAAO;AAC3C,eAAS,OAAO,MAAM,GAAG,MAAM,KAAK,IAAI,SAAS,OAAO,MAAM,MAAM,GAAG;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AACF;;;ApBmBA,IAAM,aAAqC;AAAA,EACzC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,IAAI;AACN;AAGA,IAAM,cAAc,oBAAI,IAAI,CAAC,SAAS,MAAM,CAAC;AAE7C,SAAS,gBACP,UACA,OACyB;AACzB,UAAQ,UAAU;AAAA,IAChB,KAAK,QAAQ;AACX,YAAM,MAAM,OAAO,MAAM,SAAS,MAAM,WAAW,MAAM,SAAS,IAAI;AACtE,aAAO,EAAE,SAAS,IAAI,MAAM,GAAG,GAAG,KAAK,IAAI,SAAS,MAAM,QAAQ,IAAI;AAAA,IACxE;AAAA,IACA,KAAK;AACH,aAAO,EAAE,MAAM,MAAM,MAAM,EAAE;AAAA,IAC/B,KAAK;AACH,aAAO,EAAE,MAAM,MAAM,MAAM,EAAE;AAAA,IAC/B,KAAK;AACH,aAAO,EAAE,WAAW,MAAM,WAAW,EAAE;AAAA,IACzC,KAAK;AACH,aAAO,EAAE,SAAS,MAAM,SAAS,GAAG,MAAM,MAAM,MAAM,EAAE;AAAA,IAC1D,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,MAAM,MAAM,MAAM,EAAE;AAAA,IAC/B;AACE,aAAO,CAAC;AAAA,EACZ;AACF;AAEA,SAAS,YAAY,UAAkB,OAAoD;AACzF,QAAM,MAAM,WAAW,QAAQ;AAC/B,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,MAAM,GAAG;AACrB,SAAO,OAAO,QAAQ,WAAW,MAAM;AACzC;AAIA,IAAM,kBAA6C,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,EAAE;AAEjF,SAAS,iBAAiB,UAAkB,OAAqD;AAC/F,QAAM,SAAS,oBAAI,IAAoB;AACvC,UAAQ,UAAU;AAAA,IAChB,KAAK,QAAQ;AACX,YAAM,MAAM,MAAM,SAAS;AAC3B,UAAI,OAAO,QAAQ,SAAU,QAAO,IAAI,WAAW,GAAG;AACtD;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,UAAU,MAAM,SAAS;AAC/B,UAAI,OAAO,YAAY,SAAU,QAAO,IAAI,WAAW,OAAO;AAC9D,YAAM,OAAO,MAAM,MAAM;AACzB,UAAI,OAAO,SAAS,SAAU,QAAO,IAAI,QAAQ,IAAI;AACrD;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,SAAS,MAAM,YAAY;AACjC,UAAI,OAAO,WAAW,SAAU,QAAO,IAAI,cAAc,MAAM;AAC/D,YAAM,SAAS,MAAM,YAAY;AACjC,UAAI,OAAO,WAAW,SAAU,QAAO,IAAI,cAAc,MAAM;AAC/D;AAAA,IACF;AAAA,IACA,SAAS;AAEP,iBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,YAAI,OAAO,QAAQ,SAAU,QAAO,IAAI,KAAK,GAAG;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBACP,SACA,SACA,WACW;AACX,MAAI,UAAqB;AACzB,aAAW,SAAS,SAAS;AAC3B,UAAM,SAAS,QAAQ,iBAAiB,OAAO,SAAS;AACxD,QAAI,gBAAgB,MAAM,IAAI,gBAAgB,OAAO,GAAG;AACtD,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBACP,WACA,MAC8B;AAC9B,MAAI,CAAC,WAAW,QAAS,QAAO;AAGhC,QAAM,eAAe,UAAU,iBAAiB,IAAI;AACpD,MAAI,cAAc,YAAY,MAAO,QAAO;AAE5C,QAAM,mBAAmB,oBAAI,IAAuB;AAEpD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,cAAc,QAAQ,UAAU,QAAQ;AAAA,IAC9C,UAAU,cAAc,YAAY,UAAU;AAAA,IAC9C,WAAW,cAAc,aAAa,UAAU;AAAA,IAChD,oBAAoB,UAAU,sBAAsB;AAAA,IACpD,UAAU;AAAA,MACR,SAAS,UAAU,UAAU,WAAW;AAAA,MACxC,KAAK,UAAU,UAAU,OAAO;AAAA,IAClC;AAAA,IACA,kBAAkB,UAAU,mBAAmB,CAAC,GAAG,IAAI,CAAC,QAAQ;AAAA,MAC9D,MAAM,GAAG;AAAA,MACT,SAAS,GAAG;AAAA,MACZ,UAAU,GAAG;AAAA,MACb,QAAQ,GAAG;AAAA,IACb,EAAE;AAAA,IACF,WAAW,UAAU,aAAa,CAAC;AAAA,IACnC,mBAAmB;AAAA,EACrB;AACF;AAEA,IAAM,eAAiC,CAAC,OAAO;AAE7C,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,EACb;AAEA,KAAG,GAAG,iBAAiB,OAAO,QAAQ,QAAQ;AAC5C,gBAAY,IAAI;AAGhB,UAAM,SAAS,WAAW;AAC1B,aAAS,OAAO;AAGhB,UAAM,QAAQ,oBAAoB,OAAO,IAAI;AAC7C,eAAW,MAAM,MAAM,QAAQ;AAG/B,UAAM,YAAY,OAAO,QAAQ,MAAM,cAAc;AACrD,YAAI,4BAAW,SAAS,GAAG;AACzB,qBAAe,IAAI,iBAAiB,SAAS;AAAA,IAC/C,OAAO;AAEL,qBAAe,IAAI,iBAAiB;AAAA,QAClC,OAAO;AAAA,UACL,OAAO;AAAA,YACL,eAAe,CAAC,KAAK;AAAA,YACrB,eAAe,CAAC;AAAA,YAChB,iBAAiB;AAAA,YACjB,gBAAgB;AAAA,YAChB,gBAAgB,EAAE,cAAc,CAAC,EAAE;AAAA,YACnC,oBAAoB;AAAA,YACpB,eAAe,CAAC,IAAI;AAAA,YACpB,eAAe,CAAC;AAAA,UAClB;AAAA,UACA,cAAc;AAAA,YACZ,eAAe,CAAC,KAAK;AAAA,YACrB,eAAe,CAAC;AAAA,YAChB,iBAAiB;AAAA,YACjB,gBAAgB;AAAA,YAChB,gBAAgB,EAAE,cAAc,CAAC,QAAQ,OAAO,EAAE;AAAA,YAClD,oBAAoB;AAAA,YACpB,eAAe,CAAC,IAAI;AAAA,YACpB,eAAe,CAAC;AAAA,UAClB;AAAA,UACA,SAAS;AAAA,YACP,eAAe,CAAC,QAAQ,QAAQ,QAAQ,IAAI;AAAA,YAC5C,eAAe,CAAC,SAAS,QAAQ,MAAM;AAAA,YACvC,iBAAiB;AAAA,YACjB,gBAAgB;AAAA,YAChB,gBAAgB,EAAE,cAAc,CAAC,KAAK,EAAE;AAAA,YACxC,oBAAoB;AAAA,YACpB,eAAe,CAAC,IAAI;AAAA,YACpB,eAAe,CAAC;AAAA,UAClB;AAAA,QACF;AAAA,MACF,CAAC;AACD,UAAI,GAAG,OAAO,yBAAyB,SAAS,mCAA8B,SAAS;AAAA,IACzF;AAGA,oBAAgB,aAAa,iBAAiB,SAAS,IAAI;AAG3D,UAAM,gBAAgB,aAAa,iBAAiB,SAAS,IAAI;AACjE,qBAAiB,IAAI,eAAe,aAAa;AAGjD,YAAQ,IAAI,YAAY,OAAO,KAAK;AAGpC,QAAI,kBAAkB,cAAc;AAClC,UAAI;AACF,uBAAe;AAAA,UACb;AAAA,YACE,cAAc,OAAO,MAAM,gBAAgB;AAAA,YAC3C,kBAAkB,OAAO,MAAM,oBAAoB;AAAA,YACnD,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,YACjD,SAAS,OAAO,MAAM;AAAA,UACxB;AAAA,UACA,IAAI;AAAA,QACN;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,UAAM,SAAS,aAAa,eAAe,SAAS,IAAI;AACxD,oBAAgB,IAAI,cAAc,MAAM;AAGxC,UAAM,SAAS,iBAAiB,OAAO,KAAK,SAAS,IAAI;AACzD,QAAI,QAAQ;AACV,mBAAa,IAAI,WAAW,MAAM;AAClC,kBAAY,IAAI,UAAU,OAAO,KAAK,OAAO;AAAA,IAC/C;AAGA,QAAI,OAAO,WAAW,YAAY;AAChC,sBAAgB,IAAI;AAAA,QAClB,OAAO;AAAA,QACP,CAAC,cAAc;AACb,mBAAS;AACT,gBAAM,eAAe,UAAU,QAAQ,MAAM,cAAc;AAC3D,kBAAI,4BAAW,YAAY,GAAG;AAC5B,2BAAe,IAAI,iBAAiB,YAAY;AAAA,UAClD;AACA,gBAAM,eAAe,aAAa,iBAAiB,SAAS,IAAI;AAChE,2BAAiB,IAAI,eAAe,YAAY;AAEhD,gBAAM,YAAY,iBAAiB,UAAU,KAAK,SAAS,IAAI;AAC/D,cAAI,WAAW;AACb,yBAAa,IAAI,WAAW,SAAS;AACrC,wBAAY,IAAI,UAAU,UAAU,KAAK,OAAO;AAAA,UAClD,OAAO;AACL,yBAAa;AACb,wBAAY;AAAA,UACd;AACA,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,OAAO;AAAA,YACP,QAAQ,SAAS;AAAA,YACjB,MAAM,SAAS;AAAA,YACf,SAAS,SAAS;AAAA,YAClB,UAAU,EAAE,QAAQ,OAAO,OAAO;AAAA,UACpC,CAAC;AACD,cAAI,GAAG,OAAO,8BAA8B,MAAM;AAAA,QACpD;AAAA,QACA,CAAC,UAAU;AACT,cAAI,GAAG,OAAO,yBAAyB,MAAM,OAAO,IAAI,SAAS;AAAA,QACnE;AAAA,MACF;AACA,oBAAc,MAAM;AAAA,IACtB;AAGA,UAAM,MAAM,IAAI;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP,QAAQ,SAAS;AAAA,MACjB,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,UAAU,EAAE,QAAQ,OAAO,QAAQ,cAAc;AAAA,IACnD,CAAC;AAGD,QAAI,GAAG,UAAU,cAAc,eAAe,SAAS,IAAI,KAAK,aAAa,GAAG;AAChF,QAAI,GAAG;AAAA,MACL,kCAA6B,SAAS,IAAI,YAAY,aAAa,WAAW,SAAS,OAAO;AAAA,MAC9F;AAAA,IACF;AAAA,EACF,CAAC;AAED,KAAG,GAAG,aAAa,OAAO,OAAO,SAAS;AACxC,UAAM,EAAE,UAAU,MAAM,IAAI;AAC5B,UAAM,SAAS,gBAAgB,UAAU,KAAK;AAE9C,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAGA,QAAI,kBAAkB,WAAW;AAC/B,YAAM;AACN,YAAM,MAAM,IAAI;AAAA,QACd,GAAG;AAAA,QACH,OAAO;AAAA,QACP,UAAU;AAAA,QACV,QAAQ;AAAA,MACV,CAAC;AACD,aAAO,EAAE,OAAO,MAAM,QAAQ,uDAAuD;AAAA,IACvF;AAGA,QAAI,CAAC,cAAc,QAAQ,GAAG;AAC5B,YAAM;AACN,YAAM,MAAM,IAAI;AAAA,QACd,GAAG;AAAA,QACH,OAAO;AAAA,QACP,UAAU;AAAA,QACV,QAAQ,qBAAqB,cAAc,KAAK,CAAC;AAAA,MACnD,CAAC;AACD,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ,qCAAqC,cAAc,KAAK,CAAC;AAAA,MACnE;AAAA,IACF;AAGA,UAAM,eAAe,aAAa,aAAa,SAAS,MAAM,QAAQ;AACtE,QAAI,iBAAiB,QAAQ;AAC3B,YAAM;AACN,YAAM,MAAM,IAAI;AAAA,QACd,GAAG;AAAA,QACH,OAAO;AAAA,QACP,UAAU;AAAA,QACV,QAAQ;AAAA,MACV,CAAC;AACD,aAAO,EAAE,OAAO,MAAM,QAAQ,iBAAiB,SAAS,IAAI,eAAe,QAAQ,GAAG;AAAA,IACxF;AAGA,QAAI,aAAa,QAAQ;AACvB,YAAM,UAAU,OAAO,MAAM,SAAS,MAAM,WAAW,MAAM,SAAS,IAAI;AAC1E,YAAM,iBAAiB,eAAe,SAAS,OAAO;AAEtD,UAAI,mBAAmB,aAAa;AAClC,cAAM;AACN,cAAM,MAAM,IAAI;AAAA,UACd,GAAG;AAAA,UACH,OAAO;AAAA,UACP,UAAU;AAAA,UACV,QAAQ;AAAA,QACV,CAAC;AACD,eAAO,EAAE,OAAO,MAAM,QAAQ,mCAAmC,QAAQ,MAAM,GAAG,EAAE,CAAC,GAAG;AAAA,MAC1F;AAGA,UACE,mBAAmB,kBACnB,aAAa,iBAAiB,SAAS,MAAM,MAAM,GACnD;AACA,YAAI,cAAc;AAChB,gBAAM;AACN,gBAAM,MAAM,IAAI,EAAE,GAAG,YAAY,OAAO,qBAAqB,CAAC;AAE9D,gBAAM,SAAS,MAAM,aAAa;AAAA,YAChC,EAAE,UAAU,MAAM;AAAA,YAClB,EAAE,QAAQ,SAAS,QAAQ,MAAM,SAAS,MAAM,SAAS,SAAS,QAAQ;AAAA,UAC5E;AAEA,cAAI,OAAO,UAAU;AACnB,kBAAM,MAAM,IAAI;AAAA,cACd,GAAG;AAAA,cACH,OAAO;AAAA,cACP,UAAU,OAAO;AAAA,YACnB,CAAC;AAAA,UACH,OAAO;AACL,kBAAM;AACN,kBAAM,MAAM,IAAI;AAAA,cACd,GAAG;AAAA,cACH,OAAO;AAAA,cACP,QAAQ,OAAO;AAAA,cACf,UAAU,OAAO;AAAA,YACnB,CAAC;AACD,mBAAO,EAAE,OAAO,MAAM,QAAQ,OAAO,UAAU,kBAAkB;AAAA,UACnE;AAAA,QACF,OAAO;AAEL,gBAAM;AACN,gBAAM,MAAM,IAAI;AAAA,YACd,GAAG;AAAA,YACH,OAAO;AAAA,YACP,UAAU;AAAA,YACV,QAAQ;AAAA,UACV,CAAC;AACD,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,OAAO,YAAY,UAAU,KAAK;AACxC,QAAI,MAAM;AACR,YAAM,YAAY,YAAY,IAAI,QAAQ,IAAI,UAAU;AACxD,YAAM,eAAe,aAAa;AAAA,QAChC,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA,UAAI,iBAAiB,QAAQ;AAC3B,cAAM;AACN,cAAM,MAAM,IAAI;AAAA,UACd,GAAG;AAAA,UACH,OAAO;AAAA,UACP,UAAU;AAAA,UACV,QAAQ,gBAAgB,IAAI;AAAA,QAC9B,CAAC;AACD,eAAO,EAAE,OAAO,MAAM,QAAQ,0BAA0B,IAAI,GAAG;AAAA,MACjE;AAAA,IACF;AAGA,QAAI,cAAc,WAAW;AAC3B,YAAM,SAAS,iBAAiB,UAAU,KAAK;AAC/C,YAAM,aAAyB,CAAC;AAChC,iBAAW,CAAC,EAAE,UAAU,KAAK,QAAQ;AACnC,cAAM,SAAS,WAAW,KAAK,UAAU;AACzC,mBAAW,KAAK,GAAG,OAAO,OAAO;AAAA,MACnC;AAEA,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,SAAS,qBAAqB,YAAY,YAAY,OAAO;AACnE,cAAM,eAAe,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACtE,cAAM,aAAa,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACjE,cAAM,UAAU;AAAA,UACd,UAAU;AAAA,UACV;AAAA,UACA,WAAW;AAAA,UACX,OAAO,WAAW;AAAA,QACpB;AAEA,YAAI,WAAW,SAAS;AACtB,gBAAM;AACN,gBAAM,MAAM,IAAI;AAAA,YACd,GAAG;AAAA,YACH,OAAO;AAAA,YACP,UAAU;AAAA,YACV,QAAQ,QAAQ,aAAa,KAAK,IAAI,CAAC;AAAA,YACvC,UAAU;AAAA,UACZ,CAAC;AACD,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ,yCAAyC,aAAa,KAAK,IAAI,CAAC;AAAA,UAC1E;AAAA,QACF;AAEA,YAAI,WAAW,QAAQ;AACrB,gBAAM;AAEN,qBAAW,CAAC,UAAU,UAAU,KAAK,QAAQ;AAC3C,kBAAM,cAAc,WAAW,KAAK,UAAU;AAC9C,gBAAI,YAAY,YAAY;AAC1B,cAAC,MAAkC,QAAQ,IAAI,UAAU;AAAA,gBACvD;AAAA,gBACA,YAAY;AAAA,cACd;AAAA,YACF;AAAA,UACF;AACA,gBAAM,MAAM,IAAI;AAAA,YACd,GAAG;AAAA,YACH,OAAO;AAAA,YACP,UAAU,EAAE,GAAG,SAAS,UAAU,UAAU,QAAQ,EAAE,SAAS;AAAA,UACjE,CAAC;AAAA,QACH,OAAO;AAEL,gBAAM;AACN,gBAAM,MAAM,IAAI;AAAA,YACd,GAAG;AAAA,YACH,OAAO;AAAA,YACP,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,QAAI,aAAa,UAAU,aAAa,iBAAiB,SAAS,MAAM,QAAQ,GAAG;AACjF,UAAI,cAAc;AAChB,cAAM;AACN,cAAM,MAAM,IAAI,EAAE,GAAG,YAAY,OAAO,qBAAqB,CAAC;AAE9D,cAAM,SAAS,MAAM,aAAa;AAAA,UAChC,EAAE,UAAU,MAAM;AAAA,UAClB,EAAE,QAAQ,SAAS,QAAQ,MAAM,SAAS,MAAM,SAAS,SAAS,QAAQ;AAAA,QAC5E;AAEA,YAAI,OAAO,UAAU;AACnB,gBAAM,MAAM,IAAI,EAAE,GAAG,YAAY,OAAO,oBAAoB,UAAU,OAAO,SAAS,CAAC;AAAA,QACzF,OAAO;AACL,gBAAM;AACN,gBAAM,MAAM,IAAI;AAAA,YACd,GAAG;AAAA,YACH,OAAO;AAAA,YACP,QAAQ,OAAO;AAAA,YACf,UAAU,OAAO;AAAA,UACnB,CAAC;AACD,iBAAO,EAAE,OAAO,MAAM,QAAQ,OAAO,UAAU,kBAAkB;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AAGA,UAAM;AACN,UAAM,MAAM,IAAI,EAAE,GAAG,YAAY,OAAO,gBAAgB,UAAU,UAAU,CAAC;AAC7E,WAAO;AAAA,EACT,CAAC;AAED,KAAG,GAAG,eAAe,OAAO,OAAO,SAAS;AAE1C,QAAI,cAAc,aAAa,MAAM,QAAQ;AAC3C,YAAM,SAAS,WAAW,KAAK,MAAM,MAAM;AAC3C,UAAI,OAAO,YAAY;AACrB,cAAM,SAAS,qBAAqB,YAAY,OAAO,SAAS,QAAQ;AACxE,cAAM,eAAe,CAAC,GAAG,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC1E,cAAM,aAAa,CAAC,GAAG,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACrE,cAAM,UAAU;AAAA,UACd,UAAU;AAAA,UACV;AAAA,UACA,WAAW;AAAA,UACX,OAAO,OAAO,QAAQ;AAAA,QACxB;AAEA,YAAI,WAAW,UAAU,WAAW,SAAS;AAE3C,gBAAM;AACN,gBAAM,SAAS,UAAU,SAAS,MAAM,QAAQ,OAAO,OAAO;AAC9D,gBAAM,MAAM,IAAI;AAAA,YACd;AAAA,YACA,OAAO;AAAA,YACP,QAAQ,SAAS;AAAA,YACjB,MAAM,SAAS;AAAA,YACf,SAAS,SAAS;AAAA,YAClB,MAAM,MAAM;AAAA,YACZ,UAAU,EAAE,GAAG,SAAS,UAAU,UAAU,QAAQ,EAAE,SAAS;AAAA,UACjE,CAAC;AAAA,QACH,OAAO;AACL,gBAAM;AACN,gBAAM,MAAM,IAAI;AAAA,YACd;AAAA,YACA,OAAO;AAAA,YACP,QAAQ,SAAS;AAAA,YACjB,MAAM,SAAS;AAAA,YACf,SAAS,SAAS;AAAA,YAClB,MAAM,MAAM;AAAA,YACZ,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,UAAM,MAAM,IAAI;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP,QAAQ,SAAS;AAAA,MACjB,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,MAAM,MAAM;AAAA,MACZ,OAAO,gBAAgB,MAAM,UAAU,MAAM,KAAK;AAAA,MAClD,UAAU,EAAE,SAAS,MAAM,QAAQ;AAAA,IACrC,CAAC;AAAA,EACH,CAAC;AAED,KAAG,GAAG,oBAAoB,OAAO,QAAQ,SAAS;AAChD,mBAAe,KAAK;AACpB,UAAM,MAAM,IAAI;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP,QAAQ,SAAS;AAAA,MACjB,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,UAAU;AAAA,QACR,OAAO,EAAE,GAAG,MAAM;AAAA,QAClB,QAAQ,EAAE,MAAM,cAAc,KAAK,GAAG,WAAW,cAAc,UAAU,EAAE;AAAA,QAC3E,SAAS,OAAO,YAAY,MAAM,WAAW,CAAC;AAAA,MAChD;AAAA,IACF,CAAC;AACD,UAAM,MAAM,MAAM;AAAA,EACpB,CAAC;AAED,KAAG,gBAAgB,cAAc;AAAA,IAC/B,aAAa;AAAA,IACb,SAAS,OAAO,MAAM,QAAQ;AAC5B,YAAM,aAAa,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,CAAC,KAAK;AAElD,UAAI,eAAe,UAAU;AAC3B,cAAM,UAAU,MAAM,WAAW;AACjC,cAAM,aAAa,cAAc,YAAY,IACzC,cACA,GAAG,cAAc,KAAK,CAAC,MAAM,cAAc,KAAK,IAAI,cAAc,UAAU,CAAC,KAAK,cAAc,UAAU,CAAC;AAC/G,cAAM,QAAQ;AAAA,UACZ,SAAS,SAAS,IAAI;AAAA,UACtB,aAAa,SAAS,OAAO;AAAA,UAC7B,SAAS,aAAa;AAAA,UACtB,YAAY,SAAS;AAAA,UACrB,WAAW,UAAU;AAAA,UACrB;AAAA,UACA;AAAA,UACA,cAAc,MAAM,OAAO;AAAA,UAC3B,aAAa,MAAM,MAAM;AAAA,UACzB,gBAAgB,MAAM,SAAS;AAAA,UAC/B,qBAAqB,MAAM,MAAM;AAAA,UACjC,sBAAsB,MAAM,cAAc;AAAA,UAC1C,kBAAkB,MAAM,UAAU;AAAA,UAClC,mBAAmB,MAAM,WAAW;AAAA,UACpC,iBAAiB,MAAM,SAAS;AAAA,UAChC;AAAA,UACA;AAAA,UACA,GAAG,CAAC,GAAG,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE;AAAA,QAC1D;AACA,YAAI,GAAG,OAAO,MAAM,KAAK,IAAI,GAAG,MAAM;AAAA,MACxC,OAAO;AACL,YAAI,GAAG,OAAO,6BAA6B,MAAM;AAAA,MACnD;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAO,qBAAQ;","names":["import_node_fs","parseYaml","import_fs","import_yaml","parseYaml","import_fs","import_yaml","parseYaml","import_yaml","import_value","parseYaml","import_node_crypto"]}
|