@grwnd/pi-governance 3.0.0 → 3.0.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/config/defaults.ts","../../src/lib/wizard/html.ts","../../src/lib/wizard/server.ts","../../src/lib/wizard/index.ts","../../src/extensions/index.ts","../../src/lib/config/loader.ts","../../src/lib/config/schema.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":["import type { GovernanceConfig } from './schema.js';\n\nexport const DEFAULTS: GovernanceConfig = {\n auth: {\n provider: 'env',\n env: {\n user_var: 'PI_GOV_USER',\n role_var: 'PI_GOV_ROLE',\n org_unit_var: 'PI_GOV_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: true,\n mode: 'audit',\n on_input: 'block',\n on_output: 'mask',\n masking: {\n strategy: 'partial',\n show_chars: 4,\n placeholder: '***',\n },\n severity_threshold: 'low',\n built_in: {\n secrets: true,\n pii: true,\n },\n },\n};\n","export const WIZARD_HTML: string = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Pi Governance — Setup Wizard</title>\n<style>\n :root {\n --bg: #f8f9fa;\n --bg-surface: #ffffff;\n --bg-surface-alt: #f1f3f5;\n --bg-code: #e9ecef;\n --text: #212529;\n --text-muted: #6c757d;\n --text-inverse: #ffffff;\n --border: #dee2e6;\n --border-focus: #4263eb;\n --primary: #4263eb;\n --primary-hover: #3b5bdb;\n --primary-subtle: #dbe4ff;\n --success: #2f9e44;\n --success-subtle: #d3f9d8;\n --danger: #e03131;\n --danger-subtle: #ffe3e3;\n --warning: #f08c00;\n --warning-subtle: #fff3bf;\n --radius: 8px;\n --radius-sm: 4px;\n --shadow: 0 1px 3px rgba(0,0,0,0.08);\n --shadow-lg: 0 4px 12px rgba(0,0,0,0.1);\n --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;\n --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;\n --transition: 150ms ease;\n }\n\n @media (prefers-color-scheme: dark) {\n :root {\n --bg: #1a1b1e;\n --bg-surface: #25262b;\n --bg-surface-alt: #2c2e33;\n --bg-code: #2c2e33;\n --text: #c1c2c5;\n --text-muted: #909296;\n --text-inverse: #1a1b1e;\n --border: #373a40;\n --border-focus: #5c7cfa;\n --primary: #5c7cfa;\n --primary-hover: #748ffc;\n --primary-subtle: #1b2559;\n --success: #51cf66;\n --success-subtle: #0b3d1a;\n --danger: #ff6b6b;\n --danger-subtle: #3d0b0b;\n --warning: #fcc419;\n --warning-subtle: #3d2e00;\n --shadow: 0 1px 3px rgba(0,0,0,0.3);\n --shadow-lg: 0 4px 12px rgba(0,0,0,0.4);\n }\n }\n\n * { margin: 0; padding: 0; box-sizing: border-box; }\n\n body {\n font-family: var(--font-sans);\n background: var(--bg);\n color: var(--text);\n line-height: 1.6;\n min-height: 100vh;\n }\n\n .layout {\n display: grid;\n grid-template-columns: 1fr 420px;\n gap: 0;\n min-height: 100vh;\n }\n\n @media (max-width: 1024px) {\n .layout { grid-template-columns: 1fr; }\n .preview-panel { display: none; }\n }\n\n /* --- Left column: Form --- */\n .form-column {\n padding: 32px 40px 80px;\n overflow-y: auto;\n max-height: 100vh;\n }\n\n .logo {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n }\n\n .logo-icon {\n width: 36px; height: 36px;\n background: var(--primary);\n border-radius: var(--radius);\n display: flex; align-items: center; justify-content: center;\n color: var(--text-inverse);\n font-weight: 700; font-size: 18px;\n }\n\n .logo-text {\n font-size: 20px;\n font-weight: 700;\n color: var(--text);\n }\n\n .logo-text span { color: var(--text-muted); font-weight: 400; }\n\n h1 {\n font-size: 28px;\n font-weight: 700;\n margin: 24px 0 8px;\n }\n\n .subtitle {\n color: var(--text-muted);\n font-size: 15px;\n margin-bottom: 32px;\n }\n\n /* Sections */\n .section {\n background: var(--bg-surface);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 24px;\n margin-bottom: 20px;\n box-shadow: var(--shadow);\n }\n\n .section-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 16px;\n cursor: pointer;\n user-select: none;\n }\n\n .section-header h2 {\n font-size: 16px;\n font-weight: 600;\n flex: 1;\n }\n\n .section-badge {\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .badge-required { background: var(--danger-subtle); color: var(--danger); }\n .badge-optional { background: var(--primary-subtle); color: var(--primary); }\n\n .section-icon {\n width: 32px; height: 32px;\n border-radius: var(--radius-sm);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px;\n flex-shrink: 0;\n }\n\n .section-body { display: block; }\n .section.collapsed .section-body { display: none; }\n .section-chevron {\n transition: transform var(--transition);\n color: var(--text-muted);\n font-size: 12px;\n }\n .section.collapsed .section-chevron { transform: rotate(-90deg); }\n\n /* Form elements */\n label {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n margin-bottom: 4px;\n }\n\n .label-hint {\n font-weight: 400;\n color: var(--text-muted);\n font-size: 12px;\n }\n\n input[type=\"text\"],\n input[type=\"number\"],\n select {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--border);\n border-radius: var(--radius-sm);\n background: var(--bg-surface);\n color: var(--text);\n font-size: 14px;\n font-family: var(--font-sans);\n transition: border-color var(--transition);\n outline: none;\n }\n\n input:focus, select:focus {\n border-color: var(--border-focus);\n box-shadow: 0 0 0 2px var(--primary-subtle);\n }\n\n .field { margin-bottom: 16px; }\n\n .field-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n }\n\n .field-row-3 {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 12px;\n }\n\n /* Toggle switch */\n .toggle-row {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 12px;\n }\n\n .toggle {\n position: relative;\n width: 40px; height: 22px;\n flex-shrink: 0;\n }\n\n .toggle input { display: none; }\n\n .toggle-slider {\n position: absolute;\n inset: 0;\n background: var(--border);\n border-radius: 11px;\n cursor: pointer;\n transition: background var(--transition);\n }\n\n .toggle-slider::before {\n content: '';\n position: absolute;\n width: 16px; height: 16px;\n left: 3px; top: 3px;\n background: white;\n border-radius: 50%;\n transition: transform var(--transition);\n }\n\n .toggle input:checked + .toggle-slider {\n background: var(--primary);\n }\n\n .toggle input:checked + .toggle-slider::before {\n transform: translateX(18px);\n }\n\n .toggle-label {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* Role cards */\n .role-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n }\n\n .role-card {\n border: 2px solid var(--border);\n border-radius: var(--radius);\n padding: 16px;\n cursor: pointer;\n transition: all var(--transition);\n position: relative;\n }\n\n .role-card:hover { border-color: var(--primary); }\n\n .role-card.selected {\n border-color: var(--primary);\n background: var(--primary-subtle);\n }\n\n .role-card-check {\n position: absolute;\n top: 12px; right: 12px;\n width: 20px; height: 20px;\n border: 2px solid var(--border);\n border-radius: 4px;\n display: flex; align-items: center; justify-content: center;\n font-size: 12px;\n color: transparent;\n transition: all var(--transition);\n }\n\n .role-card.selected .role-card-check {\n background: var(--primary);\n border-color: var(--primary);\n color: white;\n }\n\n .role-name {\n font-weight: 600;\n font-size: 14px;\n margin-bottom: 4px;\n }\n\n .role-desc {\n font-size: 12px;\n color: var(--text-muted);\n margin-bottom: 8px;\n }\n\n .role-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n\n .role-tag {\n font-size: 11px;\n padding: 1px 6px;\n border-radius: 3px;\n background: var(--bg-surface-alt);\n color: var(--text-muted);\n font-family: var(--font-mono);\n }\n\n .role-details {\n display: none;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--border);\n }\n\n .role-card.selected .role-details { display: block; }\n\n /* Chip selector */\n .chip-group {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-bottom: 12px;\n }\n\n .chip {\n padding: 5px 14px;\n border: 1px solid var(--border);\n border-radius: 16px;\n font-size: 13px;\n cursor: pointer;\n transition: all var(--transition);\n background: var(--bg-surface);\n color: var(--text);\n }\n\n .chip:hover { border-color: var(--primary); }\n\n .chip.active {\n background: var(--primary);\n border-color: var(--primary);\n color: var(--text-inverse);\n }\n\n /* Pattern list */\n .pattern-list { margin-top: 12px; }\n\n .pattern-item {\n display: grid;\n grid-template-columns: 1fr 1.5fr auto auto;\n gap: 8px;\n align-items: center;\n margin-bottom: 8px;\n }\n\n .pattern-item input, .pattern-item select {\n font-size: 13px;\n padding: 6px 8px;\n }\n\n .btn-remove {\n background: none;\n border: none;\n color: var(--danger);\n cursor: pointer;\n font-size: 18px;\n padding: 4px;\n line-height: 1;\n }\n\n .btn-add {\n background: none;\n border: 1px dashed var(--border);\n border-radius: var(--radius-sm);\n padding: 6px 14px;\n color: var(--primary);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n transition: all var(--transition);\n }\n\n .btn-add:hover {\n border-color: var(--primary);\n background: var(--primary-subtle);\n }\n\n /* Allowlist */\n .allowlist-item {\n display: flex;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .allowlist-item input { flex: 1; font-size: 13px; padding: 6px 8px; }\n\n /* Sink list */\n .sink-item {\n background: var(--bg-surface-alt);\n border-radius: var(--radius-sm);\n padding: 12px;\n margin-bottom: 8px;\n position: relative;\n }\n\n .sink-item .btn-remove {\n position: absolute;\n top: 8px; right: 8px;\n }\n\n /* --- Right column: Preview --- */\n .preview-panel {\n background: var(--bg-surface-alt);\n border-left: 1px solid var(--border);\n padding: 24px;\n display: flex;\n flex-direction: column;\n position: sticky;\n top: 0;\n height: 100vh;\n overflow: hidden;\n }\n\n .preview-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n flex-shrink: 0;\n }\n\n .preview-header h3 {\n font-size: 14px;\n font-weight: 600;\n }\n\n .preview-tabs {\n display: flex;\n gap: 4px;\n margin-bottom: 12px;\n flex-shrink: 0;\n }\n\n .preview-tab {\n padding: 4px 12px;\n font-size: 12px;\n border: 1px solid var(--border);\n border-radius: var(--radius-sm);\n background: var(--bg-surface);\n cursor: pointer;\n color: var(--text-muted);\n transition: all var(--transition);\n }\n\n .preview-tab.active {\n background: var(--primary);\n border-color: var(--primary);\n color: var(--text-inverse);\n }\n\n .preview-content {\n flex: 1;\n overflow-y: auto;\n background: var(--bg-surface);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 16px;\n }\n\n .preview-content pre {\n font-family: var(--font-mono);\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n color: var(--text);\n margin: 0;\n }\n\n /* Bottom bar */\n .bottom-bar {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 420px;\n padding: 16px 40px;\n background: var(--bg-surface);\n border-top: 1px solid var(--border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n z-index: 100;\n box-shadow: 0 -2px 8px rgba(0,0,0,0.06);\n }\n\n @media (max-width: 1024px) {\n .bottom-bar { right: 0; }\n }\n\n .btn-primary {\n padding: 10px 28px;\n background: var(--primary);\n color: var(--text-inverse);\n border: none;\n border-radius: var(--radius);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: background var(--transition);\n }\n\n .btn-primary:hover { background: var(--primary-hover); }\n .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }\n\n .btn-secondary {\n padding: 10px 20px;\n background: var(--bg-surface);\n color: var(--text);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all var(--transition);\n }\n\n .btn-secondary:hover { border-color: var(--primary); color: var(--primary); }\n\n .save-status {\n font-size: 13px;\n color: var(--text-muted);\n }\n\n .save-status.success { color: var(--success); }\n .save-status.error { color: var(--danger); }\n\n /* Toast */\n .toast {\n position: fixed;\n top: 20px;\n right: 20px;\n padding: 12px 20px;\n border-radius: var(--radius);\n font-size: 14px;\n font-weight: 500;\n z-index: 1000;\n box-shadow: var(--shadow-lg);\n transform: translateY(-10px);\n opacity: 0;\n transition: all 300ms ease;\n pointer-events: none;\n }\n\n .toast.visible { transform: translateY(0); opacity: 1; pointer-events: auto; }\n .toast.success { background: var(--success); color: white; }\n .toast.error { background: var(--danger); color: white; }\n\n /* Helpers */\n .help-text {\n font-size: 12px;\n color: var(--text-muted);\n margin-top: 4px;\n }\n\n .divider {\n border: none;\n border-top: 1px solid var(--border);\n margin: 16px 0;\n }\n\n .hidden { display: none !important; }\n</style>\n</head>\n<body>\n<div class=\"layout\">\n <!-- ═══════════ LEFT: FORM ═══════════ -->\n <div class=\"form-column\">\n <div class=\"logo\">\n <div class=\"logo-icon\">G</div>\n <div class=\"logo-text\">Pi Governance <span>Setup Wizard</span></div>\n </div>\n\n <h1>Configure your governance policy</h1>\n <p class=\"subtitle\">\n AI coding agents are powerful but need guardrails. This wizard generates a\n <code>governance.yaml</code> and <code>governance-rules.yaml</code> to control\n tool access, bash safety, data-loss prevention, human approvals, and audit logging.\n </p>\n\n <!-- ── 1. Roles ── -->\n <div class=\"section\" id=\"sec-roles\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-roles')\">\n <div class=\"section-icon\" style=\"background:var(--primary-subtle);color:var(--primary)\">&#x1f465;</div>\n <h2>Roles</h2>\n <span class=\"section-badge badge-required\">Required</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <p class=\"help-text\" style=\"margin-bottom:12px\">Select the roles your team needs. Each role defines tool access, execution mode, and approval rules.</p>\n <div class=\"role-grid\" id=\"role-grid\"></div>\n </div>\n </div>\n\n <!-- ── 2. DLP ── -->\n <div class=\"section\" id=\"sec-dlp\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-dlp')\">\n <div class=\"section-icon\" style=\"background:var(--warning-subtle);color:var(--warning)\">&#x1f6e1;</div>\n <h2>Data Loss Prevention</h2>\n <span class=\"section-badge badge-optional\">Optional</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <div class=\"toggle-row\">\n <label class=\"toggle\"><input type=\"checkbox\" id=\"dlp-enabled\" checked onchange=\"updatePreview()\"><span class=\"toggle-slider\"></span></label>\n <span class=\"toggle-label\">Enable DLP scanning</span>\n </div>\n\n <div id=\"dlp-options\">\n <div class=\"field\">\n <label>Default Mode</label>\n <div class=\"chip-group\" id=\"dlp-mode\">\n <span class=\"chip active\" data-value=\"audit\" onclick=\"selectChip(this)\">Audit</span>\n <span class=\"chip\" data-value=\"mask\" onclick=\"selectChip(this)\">Mask</span>\n <span class=\"chip\" data-value=\"block\" onclick=\"selectChip(this)\">Block</span>\n </div>\n </div>\n\n <div class=\"field-row\">\n <div class=\"field\">\n <label>On Input <span class=\"label-hint\">(agent receives)</span></label>\n <select id=\"dlp-on-input\" onchange=\"updatePreview()\">\n <option value=\"\">Use default mode</option>\n <option value=\"audit\">Audit</option>\n <option value=\"mask\">Mask</option>\n <option value=\"block\" selected>Block</option>\n </select>\n </div>\n <div class=\"field\">\n <label>On Output <span class=\"label-hint\">(agent produces)</span></label>\n <select id=\"dlp-on-output\" onchange=\"updatePreview()\">\n <option value=\"\">Use default mode</option>\n <option value=\"audit\">Audit</option>\n <option value=\"mask\" selected>Mask</option>\n <option value=\"block\">Block</option>\n </select>\n </div>\n </div>\n\n <hr class=\"divider\">\n <label>Built-in Patterns</label>\n <div class=\"toggle-row\" style=\"margin-top:6px\">\n <label class=\"toggle\"><input type=\"checkbox\" id=\"dlp-secrets\" checked onchange=\"updatePreview()\"><span class=\"toggle-slider\"></span></label>\n <span class=\"toggle-label\">Secrets <span class=\"label-hint\">(API keys, tokens, passwords)</span></span>\n </div>\n <div class=\"toggle-row\">\n <label class=\"toggle\"><input type=\"checkbox\" id=\"dlp-pii\" checked onchange=\"updatePreview()\"><span class=\"toggle-slider\"></span></label>\n <span class=\"toggle-label\">PII <span class=\"label-hint\">(emails, phone numbers, SSNs)</span></span>\n </div>\n\n <hr class=\"divider\">\n <label>Masking Options</label>\n <div class=\"field-row-3\" style=\"margin-top:8px\">\n <div class=\"field\">\n <label>Strategy</label>\n <select id=\"dlp-mask-strategy\" onchange=\"updatePreview()\">\n <option value=\"partial\" selected>Partial</option>\n <option value=\"full\">Full</option>\n <option value=\"hash\">Hash</option>\n </select>\n </div>\n <div class=\"field\">\n <label>Show Chars</label>\n <input type=\"number\" id=\"dlp-mask-show\" value=\"4\" min=\"0\" onchange=\"updatePreview()\">\n </div>\n <div class=\"field\">\n <label>Placeholder</label>\n <input type=\"text\" id=\"dlp-mask-placeholder\" value=\"***\" onchange=\"updatePreview()\">\n </div>\n </div>\n\n <hr class=\"divider\">\n <label>Severity Threshold <span class=\"label-hint\">(minimum severity to trigger DLP)</span></label>\n <div class=\"chip-group\" id=\"dlp-severity\" style=\"margin-top:6px\">\n <span class=\"chip active\" data-value=\"low\" onclick=\"selectChip(this)\">Low</span>\n <span class=\"chip\" data-value=\"medium\" onclick=\"selectChip(this)\">Medium</span>\n <span class=\"chip\" data-value=\"high\" onclick=\"selectChip(this)\">High</span>\n <span class=\"chip\" data-value=\"critical\" onclick=\"selectChip(this)\">Critical</span>\n </div>\n\n <hr class=\"divider\">\n <label>Custom Patterns</label>\n <div class=\"pattern-list\" id=\"dlp-custom-patterns\"></div>\n <button class=\"btn-add\" onclick=\"addCustomPattern()\">+ Add pattern</button>\n\n <hr class=\"divider\">\n <label>Allowlist <span class=\"label-hint\">(patterns to ignore)</span></label>\n <div id=\"dlp-allowlist\"></div>\n <button class=\"btn-add\" onclick=\"addAllowlistEntry()\" style=\"margin-top:8px\">+ Add entry</button>\n </div>\n </div>\n </div>\n\n <!-- ── 3. Bash Classification ── -->\n <div class=\"section\" id=\"sec-bash\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-bash')\">\n <div class=\"section-icon\" style=\"background:var(--danger-subtle);color:var(--danger)\">&#x1f4bb;</div>\n <h2>Bash Classification</h2>\n <span class=\"section-badge badge-optional\">Optional</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <p class=\"help-text\" style=\"margin-bottom:12px\">The built-in bash classifier categorizes commands by danger level. Adjust the threshold for auto-blocking.</p>\n <div class=\"field\">\n <label>Auto-block Severity</label>\n <p class=\"help-text\">Commands at or above this severity are blocked without HITL.</p>\n <div class=\"chip-group\" id=\"bash-severity\" style=\"margin-top:6px\">\n <span class=\"chip\" data-value=\"low\" onclick=\"selectChip(this)\">Low</span>\n <span class=\"chip\" data-value=\"medium\" onclick=\"selectChip(this)\">Medium</span>\n <span class=\"chip active\" data-value=\"high\" onclick=\"selectChip(this)\">High</span>\n <span class=\"chip\" data-value=\"critical\" onclick=\"selectChip(this)\">Critical</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- ── 4. HITL ── -->\n <div class=\"section\" id=\"sec-hitl\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-hitl')\">\n <div class=\"section-icon\" style=\"background:var(--success-subtle);color:var(--success)\">&#x1f9d1;</div>\n <h2>Human-in-the-Loop</h2>\n <span class=\"section-badge badge-required\">Required</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <div class=\"field\">\n <label>Default Execution Mode</label>\n <div class=\"chip-group\" id=\"hitl-mode\">\n <span class=\"chip\" data-value=\"autonomous\" onclick=\"selectChip(this)\">Autonomous</span>\n <span class=\"chip active\" data-value=\"supervised\" onclick=\"selectChip(this)\">Supervised</span>\n <span class=\"chip\" data-value=\"dry_run\" onclick=\"selectChip(this)\">Dry Run</span>\n </div>\n </div>\n <div class=\"field-row\">\n <div class=\"field\">\n <label>Approval Channel</label>\n <select id=\"hitl-channel\" onchange=\"updatePreview()\">\n <option value=\"cli\" selected>CLI (terminal prompt)</option>\n <option value=\"webhook\">Webhook</option>\n </select>\n </div>\n <div class=\"field\">\n <label>Timeout <span class=\"label-hint\">(seconds)</span></label>\n <input type=\"number\" id=\"hitl-timeout\" value=\"300\" min=\"10\" max=\"3600\" onchange=\"updatePreview()\">\n </div>\n </div>\n <div class=\"field hidden\" id=\"hitl-webhook-field\">\n <label>Webhook URL</label>\n <input type=\"text\" id=\"hitl-webhook-url\" placeholder=\"https://...\" onchange=\"updatePreview()\">\n </div>\n </div>\n </div>\n\n <!-- ── 5. Audit ── -->\n <div class=\"section\" id=\"sec-audit\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-audit')\">\n <div class=\"section-icon\" style=\"background:var(--primary-subtle);color:var(--primary)\">&#x1f4dd;</div>\n <h2>Audit Logging</h2>\n <span class=\"section-badge badge-required\">Required</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <p class=\"help-text\" style=\"margin-bottom:12px\">All governance events are logged to one or more sinks.</p>\n <div id=\"audit-sinks\"></div>\n <button class=\"btn-add\" onclick=\"addAuditSink()\" style=\"margin-top:8px\">+ Add sink</button>\n </div>\n </div>\n\n <!-- ── 6. Auth ── -->\n <div class=\"section collapsed\" id=\"sec-auth\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-auth')\">\n <div class=\"section-icon\" style=\"background:var(--bg-surface-alt);color:var(--text-muted)\">&#x1f511;</div>\n <h2>Authentication</h2>\n <span class=\"section-badge badge-optional\">Optional</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <div class=\"field\">\n <label>Provider</label>\n <div class=\"chip-group\" id=\"auth-provider\">\n <span class=\"chip active\" data-value=\"env\" onclick=\"selectChip(this)\">Environment Vars</span>\n <span class=\"chip\" data-value=\"local\" onclick=\"selectChip(this)\">Local File</span>\n <span class=\"chip\" data-value=\"oidc\" onclick=\"selectChip(this)\">OIDC</span>\n </div>\n </div>\n <div id=\"auth-env-fields\">\n <div class=\"field-row-3\">\n <div class=\"field\">\n <label>User Var</label>\n <input type=\"text\" id=\"auth-user-var\" value=\"PI_GOV_USER\" onchange=\"updatePreview()\">\n </div>\n <div class=\"field\">\n <label>Role Var</label>\n <input type=\"text\" id=\"auth-role-var\" value=\"PI_GOV_ROLE\" onchange=\"updatePreview()\">\n </div>\n <div class=\"field\">\n <label>Org Unit Var</label>\n <input type=\"text\" id=\"auth-org-unit-var\" value=\"PI_GOV_ORG_UNIT\" onchange=\"updatePreview()\">\n </div>\n </div>\n </div>\n <div id=\"auth-local-fields\" class=\"hidden\">\n <div class=\"field\">\n <label>Users File</label>\n <input type=\"text\" id=\"auth-users-file\" value=\"./users.yaml\" onchange=\"updatePreview()\">\n </div>\n </div>\n </div>\n </div>\n\n <div style=\"height:80px\"></div>\n </div>\n\n <!-- ═══════════ RIGHT: PREVIEW ═══════════ -->\n <div class=\"preview-panel\">\n <div class=\"preview-header\">\n <h3>Live Preview</h3>\n </div>\n <div class=\"preview-tabs\">\n <span class=\"preview-tab active\" data-tab=\"governance\" onclick=\"switchTab(this)\">governance.yaml</span>\n <span class=\"preview-tab\" data-tab=\"rules\" onclick=\"switchTab(this)\">governance-rules.yaml</span>\n </div>\n <div class=\"preview-content\">\n <pre id=\"preview-yaml\"></pre>\n </div>\n </div>\n</div>\n\n<!-- ── Bottom bar ── -->\n<div class=\"bottom-bar\">\n <span class=\"save-status\" id=\"save-status\"></span>\n <div style=\"display:flex;gap:10px\">\n <button class=\"btn-secondary\" onclick=\"handleClose()\">Cancel</button>\n <button class=\"btn-primary\" id=\"btn-save\" onclick=\"handleSave()\">Save Configuration</button>\n </div>\n</div>\n\n<!-- Toast -->\n<div class=\"toast\" id=\"toast\"></div>\n\n<script>\n// ─── State ───────────────────────────────────────────────────────────\nconst PRESET_ROLES = {\n analyst: {\n label: 'Analyst',\n desc: 'Read-only access, every action requires approval.',\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: 100000,\n allowed_paths: ['{{project_path}}/**'],\n blocked_paths: ['**/secrets/**', '**/.env*']\n },\n project_lead: {\n label: 'Project Lead',\n desc: 'Full tools, bash & write need human approval.',\n allowed_tools: ['read','write','edit','bash','grep','find','ls'],\n blocked_tools: [],\n prompt_template: 'project-lead',\n execution_mode: 'supervised',\n human_approval: { required_for: ['bash','write'], auto_approve: ['read','edit','grep','find','ls'] },\n token_budget_daily: 500000,\n allowed_paths: ['{{project_path}}/**'],\n blocked_paths: ['**/secrets/**', '**/.env*'],\n bash_overrides: { additional_blocked: ['sudo','ssh','curl.*\\\\\\\\|.*sh'] }\n },\n admin: {\n label: 'Admin',\n desc: 'Full autonomous access, no approvals, unlimited budget.',\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 auditor: {\n label: 'Auditor',\n desc: 'Dry-run: all calls logged, nothing executed.',\n allowed_tools: ['read','grep','find','ls'],\n blocked_tools: ['write','edit','bash'],\n prompt_template: 'analyst',\n execution_mode: 'dry_run',\n human_approval: { required_for: ['all'] },\n token_budget_daily: 50000,\n allowed_paths: ['**'],\n blocked_paths: ['**/secrets/**']\n }\n};\n\nlet selectedRoles = { analyst: false, project_lead: true, admin: false, auditor: false };\nlet customPatterns = [];\nlet allowlistEntries = [];\nlet auditSinks = [{ type: 'jsonl', path: '~/.pi/agent/audit.jsonl' }];\nlet activePreviewTab = 'governance';\n\n// ─── Init ────────────────────────────────────────────────────────────\ndocument.addEventListener('DOMContentLoaded', async () => {\n renderRoles();\n renderAuditSinks();\n updatePreview();\n\n try {\n const [configRes, defaultsRes] = await Promise.all([\n fetch('/api/config').catch(() => null),\n fetch('/api/defaults').catch(() => null)\n ]);\n if (configRes && configRes.ok) {\n const cfg = await configRes.json();\n applyConfig(cfg);\n }\n if (defaultsRes && defaultsRes.ok) {\n const defs = await defaultsRes.json();\n if (!configRes || !configRes.ok) applyConfig(defs);\n }\n } catch (e) { /* use built-in defaults */ }\n\n // watch for webhook channel\n document.getElementById('hitl-channel').addEventListener('change', (e) => {\n document.getElementById('hitl-webhook-field').classList.toggle('hidden', e.target.value !== 'webhook');\n updatePreview();\n });\n\n // watch dlp toggle\n document.getElementById('dlp-enabled').addEventListener('change', (e) => {\n document.getElementById('dlp-options').classList.toggle('hidden', !e.target.checked);\n updatePreview();\n });\n});\n\n// ─── Apply Config ────────────────────────────────────────────────────\nfunction applyConfig(cfg) {\n if (!cfg) return;\n\n // Auth\n if (cfg.auth) {\n setChipValue('auth-provider', cfg.auth.provider || 'env');\n if (cfg.auth.env) {\n if (cfg.auth.env.user_var) document.getElementById('auth-user-var').value = cfg.auth.env.user_var;\n if (cfg.auth.env.role_var) document.getElementById('auth-role-var').value = cfg.auth.env.role_var;\n if (cfg.auth.env.org_unit_var) document.getElementById('auth-org-unit-var').value = cfg.auth.env.org_unit_var;\n }\n if (cfg.auth.local && cfg.auth.local.users_file) {\n document.getElementById('auth-users-file').value = cfg.auth.local.users_file;\n }\n }\n\n // HITL\n if (cfg.hitl) {\n if (cfg.hitl.default_mode) setChipValue('hitl-mode', cfg.hitl.default_mode);\n if (cfg.hitl.approval_channel) {\n document.getElementById('hitl-channel').value = cfg.hitl.approval_channel;\n document.getElementById('hitl-webhook-field').classList.toggle('hidden', cfg.hitl.approval_channel !== 'webhook');\n }\n if (cfg.hitl.timeout_seconds) document.getElementById('hitl-timeout').value = cfg.hitl.timeout_seconds;\n if (cfg.hitl.webhook && cfg.hitl.webhook.url) document.getElementById('hitl-webhook-url').value = cfg.hitl.webhook.url;\n }\n\n // DLP\n if (cfg.dlp) {\n document.getElementById('dlp-enabled').checked = cfg.dlp.enabled !== false;\n document.getElementById('dlp-options').classList.toggle('hidden', !cfg.dlp.enabled);\n if (cfg.dlp.mode) setChipValue('dlp-mode', cfg.dlp.mode);\n if (cfg.dlp.on_input) document.getElementById('dlp-on-input').value = cfg.dlp.on_input;\n if (cfg.dlp.on_output) document.getElementById('dlp-on-output').value = cfg.dlp.on_output;\n if (cfg.dlp.masking) {\n if (cfg.dlp.masking.strategy) document.getElementById('dlp-mask-strategy').value = cfg.dlp.masking.strategy;\n if (cfg.dlp.masking.show_chars != null) document.getElementById('dlp-mask-show').value = cfg.dlp.masking.show_chars;\n if (cfg.dlp.masking.placeholder) document.getElementById('dlp-mask-placeholder').value = cfg.dlp.masking.placeholder;\n }\n if (cfg.dlp.severity_threshold) setChipValue('dlp-severity', cfg.dlp.severity_threshold);\n if (cfg.dlp.built_in) {\n if (cfg.dlp.built_in.secrets != null) document.getElementById('dlp-secrets').checked = cfg.dlp.built_in.secrets;\n if (cfg.dlp.built_in.pii != null) document.getElementById('dlp-pii').checked = cfg.dlp.built_in.pii;\n }\n if (cfg.dlp.custom_patterns) {\n customPatterns = cfg.dlp.custom_patterns;\n renderCustomPatterns();\n }\n if (cfg.dlp.allowlist) {\n allowlistEntries = cfg.dlp.allowlist.map(e => e.pattern || e);\n renderAllowlist();\n }\n }\n\n // Audit\n if (cfg.audit && cfg.audit.sinks) {\n auditSinks = cfg.audit.sinks;\n renderAuditSinks();\n }\n\n updatePreview();\n}\n\n// ─── Roles ───────────────────────────────────────────────────────────\nfunction renderRoles() {\n const grid = document.getElementById('role-grid');\n grid.innerHTML = '';\n for (const [key, role] of Object.entries(PRESET_ROLES)) {\n const sel = selectedRoles[key];\n const card = document.createElement('div');\n card.className = 'role-card' + (sel ? ' selected' : '');\n card.dataset.role = key;\n card.onclick = () => { toggleRole(key); };\n card.innerHTML =\n '<div class=\"role-card-check\">&#10003;</div>' +\n '<div class=\"role-name\">' + role.label + '</div>' +\n '<div class=\"role-desc\">' + role.desc + '</div>' +\n '<div class=\"role-tags\">' +\n '<span class=\"role-tag\">' + role.execution_mode + '</span>' +\n '<span class=\"role-tag\">' + (role.token_budget_daily === -1 ? 'unlimited' : role.token_budget_daily.toLocaleString()) + ' budget</span>' +\n '</div>' +\n '<div class=\"role-details\">' +\n '<div class=\"field\"><label>Allowed Tools</label>' +\n '<input type=\"text\" value=\"' + role.allowed_tools.join(', ') + '\" onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'allowed_tools\\\\', this.value)\" onclick=\"event.stopPropagation()\">' +\n '</div>' +\n '<div class=\"field\"><label>Blocked Tools</label>' +\n '<input type=\"text\" value=\"' + role.blocked_tools.join(', ') + '\" onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'blocked_tools\\\\', this.value)\" onclick=\"event.stopPropagation()\">' +\n '</div>' +\n '<div class=\"field\"><label>Execution Mode</label>' +\n '<select onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'execution_mode\\\\', this.value)\" onclick=\"event.stopPropagation()\">' +\n '<option value=\"supervised\"' + (role.execution_mode === 'supervised' ? ' selected' : '') + '>Supervised</option>' +\n '<option value=\"autonomous\"' + (role.execution_mode === 'autonomous' ? ' selected' : '') + '>Autonomous</option>' +\n '<option value=\"dry_run\"' + (role.execution_mode === 'dry_run' ? ' selected' : '') + '>Dry Run</option>' +\n '</select>' +\n '</div>' +\n '<div class=\"field\"><label>Token Budget Daily</label>' +\n '<input type=\"number\" value=\"' + role.token_budget_daily + '\" onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'token_budget_daily\\\\', parseInt(this.value))\" onclick=\"event.stopPropagation()\">' +\n '</div>' +\n '</div>';\n grid.appendChild(card);\n }\n}\n\nfunction toggleRole(key) {\n selectedRoles[key] = !selectedRoles[key];\n renderRoles();\n updatePreview();\n}\n\nfunction updateRoleField(key, field, value) {\n if (field === 'allowed_tools' || field === 'blocked_tools') {\n PRESET_ROLES[key][field] = value.split(',').map(s => s.trim()).filter(Boolean);\n } else {\n PRESET_ROLES[key][field] = value;\n }\n updatePreview();\n}\n\n// ─── Section Toggle ──────────────────────────────────────────────────\nfunction toggleSection(id) {\n document.getElementById(id).classList.toggle('collapsed');\n}\n\n// ─── Chip Groups ─────────────────────────────────────────────────────\nfunction selectChip(el) {\n const group = el.parentElement;\n group.querySelectorAll('.chip').forEach(c => c.classList.remove('active'));\n el.classList.add('active');\n\n // Auth provider visibility\n if (group.id === 'auth-provider') {\n const val = el.dataset.value;\n document.getElementById('auth-env-fields').classList.toggle('hidden', val !== 'env');\n document.getElementById('auth-local-fields').classList.toggle('hidden', val !== 'local');\n }\n\n updatePreview();\n}\n\nfunction getChipValue(groupId) {\n const active = document.querySelector('#' + groupId + ' .chip.active');\n return active ? active.dataset.value : '';\n}\n\nfunction setChipValue(groupId, value) {\n const group = document.getElementById(groupId);\n if (!group) return;\n group.querySelectorAll('.chip').forEach(c => {\n c.classList.toggle('active', c.dataset.value === value);\n });\n}\n\n// ─── Custom Patterns ─────────────────────────────────────────────────\nfunction addCustomPattern() {\n customPatterns.push({ name: '', pattern: '', severity: 'medium', action: 'audit' });\n renderCustomPatterns();\n}\n\nfunction renderCustomPatterns() {\n const container = document.getElementById('dlp-custom-patterns');\n container.innerHTML = '';\n customPatterns.forEach((p, i) => {\n const div = document.createElement('div');\n div.className = 'pattern-item';\n div.innerHTML =\n '<input type=\"text\" placeholder=\"Name\" value=\"' + esc(p.name) + '\" onchange=\"customPatterns[' + i + '].name=this.value;updatePreview()\">' +\n '<input type=\"text\" placeholder=\"Regex pattern\" value=\"' + esc(p.pattern) + '\" onchange=\"customPatterns[' + i + '].pattern=this.value;updatePreview()\">' +\n '<select onchange=\"customPatterns[' + i + '].severity=this.value;updatePreview()\">' +\n '<option value=\"low\"' + (p.severity==='low'?' selected':'') + '>Low</option>' +\n '<option value=\"medium\"' + (p.severity==='medium'?' selected':'') + '>Medium</option>' +\n '<option value=\"high\"' + (p.severity==='high'?' selected':'') + '>High</option>' +\n '<option value=\"critical\"' + (p.severity==='critical'?' selected':'') + '>Critical</option>' +\n '</select>' +\n '<button class=\"btn-remove\" onclick=\"customPatterns.splice(' + i + ',1);renderCustomPatterns();updatePreview()\">&times;</button>';\n container.appendChild(div);\n });\n}\n\n// ─── Allowlist ───────────────────────────────────────────────────────\nfunction addAllowlistEntry() {\n allowlistEntries.push('');\n renderAllowlist();\n}\n\nfunction renderAllowlist() {\n const container = document.getElementById('dlp-allowlist');\n container.innerHTML = '';\n allowlistEntries.forEach((entry, i) => {\n const div = document.createElement('div');\n div.className = 'allowlist-item';\n div.innerHTML =\n '<input type=\"text\" placeholder=\"Pattern to allow\" value=\"' + esc(entry) + '\" onchange=\"allowlistEntries[' + i + ']=this.value;updatePreview()\">' +\n '<button class=\"btn-remove\" onclick=\"allowlistEntries.splice(' + i + ',1);renderAllowlist();updatePreview()\">&times;</button>';\n container.appendChild(div);\n });\n}\n\n// ─── Audit Sinks ─────────────────────────────────────────────────────\nfunction addAuditSink() {\n auditSinks.push({ type: 'jsonl', path: '' });\n renderAuditSinks();\n}\n\nfunction renderAuditSinks() {\n const container = document.getElementById('audit-sinks');\n container.innerHTML = '';\n auditSinks.forEach((sink, i) => {\n const div = document.createElement('div');\n div.className = 'sink-item';\n let inner = '<button class=\"btn-remove\" onclick=\"auditSinks.splice(' + i + ',1);renderAuditSinks();updatePreview()\">&times;</button>';\n inner += '<div class=\"field\"><label>Sink Type</label>' +\n '<select onchange=\"auditSinks[' + i + '].type=this.value;renderAuditSinks();updatePreview()\">' +\n '<option value=\"jsonl\"' + (sink.type==='jsonl'?' selected':'') + '>JSONL File</option>' +\n '<option value=\"webhook\"' + (sink.type==='webhook'?' selected':'') + '>Webhook</option>' +\n '<option value=\"postgres\"' + (sink.type==='postgres'?' selected':'') + '>PostgreSQL</option>' +\n '</select></div>';\n if (sink.type === 'jsonl') {\n inner += '<div class=\"field\"><label>File Path</label>' +\n '<input type=\"text\" value=\"' + esc(sink.path || '') + '\" placeholder=\"~/.pi/agent/audit.jsonl\" ' +\n 'onchange=\"auditSinks[' + i + '].path=this.value;updatePreview()\"></div>';\n } else if (sink.type === 'webhook') {\n inner += '<div class=\"field\"><label>Webhook URL</label>' +\n '<input type=\"text\" value=\"' + esc(sink.url || '') + '\" placeholder=\"https://...\" ' +\n 'onchange=\"auditSinks[' + i + '].url=this.value;updatePreview()\"></div>';\n } else if (sink.type === 'postgres') {\n inner += '<div class=\"field\"><label>Connection String</label>' +\n '<input type=\"text\" value=\"' + esc(sink.connection || '') + '\" placeholder=\"postgresql://...\" ' +\n 'onchange=\"auditSinks[' + i + '].connection=this.value;updatePreview()\"></div>';\n }\n div.innerHTML = inner;\n container.appendChild(div);\n });\n}\n\n// ─── Preview Tabs ────────────────────────────────────────────────────\nfunction switchTab(el) {\n document.querySelectorAll('.preview-tab').forEach(t => t.classList.remove('active'));\n el.classList.add('active');\n activePreviewTab = el.dataset.tab;\n updatePreview();\n}\n\n// ─── YAML Generator ──────────────────────────────────────────────────\nfunction toYaml(obj, indent) {\n indent = indent || 0;\n const pad = ' '.repeat(indent);\n let out = '';\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return ' []\\\\n';\n for (const item of obj) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const keys = Object.keys(item);\n if (keys.length > 0) {\n out += pad + '- ' + keys[0] + ': ' + formatScalar(item[keys[0]]) + '\\\\n';\n for (let k = 1; k < keys.length; k++) {\n const val = item[keys[k]];\n if (typeof val === 'object' && val !== null) {\n out += pad + ' ' + keys[k] + ':\\\\n' + toYaml(val, indent + 2);\n } else {\n out += pad + ' ' + keys[k] + ': ' + formatScalar(val) + '\\\\n';\n }\n }\n }\n } else {\n out += pad + '- ' + formatScalar(item) + '\\\\n';\n }\n }\n return out;\n }\n\n if (typeof obj === 'object' && obj !== null) {\n for (const [key, val] of Object.entries(obj)) {\n if (val === undefined || val === null) continue;\n if (typeof val === 'object') {\n const yamlVal = toYaml(val, indent + 1);\n if (Array.isArray(val) && val.length === 0) {\n out += pad + key + ': []\\\\n';\n } else {\n out += pad + key + ':\\\\n' + yamlVal;\n }\n } else {\n out += pad + key + ': ' + formatScalar(val) + '\\\\n';\n }\n }\n return out;\n }\n\n return pad + formatScalar(obj) + '\\\\n';\n}\n\nfunction formatScalar(val) {\n if (typeof val === 'boolean') return val ? 'true' : 'false';\n if (typeof val === 'number') return String(val);\n if (typeof val === 'string') {\n if (val === '') return \"''\";\n if (val === 'true' || val === 'false' || !isNaN(val)) return \"'\" + val + \"'\";\n if (/[:#{}\\\\[\\\\],&*?|\\\\->!%@]/.test(val) || val.includes('\\\\\\\\')) return \"'\" + val.replace(/'/g, \"''\") + \"'\";\n return val;\n }\n return String(val);\n}\n\n// ─── Build Config Objects ────────────────────────────────────────────\nfunction buildGovernanceConfig() {\n const cfg = {};\n\n // Auth\n const authProvider = getChipValue('auth-provider');\n cfg.auth = { provider: authProvider };\n if (authProvider === 'env') {\n cfg.auth.env = {\n user_var: document.getElementById('auth-user-var').value || 'PI_GOV_USER',\n role_var: document.getElementById('auth-role-var').value || 'PI_GOV_ROLE',\n org_unit_var: document.getElementById('auth-org-unit-var').value || 'PI_GOV_ORG_UNIT'\n };\n } else if (authProvider === 'local') {\n cfg.auth.local = {\n users_file: document.getElementById('auth-users-file').value || './users.yaml'\n };\n }\n\n // Policy\n cfg.policy = {\n engine: 'yaml',\n yaml: { rules_file: './governance-rules.yaml' }\n };\n\n // HITL\n cfg.hitl = {\n default_mode: getChipValue('hitl-mode') || 'supervised',\n approval_channel: document.getElementById('hitl-channel').value,\n timeout_seconds: parseInt(document.getElementById('hitl-timeout').value) || 300\n };\n if (cfg.hitl.approval_channel === 'webhook') {\n const url = document.getElementById('hitl-webhook-url').value;\n if (url) cfg.hitl.webhook = { url: url };\n }\n\n // Audit\n cfg.audit = { sinks: auditSinks.filter(s => {\n if (s.type === 'jsonl') return s.path;\n if (s.type === 'webhook') return s.url;\n if (s.type === 'postgres') return s.connection;\n return false;\n }).map(s => {\n if (s.type === 'jsonl') return { type: 'jsonl', path: s.path };\n if (s.type === 'webhook') return { type: 'webhook', url: s.url };\n if (s.type === 'postgres') return { type: 'postgres', connection: s.connection };\n return s;\n })};\n\n // DLP\n if (document.getElementById('dlp-enabled').checked) {\n cfg.dlp = {\n enabled: true,\n mode: getChipValue('dlp-mode') || 'audit'\n };\n const onInput = document.getElementById('dlp-on-input').value;\n const onOutput = document.getElementById('dlp-on-output').value;\n if (onInput) cfg.dlp.on_input = onInput;\n if (onOutput) cfg.dlp.on_output = onOutput;\n cfg.dlp.masking = {\n strategy: document.getElementById('dlp-mask-strategy').value,\n show_chars: parseInt(document.getElementById('dlp-mask-show').value) || 4,\n placeholder: document.getElementById('dlp-mask-placeholder').value || '***'\n };\n cfg.dlp.severity_threshold = getChipValue('dlp-severity') || 'low';\n cfg.dlp.built_in = {\n secrets: document.getElementById('dlp-secrets').checked,\n pii: document.getElementById('dlp-pii').checked\n };\n const patterns = customPatterns.filter(p => p.name && p.pattern);\n if (patterns.length > 0) cfg.dlp.custom_patterns = patterns;\n const al = allowlistEntries.filter(Boolean);\n if (al.length > 0) cfg.dlp.allowlist = al.map(p => ({ pattern: p }));\n } else {\n cfg.dlp = { enabled: false };\n }\n\n return cfg;\n}\n\nfunction buildRulesConfig() {\n const roles = {};\n for (const [key, sel] of Object.entries(selectedRoles)) {\n if (!sel) continue;\n const r = PRESET_ROLES[key];\n const role = {\n allowed_tools: r.allowed_tools,\n blocked_tools: r.blocked_tools,\n prompt_template: r.prompt_template,\n execution_mode: r.execution_mode,\n human_approval: r.human_approval,\n token_budget_daily: r.token_budget_daily,\n allowed_paths: r.allowed_paths,\n blocked_paths: r.blocked_paths\n };\n if (r.bash_overrides) role.bash_overrides = r.bash_overrides;\n roles[key] = role;\n }\n return { roles: roles };\n}\n\n// ─── Update Preview ──────────────────────────────────────────────────\nfunction updatePreview() {\n const el = document.getElementById('preview-yaml');\n if (activePreviewTab === 'governance') {\n const cfg = buildGovernanceConfig();\n el.textContent = '# governance.yaml\\\\n# Generated by Pi Governance Setup Wizard\\\\n\\\\n' + toYaml(cfg);\n } else {\n const rules = buildRulesConfig();\n el.textContent = '# governance-rules.yaml\\\\n# Generated by Pi Governance Setup Wizard\\\\n\\\\n' + toYaml(rules);\n }\n}\n\n// ─── Save ────────────────────────────────────────────────────────────\nasync function handleSave() {\n const btn = document.getElementById('btn-save');\n const status = document.getElementById('save-status');\n btn.disabled = true;\n status.textContent = 'Saving...';\n status.className = 'save-status';\n\n try {\n const payload = {\n governance: buildGovernanceConfig(),\n rules: buildRulesConfig()\n };\n const res = await fetch('/api/save', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload)\n });\n if (!res.ok) {\n const err = await res.text();\n throw new Error(err || 'Server error');\n }\n const result = await res.json();\n showToast('Configuration saved!', 'success');\n status.textContent = 'Saved: ' + (result.files || []).join(', ');\n status.className = 'save-status success';\n } catch (e) {\n showToast('Failed to save: ' + e.message, 'error');\n status.textContent = 'Error: ' + e.message;\n status.className = 'save-status error';\n } finally {\n btn.disabled = false;\n }\n}\n\nasync function handleClose() {\n try { await fetch('/api/close', { method: 'POST' }); } catch (e) { /* ignore */ }\n window.close();\n}\n\n// ─── Toast ───────────────────────────────────────────────────────────\nfunction showToast(msg, type) {\n const toast = document.getElementById('toast');\n toast.textContent = msg;\n toast.className = 'toast ' + type + ' visible';\n setTimeout(() => { toast.classList.remove('visible'); }, 3000);\n}\n\n// ─── Util ────────────────────────────────────────────────────────────\nfunction esc(s) {\n return String(s).replace(/&/g,'&amp;').replace(/\"/g,'&quot;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n}\n</script>\n</body>\n</html>`;\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { writeFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { stringify } from 'yaml';\nimport type { GovernanceConfig } from '../config/schema.js';\nimport { DEFAULTS } from '../config/defaults.js';\nimport { WIZARD_HTML } from './html.js';\n\nexport interface WizardServerOptions {\n workingDirectory: string;\n existingConfig?: GovernanceConfig;\n onComplete: (files: { path: string; content: string }[]) => void;\n onError: (error: Error) => void;\n}\n\nconst AUTO_SHUTDOWN_MS = 10 * 60 * 1000;\n\nconst BUILTIN_ROLES = {\n analyst: {\n allowed_tools: ['read', 'grep', 'find', 'ls'],\n blocked_tools: ['bash', 'write', 'edit'],\n hitl_mode: 'dry_run' as const,\n },\n project_lead: {\n allowed_tools: ['read', 'write', 'edit', 'grep', 'find', 'ls', 'bash'],\n blocked_tools: [],\n hitl_mode: 'supervised' as const,\n },\n admin: {\n allowed_tools: ['read', 'write', 'edit', 'grep', 'find', 'ls', 'bash'],\n blocked_tools: [],\n hitl_mode: 'autonomous' as const,\n },\n auditor: {\n allowed_tools: ['read', 'grep', 'find', 'ls'],\n blocked_tools: ['bash', 'write', 'edit'],\n hitl_mode: 'dry_run' as const,\n },\n};\n\nfunction setCorsHeaders(res: ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', 'http://localhost');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n}\n\nfunction sendJson(res: ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n\nexport function startWizardServer(\n options: WizardServerOptions,\n): Promise<{ port: number; close: () => void }> {\n return new Promise((resolve, reject) => {\n let shutdownTimer: ReturnType<typeof setTimeout> | undefined;\n\n const server = createServer((req, res) => {\n setCorsHeaders(res);\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const url = req.url ?? '/';\n\n try {\n if (req.method === 'GET' && url === '/') {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(WIZARD_HTML);\n return;\n }\n\n if (req.method === 'GET' && url === '/api/config') {\n sendJson(res, 200, options.existingConfig ?? DEFAULTS);\n return;\n }\n\n if (req.method === 'GET' && url === '/api/defaults') {\n sendJson(res, 200, { defaults: DEFAULTS, roles: BUILTIN_ROLES });\n return;\n }\n\n if (req.method === 'POST' && url === '/api/save') {\n readBody(req)\n .then((body) => {\n const parsed: unknown = JSON.parse(body);\n if (typeof parsed !== 'object' || parsed === null || !('governance' in parsed)) {\n sendJson(res, 400, { error: 'Request body must include \"governance\" property' });\n return;\n }\n\n const payload = parsed as { governance: GovernanceConfig; rules?: unknown };\n const governanceYaml = stringify(payload.governance);\n const piDir = join(options.workingDirectory, '.pi');\n const governancePath = join(piDir, 'governance.yaml');\n\n mkdirSync(piDir, { recursive: true });\n writeFileSync(governancePath, governanceYaml, 'utf-8');\n\n const files: { path: string; content: string }[] = [\n { path: governancePath, content: governanceYaml },\n ];\n\n if (payload.rules !== undefined) {\n const rulesYaml = stringify(payload.rules);\n const rulesPath = join(options.workingDirectory, 'governance-rules.yaml');\n writeFileSync(rulesPath, rulesYaml, 'utf-8');\n files.push({ path: rulesPath, content: rulesYaml });\n }\n\n sendJson(res, 200, { ok: true, files: files.map((f) => f.path) });\n options.onComplete(files);\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n sendJson(res, 400, { error: `Invalid request body: ${message}` });\n });\n return;\n }\n\n if (req.method === 'POST' && url === '/api/close') {\n sendJson(res, 200, { ok: true });\n setTimeout(() => {\n closeServer();\n }, 100);\n return;\n }\n\n sendJson(res, 404, { error: 'Not found' });\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n options.onError(error);\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n\n function closeServer(): void {\n if (shutdownTimer !== undefined) {\n clearTimeout(shutdownTimer);\n shutdownTimer = undefined;\n }\n server.close();\n }\n\n server.on('error', (err) => {\n options.onError(err);\n reject(err);\n });\n\n server.listen(0, () => {\n const addr = server.address();\n if (addr === null || typeof addr === 'string') {\n const err = new Error('Failed to get server address');\n options.onError(err);\n reject(err);\n return;\n }\n\n shutdownTimer = setTimeout(() => {\n closeServer();\n }, AUTO_SHUTDOWN_MS);\n\n resolve({ port: addr.port, close: closeServer });\n });\n });\n}\n","export { startWizardServer } from './server.js';\nexport type { WizardServerOptions } from './server.js';\n","// 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 { resolve } from 'node:path';\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 let protectedPaths: Set<string> = new Set();\n\n const stats = {\n configTampered: 0,\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 // 1b. Compute protected config paths (hardcoded — cannot be overridden)\n const paths = new Set<string>();\n if (loaded.source !== 'built-in') {\n paths.add(resolve(loaded.source));\n }\n const rulesFileCfg = config.policy?.yaml?.rules_file ?? './governance-rules.yaml';\n paths.add(resolve(rulesFileCfg));\n // Fallback well-known paths\n paths.add(resolve(ctx.workingDirectory, '.pi/governance.yaml'));\n paths.add(resolve(ctx.workingDirectory, 'governance-rules.yaml'));\n protectedPaths = paths;\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 // Only warn if the user explicitly configured a rules file path\n if (config.policy?.yaml?.rules_file) {\n ctx.ui.notify(`Rules file not found: ${rulesFile} — using built-in defaults`, 'warning');\n }\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 // 0. Hardcoded config self-protection — cannot be bypassed by policy\n if (WRITE_TOOLS.has(toolName)) {\n const filePath = extractPath(toolName, input);\n if (filePath && protectedPaths.has(resolve(filePath))) {\n stats.configTampered++;\n await audit.log({\n ...baseRecord,\n event: 'config_tampered',\n decision: 'denied',\n reason: `Config self-protection: write to governance file blocked (${filePath})`,\n });\n return {\n block: true,\n reason: `Governance config files are protected and cannot be modified by agents`,\n };\n }\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 ` Config tampered: ${stats.configTampered}`,\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 if (subcommand === 'init') {\n const { startWizardServer } = await import('../lib/wizard/index.js');\n\n ctx.ui.notify('Starting governance configuration wizard...', 'info');\n\n const { port, close } = await startWizardServer({\n workingDirectory: ctx.workingDirectory,\n existingConfig: config,\n onComplete: (files) => {\n const names = files.map((f) => f.path).join(', ');\n ctx.ui.notify(`Configuration saved: ${names}`, 'info');\n close();\n },\n onError: (err) => {\n ctx.ui.notify(`Wizard error: ${err.message}`, 'error');\n close();\n },\n });\n\n const url = `http://localhost:${port}`;\n const { exec } = await import('node:child_process');\n const openCmd =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${openCmd} ${url}`);\n\n ctx.ui.notify(`Wizard running at ${url}`, 'info');\n } else {\n ctx.ui.notify('Usage: /governance status | init', '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['PI_GOV_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: 'PI_GOV_USER' }),\n role_var: Type.String({ default: 'PI_GOV_ROLE' }),\n org_unit_var: Type.String({ default: 'PI_GOV_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 { IdentityProvider, ResolvedIdentity } from './provider.js';\n\nexport class EnvIdentityProvider implements IdentityProvider {\n name = 'env';\n\n constructor(\n private userVar: string = 'PI_GOV_USER',\n private roleVar: string = 'PI_GOV_ROLE',\n private orgUnitVar: string = 'PI_GOV_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 // Governance config tampering — shell-based writes to governance files\n /(cat|echo|printf)\\s.*>\\s*.*governance(-rules)?\\.yaml/,\n /\\btee\\s+.*governance(-rules)?\\.yaml/,\n /sed\\s+-i.*governance(-rules)?\\.yaml/,\n /(cp|mv|rm)\\s.*governance(-rules)?\\.yaml/,\n /(cat|echo|printf)\\s.*>\\s*.*\\.pi\\/governance/,\n /\\btee\\s+.*\\.pi\\/governance/,\n /sed\\s+-i.*\\.pi\\/governance/,\n /(cp|mv|rm)\\s.*\\.pi\\/governance/,\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,IAEa;AAFb;AAAA;AAAA;AAEO,IAAM,WAA6B;AAAA,MACxC,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,KAAK;AAAA,UACH,UAAU;AAAA,UACV,UAAU;AAAA,UACV,cAAc;AAAA,QAChB;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,UACJ,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AAAA,MACA,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,iBAAiB;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,QACL,OAAO,CAAC,EAAE,MAAM,SAAS,MAAM,0BAA0B,CAAC;AAAA,MAC5D;AAAA,MACA,KAAK;AAAA,QACH,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,UACP,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,aAAa;AAAA,QACf;AAAA,QACA,oBAAoB;AAAA,QACpB,UAAU;AAAA,UACR,SAAS;AAAA,UACT,KAAK;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC7CA,IAAa;AAAb;AAAA;AAAA;AAAO,IAAM,cAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["resolve","existsSync","readFileSync","parseYaml","readFileSync","parseYaml","readFileSync","parseYaml","Value","readFileSync","parseYaml","Value","existsSync","startWizardServer"]}
1
+ {"version":3,"sources":["../../src/lib/config/defaults.ts","../../src/lib/wizard/html.ts","../../src/lib/wizard/server.ts","../../src/lib/wizard/index.ts","../../src/extensions/index.ts","../../src/lib/config/loader.ts","../../src/lib/config/schema.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":["import type { GovernanceConfig } from './schema.js';\n\nexport const DEFAULTS: GovernanceConfig = {\n auth: {\n provider: 'env',\n env: {\n user_var: 'PI_GOV_USER',\n role_var: 'PI_GOV_ROLE',\n org_unit_var: 'PI_GOV_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: true,\n mode: 'audit',\n on_input: 'block',\n on_output: 'mask',\n masking: {\n strategy: 'partial',\n show_chars: 4,\n placeholder: '***',\n },\n severity_threshold: 'low',\n built_in: {\n secrets: true,\n pii: true,\n },\n },\n};\n","export const WIZARD_HTML: string = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Pi Governance — Setup Wizard</title>\n<style>\n :root {\n --bg: #f8f9fa;\n --bg-surface: #ffffff;\n --bg-surface-alt: #f1f3f5;\n --bg-code: #e9ecef;\n --text: #212529;\n --text-muted: #6c757d;\n --text-inverse: #ffffff;\n --border: #dee2e6;\n --border-focus: #4263eb;\n --primary: #4263eb;\n --primary-hover: #3b5bdb;\n --primary-subtle: #dbe4ff;\n --success: #2f9e44;\n --success-subtle: #d3f9d8;\n --danger: #e03131;\n --danger-subtle: #ffe3e3;\n --warning: #f08c00;\n --warning-subtle: #fff3bf;\n --radius: 8px;\n --radius-sm: 4px;\n --shadow: 0 1px 3px rgba(0,0,0,0.08);\n --shadow-lg: 0 4px 12px rgba(0,0,0,0.1);\n --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;\n --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;\n --transition: 150ms ease;\n }\n\n @media (prefers-color-scheme: dark) {\n :root {\n --bg: #1a1b1e;\n --bg-surface: #25262b;\n --bg-surface-alt: #2c2e33;\n --bg-code: #2c2e33;\n --text: #c1c2c5;\n --text-muted: #909296;\n --text-inverse: #1a1b1e;\n --border: #373a40;\n --border-focus: #5c7cfa;\n --primary: #5c7cfa;\n --primary-hover: #748ffc;\n --primary-subtle: #1b2559;\n --success: #51cf66;\n --success-subtle: #0b3d1a;\n --danger: #ff6b6b;\n --danger-subtle: #3d0b0b;\n --warning: #fcc419;\n --warning-subtle: #3d2e00;\n --shadow: 0 1px 3px rgba(0,0,0,0.3);\n --shadow-lg: 0 4px 12px rgba(0,0,0,0.4);\n }\n }\n\n * { margin: 0; padding: 0; box-sizing: border-box; }\n\n body {\n font-family: var(--font-sans);\n background: var(--bg);\n color: var(--text);\n line-height: 1.6;\n min-height: 100vh;\n }\n\n .layout {\n display: grid;\n grid-template-columns: 1fr 420px;\n gap: 0;\n min-height: 100vh;\n }\n\n @media (max-width: 1024px) {\n .layout { grid-template-columns: 1fr; }\n .preview-panel { display: none; }\n }\n\n /* --- Left column: Form --- */\n .form-column {\n padding: 32px 40px 80px;\n overflow-y: auto;\n max-height: 100vh;\n }\n\n .logo {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n }\n\n .logo-icon {\n width: 36px; height: 36px;\n background: var(--primary);\n border-radius: var(--radius);\n display: flex; align-items: center; justify-content: center;\n color: var(--text-inverse);\n font-weight: 700; font-size: 18px;\n }\n\n .logo-text {\n font-size: 20px;\n font-weight: 700;\n color: var(--text);\n }\n\n .logo-text span { color: var(--text-muted); font-weight: 400; }\n\n h1 {\n font-size: 28px;\n font-weight: 700;\n margin: 24px 0 8px;\n }\n\n .subtitle {\n color: var(--text-muted);\n font-size: 15px;\n margin-bottom: 32px;\n }\n\n /* Sections */\n .section {\n background: var(--bg-surface);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 24px;\n margin-bottom: 20px;\n box-shadow: var(--shadow);\n }\n\n .section-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 16px;\n cursor: pointer;\n user-select: none;\n }\n\n .section-header h2 {\n font-size: 16px;\n font-weight: 600;\n flex: 1;\n }\n\n .section-badge {\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .badge-required { background: var(--danger-subtle); color: var(--danger); }\n .badge-optional { background: var(--primary-subtle); color: var(--primary); }\n\n .section-icon {\n width: 32px; height: 32px;\n border-radius: var(--radius-sm);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px;\n flex-shrink: 0;\n }\n\n .section-body { display: block; }\n .section.collapsed .section-body { display: none; }\n .section-chevron {\n transition: transform var(--transition);\n color: var(--text-muted);\n font-size: 12px;\n }\n .section.collapsed .section-chevron { transform: rotate(-90deg); }\n\n /* Form elements */\n label {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n margin-bottom: 4px;\n }\n\n .label-hint {\n font-weight: 400;\n color: var(--text-muted);\n font-size: 12px;\n }\n\n input[type=\"text\"],\n input[type=\"number\"],\n select {\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--border);\n border-radius: var(--radius-sm);\n background: var(--bg-surface);\n color: var(--text);\n font-size: 14px;\n font-family: var(--font-sans);\n transition: border-color var(--transition);\n outline: none;\n }\n\n input:focus, select:focus {\n border-color: var(--border-focus);\n box-shadow: 0 0 0 2px var(--primary-subtle);\n }\n\n .field { margin-bottom: 16px; }\n\n .field-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n }\n\n .field-row-3 {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 12px;\n }\n\n /* Toggle switch */\n .toggle-row {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 12px;\n }\n\n .toggle {\n position: relative;\n width: 40px; height: 22px;\n flex-shrink: 0;\n }\n\n .toggle input { display: none; }\n\n .toggle-slider {\n position: absolute;\n inset: 0;\n background: var(--border);\n border-radius: 11px;\n cursor: pointer;\n transition: background var(--transition);\n }\n\n .toggle-slider::before {\n content: '';\n position: absolute;\n width: 16px; height: 16px;\n left: 3px; top: 3px;\n background: white;\n border-radius: 50%;\n transition: transform var(--transition);\n }\n\n .toggle input:checked + .toggle-slider {\n background: var(--primary);\n }\n\n .toggle input:checked + .toggle-slider::before {\n transform: translateX(18px);\n }\n\n .toggle-label {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* Role cards */\n .role-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n }\n\n .role-card {\n border: 2px solid var(--border);\n border-radius: var(--radius);\n padding: 16px;\n cursor: pointer;\n transition: all var(--transition);\n position: relative;\n }\n\n .role-card:hover { border-color: var(--primary); }\n\n .role-card.selected {\n border-color: var(--primary);\n background: var(--primary-subtle);\n }\n\n .role-card-check {\n position: absolute;\n top: 12px; right: 12px;\n width: 20px; height: 20px;\n border: 2px solid var(--border);\n border-radius: 4px;\n display: flex; align-items: center; justify-content: center;\n font-size: 12px;\n color: transparent;\n transition: all var(--transition);\n }\n\n .role-card.selected .role-card-check {\n background: var(--primary);\n border-color: var(--primary);\n color: white;\n }\n\n .role-name {\n font-weight: 600;\n font-size: 14px;\n margin-bottom: 4px;\n }\n\n .role-desc {\n font-size: 12px;\n color: var(--text-muted);\n margin-bottom: 8px;\n }\n\n .role-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n\n .role-tag {\n font-size: 11px;\n padding: 1px 6px;\n border-radius: 3px;\n background: var(--bg-surface-alt);\n color: var(--text-muted);\n font-family: var(--font-mono);\n }\n\n .role-details {\n display: none;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--border);\n }\n\n .role-card.selected .role-details { display: block; }\n\n /* Chip selector */\n .chip-group {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-bottom: 12px;\n }\n\n .chip {\n padding: 5px 14px;\n border: 1px solid var(--border);\n border-radius: 16px;\n font-size: 13px;\n cursor: pointer;\n transition: all var(--transition);\n background: var(--bg-surface);\n color: var(--text);\n }\n\n .chip:hover { border-color: var(--primary); }\n\n .chip.active {\n background: var(--primary);\n border-color: var(--primary);\n color: var(--text-inverse);\n }\n\n /* Pattern list */\n .pattern-list { margin-top: 12px; }\n\n .pattern-item {\n display: grid;\n grid-template-columns: 1fr 1.5fr auto auto;\n gap: 8px;\n align-items: center;\n margin-bottom: 8px;\n }\n\n .pattern-item input, .pattern-item select {\n font-size: 13px;\n padding: 6px 8px;\n }\n\n .btn-remove {\n background: none;\n border: none;\n color: var(--danger);\n cursor: pointer;\n font-size: 18px;\n padding: 4px;\n line-height: 1;\n }\n\n .btn-add {\n background: none;\n border: 1px dashed var(--border);\n border-radius: var(--radius-sm);\n padding: 6px 14px;\n color: var(--primary);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n transition: all var(--transition);\n }\n\n .btn-add:hover {\n border-color: var(--primary);\n background: var(--primary-subtle);\n }\n\n /* Allowlist */\n .allowlist-item {\n display: flex;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .allowlist-item input { flex: 1; font-size: 13px; padding: 6px 8px; }\n\n /* Sink list */\n .sink-item {\n background: var(--bg-surface-alt);\n border-radius: var(--radius-sm);\n padding: 12px;\n margin-bottom: 8px;\n position: relative;\n }\n\n .sink-item .btn-remove {\n position: absolute;\n top: 8px; right: 8px;\n }\n\n /* --- Right column: Preview --- */\n .preview-panel {\n background: var(--bg-surface-alt);\n border-left: 1px solid var(--border);\n padding: 24px;\n display: flex;\n flex-direction: column;\n position: sticky;\n top: 0;\n height: 100vh;\n overflow: hidden;\n }\n\n .preview-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n flex-shrink: 0;\n }\n\n .preview-header h3 {\n font-size: 14px;\n font-weight: 600;\n }\n\n .preview-tabs {\n display: flex;\n gap: 4px;\n margin-bottom: 12px;\n flex-shrink: 0;\n }\n\n .preview-tab {\n padding: 4px 12px;\n font-size: 12px;\n border: 1px solid var(--border);\n border-radius: var(--radius-sm);\n background: var(--bg-surface);\n cursor: pointer;\n color: var(--text-muted);\n transition: all var(--transition);\n }\n\n .preview-tab.active {\n background: var(--primary);\n border-color: var(--primary);\n color: var(--text-inverse);\n }\n\n .preview-content {\n flex: 1;\n overflow-y: auto;\n background: var(--bg-surface);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 16px;\n }\n\n .preview-content pre {\n font-family: var(--font-mono);\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n color: var(--text);\n margin: 0;\n }\n\n /* Bottom bar */\n .bottom-bar {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 420px;\n padding: 16px 40px;\n background: var(--bg-surface);\n border-top: 1px solid var(--border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n z-index: 100;\n box-shadow: 0 -2px 8px rgba(0,0,0,0.06);\n }\n\n @media (max-width: 1024px) {\n .bottom-bar { right: 0; }\n }\n\n .btn-primary {\n padding: 10px 28px;\n background: var(--primary);\n color: var(--text-inverse);\n border: none;\n border-radius: var(--radius);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: background var(--transition);\n }\n\n .btn-primary:hover { background: var(--primary-hover); }\n .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }\n\n .btn-secondary {\n padding: 10px 20px;\n background: var(--bg-surface);\n color: var(--text);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all var(--transition);\n }\n\n .btn-secondary:hover { border-color: var(--primary); color: var(--primary); }\n\n .save-status {\n font-size: 13px;\n color: var(--text-muted);\n }\n\n .save-status.success { color: var(--success); }\n .save-status.error { color: var(--danger); }\n\n /* Toast */\n .toast {\n position: fixed;\n top: 20px;\n right: 20px;\n padding: 12px 20px;\n border-radius: var(--radius);\n font-size: 14px;\n font-weight: 500;\n z-index: 1000;\n box-shadow: var(--shadow-lg);\n transform: translateY(-10px);\n opacity: 0;\n transition: all 300ms ease;\n pointer-events: none;\n }\n\n .toast.visible { transform: translateY(0); opacity: 1; pointer-events: auto; }\n .toast.success { background: var(--success); color: white; }\n .toast.error { background: var(--danger); color: white; }\n\n /* Helpers */\n .help-text {\n font-size: 12px;\n color: var(--text-muted);\n margin-top: 4px;\n }\n\n .divider {\n border: none;\n border-top: 1px solid var(--border);\n margin: 16px 0;\n }\n\n .hidden { display: none !important; }\n</style>\n</head>\n<body>\n<div class=\"layout\">\n <!-- ═══════════ LEFT: FORM ═══════════ -->\n <div class=\"form-column\">\n <div class=\"logo\">\n <div class=\"logo-icon\">G</div>\n <div class=\"logo-text\">Pi Governance <span>Setup Wizard</span></div>\n </div>\n\n <h1>Configure your governance policy</h1>\n <p class=\"subtitle\">\n AI coding agents are powerful but need guardrails. This wizard generates a\n <code>governance.yaml</code> and <code>governance-rules.yaml</code> to control\n tool access, bash safety, data-loss prevention, human approvals, and audit logging.\n </p>\n\n <!-- ── 1. Roles ── -->\n <div class=\"section\" id=\"sec-roles\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-roles')\">\n <div class=\"section-icon\" style=\"background:var(--primary-subtle);color:var(--primary)\">&#x1f465;</div>\n <h2>Roles</h2>\n <span class=\"section-badge badge-required\">Required</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <p class=\"help-text\" style=\"margin-bottom:12px\">Select the roles your team needs. Each role defines tool access, execution mode, and approval rules.</p>\n <div class=\"role-grid\" id=\"role-grid\"></div>\n </div>\n </div>\n\n <!-- ── 2. DLP ── -->\n <div class=\"section\" id=\"sec-dlp\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-dlp')\">\n <div class=\"section-icon\" style=\"background:var(--warning-subtle);color:var(--warning)\">&#x1f6e1;</div>\n <h2>Data Loss Prevention</h2>\n <span class=\"section-badge badge-optional\">Optional</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <div class=\"toggle-row\">\n <label class=\"toggle\"><input type=\"checkbox\" id=\"dlp-enabled\" checked onchange=\"updatePreview()\"><span class=\"toggle-slider\"></span></label>\n <span class=\"toggle-label\">Enable DLP scanning</span>\n </div>\n\n <div id=\"dlp-options\">\n <div class=\"field\">\n <label>Default Mode</label>\n <div class=\"chip-group\" id=\"dlp-mode\">\n <span class=\"chip active\" data-value=\"audit\" onclick=\"selectChip(this)\">Audit</span>\n <span class=\"chip\" data-value=\"mask\" onclick=\"selectChip(this)\">Mask</span>\n <span class=\"chip\" data-value=\"block\" onclick=\"selectChip(this)\">Block</span>\n </div>\n </div>\n\n <div class=\"field-row\">\n <div class=\"field\">\n <label>On Input <span class=\"label-hint\">(agent receives)</span></label>\n <select id=\"dlp-on-input\" onchange=\"updatePreview()\">\n <option value=\"\">Use default mode</option>\n <option value=\"audit\">Audit</option>\n <option value=\"mask\">Mask</option>\n <option value=\"block\" selected>Block</option>\n </select>\n </div>\n <div class=\"field\">\n <label>On Output <span class=\"label-hint\">(agent produces)</span></label>\n <select id=\"dlp-on-output\" onchange=\"updatePreview()\">\n <option value=\"\">Use default mode</option>\n <option value=\"audit\">Audit</option>\n <option value=\"mask\" selected>Mask</option>\n <option value=\"block\">Block</option>\n </select>\n </div>\n </div>\n\n <hr class=\"divider\">\n <label>Built-in Patterns</label>\n <div class=\"toggle-row\" style=\"margin-top:6px\">\n <label class=\"toggle\"><input type=\"checkbox\" id=\"dlp-secrets\" checked onchange=\"updatePreview()\"><span class=\"toggle-slider\"></span></label>\n <span class=\"toggle-label\">Secrets <span class=\"label-hint\">(API keys, tokens, passwords)</span></span>\n </div>\n <div class=\"toggle-row\">\n <label class=\"toggle\"><input type=\"checkbox\" id=\"dlp-pii\" checked onchange=\"updatePreview()\"><span class=\"toggle-slider\"></span></label>\n <span class=\"toggle-label\">PII <span class=\"label-hint\">(emails, phone numbers, SSNs)</span></span>\n </div>\n\n <hr class=\"divider\">\n <label>Masking Options</label>\n <div class=\"field-row-3\" style=\"margin-top:8px\">\n <div class=\"field\">\n <label>Strategy</label>\n <select id=\"dlp-mask-strategy\" onchange=\"updatePreview()\">\n <option value=\"partial\" selected>Partial</option>\n <option value=\"full\">Full</option>\n <option value=\"hash\">Hash</option>\n </select>\n </div>\n <div class=\"field\">\n <label>Show Chars</label>\n <input type=\"number\" id=\"dlp-mask-show\" value=\"4\" min=\"0\" onchange=\"updatePreview()\">\n </div>\n <div class=\"field\">\n <label>Placeholder</label>\n <input type=\"text\" id=\"dlp-mask-placeholder\" value=\"***\" onchange=\"updatePreview()\">\n </div>\n </div>\n\n <hr class=\"divider\">\n <label>Severity Threshold <span class=\"label-hint\">(minimum severity to trigger DLP)</span></label>\n <div class=\"chip-group\" id=\"dlp-severity\" style=\"margin-top:6px\">\n <span class=\"chip active\" data-value=\"low\" onclick=\"selectChip(this)\">Low</span>\n <span class=\"chip\" data-value=\"medium\" onclick=\"selectChip(this)\">Medium</span>\n <span class=\"chip\" data-value=\"high\" onclick=\"selectChip(this)\">High</span>\n <span class=\"chip\" data-value=\"critical\" onclick=\"selectChip(this)\">Critical</span>\n </div>\n\n <hr class=\"divider\">\n <label>Custom Patterns</label>\n <div class=\"pattern-list\" id=\"dlp-custom-patterns\"></div>\n <button class=\"btn-add\" onclick=\"addCustomPattern()\">+ Add pattern</button>\n\n <hr class=\"divider\">\n <label>Allowlist <span class=\"label-hint\">(patterns to ignore)</span></label>\n <div id=\"dlp-allowlist\"></div>\n <button class=\"btn-add\" onclick=\"addAllowlistEntry()\" style=\"margin-top:8px\">+ Add entry</button>\n </div>\n </div>\n </div>\n\n <!-- ── 3. Bash Classification ── -->\n <div class=\"section\" id=\"sec-bash\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-bash')\">\n <div class=\"section-icon\" style=\"background:var(--danger-subtle);color:var(--danger)\">&#x1f4bb;</div>\n <h2>Bash Classification</h2>\n <span class=\"section-badge badge-optional\">Optional</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <p class=\"help-text\" style=\"margin-bottom:12px\">The built-in bash classifier categorizes commands by danger level. Adjust the threshold for auto-blocking.</p>\n <div class=\"field\">\n <label>Auto-block Severity</label>\n <p class=\"help-text\">Commands at or above this severity are blocked without HITL.</p>\n <div class=\"chip-group\" id=\"bash-severity\" style=\"margin-top:6px\">\n <span class=\"chip\" data-value=\"low\" onclick=\"selectChip(this)\">Low</span>\n <span class=\"chip\" data-value=\"medium\" onclick=\"selectChip(this)\">Medium</span>\n <span class=\"chip active\" data-value=\"high\" onclick=\"selectChip(this)\">High</span>\n <span class=\"chip\" data-value=\"critical\" onclick=\"selectChip(this)\">Critical</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- ── 4. HITL ── -->\n <div class=\"section\" id=\"sec-hitl\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-hitl')\">\n <div class=\"section-icon\" style=\"background:var(--success-subtle);color:var(--success)\">&#x1f9d1;</div>\n <h2>Human-in-the-Loop</h2>\n <span class=\"section-badge badge-required\">Required</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <div class=\"field\">\n <label>Default Execution Mode</label>\n <div class=\"chip-group\" id=\"hitl-mode\">\n <span class=\"chip\" data-value=\"autonomous\" onclick=\"selectChip(this)\">Autonomous</span>\n <span class=\"chip active\" data-value=\"supervised\" onclick=\"selectChip(this)\">Supervised</span>\n <span class=\"chip\" data-value=\"dry_run\" onclick=\"selectChip(this)\">Dry Run</span>\n </div>\n </div>\n <div class=\"field-row\">\n <div class=\"field\">\n <label>Approval Channel</label>\n <select id=\"hitl-channel\" onchange=\"updatePreview()\">\n <option value=\"cli\" selected>CLI (terminal prompt)</option>\n <option value=\"webhook\">Webhook</option>\n </select>\n </div>\n <div class=\"field\">\n <label>Timeout <span class=\"label-hint\">(seconds)</span></label>\n <input type=\"number\" id=\"hitl-timeout\" value=\"300\" min=\"10\" max=\"3600\" onchange=\"updatePreview()\">\n </div>\n </div>\n <div class=\"field hidden\" id=\"hitl-webhook-field\">\n <label>Webhook URL</label>\n <input type=\"text\" id=\"hitl-webhook-url\" placeholder=\"https://...\" onchange=\"updatePreview()\">\n </div>\n </div>\n </div>\n\n <!-- ── 5. Audit ── -->\n <div class=\"section\" id=\"sec-audit\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-audit')\">\n <div class=\"section-icon\" style=\"background:var(--primary-subtle);color:var(--primary)\">&#x1f4dd;</div>\n <h2>Audit Logging</h2>\n <span class=\"section-badge badge-required\">Required</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <p class=\"help-text\" style=\"margin-bottom:12px\">All governance events are logged to one or more sinks.</p>\n <div id=\"audit-sinks\"></div>\n <button class=\"btn-add\" onclick=\"addAuditSink()\" style=\"margin-top:8px\">+ Add sink</button>\n </div>\n </div>\n\n <!-- ── 6. Auth ── -->\n <div class=\"section collapsed\" id=\"sec-auth\">\n <div class=\"section-header\" onclick=\"toggleSection('sec-auth')\">\n <div class=\"section-icon\" style=\"background:var(--bg-surface-alt);color:var(--text-muted)\">&#x1f511;</div>\n <h2>Authentication</h2>\n <span class=\"section-badge badge-optional\">Optional</span>\n <span class=\"section-chevron\">&#9660;</span>\n </div>\n <div class=\"section-body\">\n <div class=\"field\">\n <label>Provider</label>\n <div class=\"chip-group\" id=\"auth-provider\">\n <span class=\"chip active\" data-value=\"env\" onclick=\"selectChip(this)\">Environment Vars</span>\n <span class=\"chip\" data-value=\"local\" onclick=\"selectChip(this)\">Local File</span>\n <span class=\"chip\" data-value=\"oidc\" onclick=\"selectChip(this)\">OIDC</span>\n </div>\n </div>\n <div id=\"auth-env-fields\">\n <div class=\"field-row-3\">\n <div class=\"field\">\n <label>User Var</label>\n <input type=\"text\" id=\"auth-user-var\" value=\"PI_GOV_USER\" onchange=\"updatePreview()\">\n </div>\n <div class=\"field\">\n <label>Role Var</label>\n <input type=\"text\" id=\"auth-role-var\" value=\"PI_GOV_ROLE\" onchange=\"updatePreview()\">\n </div>\n <div class=\"field\">\n <label>Org Unit Var</label>\n <input type=\"text\" id=\"auth-org-unit-var\" value=\"PI_GOV_ORG_UNIT\" onchange=\"updatePreview()\">\n </div>\n </div>\n </div>\n <div id=\"auth-local-fields\" class=\"hidden\">\n <div class=\"field\">\n <label>Users File</label>\n <input type=\"text\" id=\"auth-users-file\" value=\"./users.yaml\" onchange=\"updatePreview()\">\n </div>\n </div>\n </div>\n </div>\n\n <div style=\"height:80px\"></div>\n </div>\n\n <!-- ═══════════ RIGHT: PREVIEW ═══════════ -->\n <div class=\"preview-panel\">\n <div class=\"preview-header\">\n <h3>Live Preview</h3>\n </div>\n <div class=\"preview-tabs\">\n <span class=\"preview-tab active\" data-tab=\"governance\" onclick=\"switchTab(this)\">governance.yaml</span>\n <span class=\"preview-tab\" data-tab=\"rules\" onclick=\"switchTab(this)\">governance-rules.yaml</span>\n </div>\n <div class=\"preview-content\">\n <pre id=\"preview-yaml\"></pre>\n </div>\n </div>\n</div>\n\n<!-- ── Bottom bar ── -->\n<div class=\"bottom-bar\">\n <span class=\"save-status\" id=\"save-status\"></span>\n <div style=\"display:flex;gap:10px\">\n <button class=\"btn-secondary\" onclick=\"handleClose()\">Cancel</button>\n <button class=\"btn-primary\" id=\"btn-save\" onclick=\"handleSave()\">Save Configuration</button>\n </div>\n</div>\n\n<!-- Toast -->\n<div class=\"toast\" id=\"toast\"></div>\n\n<script>\n// ─── State ───────────────────────────────────────────────────────────\nconst PRESET_ROLES = {\n analyst: {\n label: 'Analyst',\n desc: 'Read-only access, every action requires approval.',\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: 100000,\n allowed_paths: ['{{project_path}}/**'],\n blocked_paths: ['**/secrets/**', '**/.env*']\n },\n project_lead: {\n label: 'Project Lead',\n desc: 'Full tools, bash & write need human approval.',\n allowed_tools: ['read','write','edit','bash','grep','find','ls'],\n blocked_tools: [],\n prompt_template: 'project-lead',\n execution_mode: 'supervised',\n human_approval: { required_for: ['bash','write'], auto_approve: ['read','edit','grep','find','ls'] },\n token_budget_daily: 500000,\n allowed_paths: ['{{project_path}}/**'],\n blocked_paths: ['**/secrets/**', '**/.env*'],\n bash_overrides: { additional_blocked: ['sudo','ssh','curl.*\\\\\\\\|.*sh'] }\n },\n admin: {\n label: 'Admin',\n desc: 'Full autonomous access, no approvals, unlimited budget.',\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 auditor: {\n label: 'Auditor',\n desc: 'Dry-run: all calls logged, nothing executed.',\n allowed_tools: ['read','grep','find','ls'],\n blocked_tools: ['write','edit','bash'],\n prompt_template: 'analyst',\n execution_mode: 'dry_run',\n human_approval: { required_for: ['all'] },\n token_budget_daily: 50000,\n allowed_paths: ['**'],\n blocked_paths: ['**/secrets/**']\n }\n};\n\nlet selectedRoles = { analyst: false, project_lead: true, admin: false, auditor: false };\nlet customPatterns = [];\nlet allowlistEntries = [];\nlet auditSinks = [{ type: 'jsonl', path: '~/.pi/agent/audit.jsonl' }];\nlet activePreviewTab = 'governance';\n\n// ─── Init ────────────────────────────────────────────────────────────\ndocument.addEventListener('DOMContentLoaded', async () => {\n renderRoles();\n renderAuditSinks();\n updatePreview();\n\n try {\n const [configRes, defaultsRes] = await Promise.all([\n fetch('/api/config').catch(() => null),\n fetch('/api/defaults').catch(() => null)\n ]);\n if (configRes && configRes.ok) {\n const cfg = await configRes.json();\n applyConfig(cfg);\n }\n if (defaultsRes && defaultsRes.ok) {\n const defs = await defaultsRes.json();\n if (!configRes || !configRes.ok) applyConfig(defs);\n }\n } catch (e) { /* use built-in defaults */ }\n\n // watch for webhook channel\n document.getElementById('hitl-channel').addEventListener('change', (e) => {\n document.getElementById('hitl-webhook-field').classList.toggle('hidden', e.target.value !== 'webhook');\n updatePreview();\n });\n\n // watch dlp toggle\n document.getElementById('dlp-enabled').addEventListener('change', (e) => {\n document.getElementById('dlp-options').classList.toggle('hidden', !e.target.checked);\n updatePreview();\n });\n});\n\n// ─── Apply Config ────────────────────────────────────────────────────\nfunction applyConfig(cfg) {\n if (!cfg) return;\n\n // Auth\n if (cfg.auth) {\n setChipValue('auth-provider', cfg.auth.provider || 'env');\n if (cfg.auth.env) {\n if (cfg.auth.env.user_var) document.getElementById('auth-user-var').value = cfg.auth.env.user_var;\n if (cfg.auth.env.role_var) document.getElementById('auth-role-var').value = cfg.auth.env.role_var;\n if (cfg.auth.env.org_unit_var) document.getElementById('auth-org-unit-var').value = cfg.auth.env.org_unit_var;\n }\n if (cfg.auth.local && cfg.auth.local.users_file) {\n document.getElementById('auth-users-file').value = cfg.auth.local.users_file;\n }\n }\n\n // HITL\n if (cfg.hitl) {\n if (cfg.hitl.default_mode) setChipValue('hitl-mode', cfg.hitl.default_mode);\n if (cfg.hitl.approval_channel) {\n document.getElementById('hitl-channel').value = cfg.hitl.approval_channel;\n document.getElementById('hitl-webhook-field').classList.toggle('hidden', cfg.hitl.approval_channel !== 'webhook');\n }\n if (cfg.hitl.timeout_seconds) document.getElementById('hitl-timeout').value = cfg.hitl.timeout_seconds;\n if (cfg.hitl.webhook && cfg.hitl.webhook.url) document.getElementById('hitl-webhook-url').value = cfg.hitl.webhook.url;\n }\n\n // DLP\n if (cfg.dlp) {\n document.getElementById('dlp-enabled').checked = cfg.dlp.enabled !== false;\n document.getElementById('dlp-options').classList.toggle('hidden', !cfg.dlp.enabled);\n if (cfg.dlp.mode) setChipValue('dlp-mode', cfg.dlp.mode);\n if (cfg.dlp.on_input) document.getElementById('dlp-on-input').value = cfg.dlp.on_input;\n if (cfg.dlp.on_output) document.getElementById('dlp-on-output').value = cfg.dlp.on_output;\n if (cfg.dlp.masking) {\n if (cfg.dlp.masking.strategy) document.getElementById('dlp-mask-strategy').value = cfg.dlp.masking.strategy;\n if (cfg.dlp.masking.show_chars != null) document.getElementById('dlp-mask-show').value = cfg.dlp.masking.show_chars;\n if (cfg.dlp.masking.placeholder) document.getElementById('dlp-mask-placeholder').value = cfg.dlp.masking.placeholder;\n }\n if (cfg.dlp.severity_threshold) setChipValue('dlp-severity', cfg.dlp.severity_threshold);\n if (cfg.dlp.built_in) {\n if (cfg.dlp.built_in.secrets != null) document.getElementById('dlp-secrets').checked = cfg.dlp.built_in.secrets;\n if (cfg.dlp.built_in.pii != null) document.getElementById('dlp-pii').checked = cfg.dlp.built_in.pii;\n }\n if (cfg.dlp.custom_patterns) {\n customPatterns = cfg.dlp.custom_patterns;\n renderCustomPatterns();\n }\n if (cfg.dlp.allowlist) {\n allowlistEntries = cfg.dlp.allowlist.map(e => e.pattern || e);\n renderAllowlist();\n }\n }\n\n // Audit\n if (cfg.audit && cfg.audit.sinks) {\n auditSinks = cfg.audit.sinks;\n renderAuditSinks();\n }\n\n updatePreview();\n}\n\n// ─── Roles ───────────────────────────────────────────────────────────\nfunction renderRoles() {\n const grid = document.getElementById('role-grid');\n grid.innerHTML = '';\n for (const [key, role] of Object.entries(PRESET_ROLES)) {\n const sel = selectedRoles[key];\n const card = document.createElement('div');\n card.className = 'role-card' + (sel ? ' selected' : '');\n card.dataset.role = key;\n card.onclick = () => { toggleRole(key); };\n card.innerHTML =\n '<div class=\"role-card-check\">&#10003;</div>' +\n '<div class=\"role-name\">' + role.label + '</div>' +\n '<div class=\"role-desc\">' + role.desc + '</div>' +\n '<div class=\"role-tags\">' +\n '<span class=\"role-tag\">' + role.execution_mode + '</span>' +\n '<span class=\"role-tag\">' + (role.token_budget_daily === -1 ? 'unlimited' : role.token_budget_daily.toLocaleString()) + ' budget</span>' +\n '</div>' +\n '<div class=\"role-details\">' +\n '<div class=\"field\"><label>Allowed Tools</label>' +\n '<input type=\"text\" value=\"' + role.allowed_tools.join(', ') + '\" onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'allowed_tools\\\\', this.value)\" onclick=\"event.stopPropagation()\">' +\n '</div>' +\n '<div class=\"field\"><label>Blocked Tools</label>' +\n '<input type=\"text\" value=\"' + role.blocked_tools.join(', ') + '\" onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'blocked_tools\\\\', this.value)\" onclick=\"event.stopPropagation()\">' +\n '</div>' +\n '<div class=\"field\"><label>Execution Mode</label>' +\n '<select onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'execution_mode\\\\', this.value)\" onclick=\"event.stopPropagation()\">' +\n '<option value=\"supervised\"' + (role.execution_mode === 'supervised' ? ' selected' : '') + '>Supervised</option>' +\n '<option value=\"autonomous\"' + (role.execution_mode === 'autonomous' ? ' selected' : '') + '>Autonomous</option>' +\n '<option value=\"dry_run\"' + (role.execution_mode === 'dry_run' ? ' selected' : '') + '>Dry Run</option>' +\n '</select>' +\n '</div>' +\n '<div class=\"field\"><label>Token Budget Daily</label>' +\n '<input type=\"number\" value=\"' + role.token_budget_daily + '\" onchange=\"updateRoleField(\\\\'' + key + '\\\\', \\\\'token_budget_daily\\\\', parseInt(this.value))\" onclick=\"event.stopPropagation()\">' +\n '</div>' +\n '</div>';\n grid.appendChild(card);\n }\n}\n\nfunction toggleRole(key) {\n selectedRoles[key] = !selectedRoles[key];\n renderRoles();\n updatePreview();\n}\n\nfunction updateRoleField(key, field, value) {\n if (field === 'allowed_tools' || field === 'blocked_tools') {\n PRESET_ROLES[key][field] = value.split(',').map(s => s.trim()).filter(Boolean);\n } else {\n PRESET_ROLES[key][field] = value;\n }\n updatePreview();\n}\n\n// ─── Section Toggle ──────────────────────────────────────────────────\nfunction toggleSection(id) {\n document.getElementById(id).classList.toggle('collapsed');\n}\n\n// ─── Chip Groups ─────────────────────────────────────────────────────\nfunction selectChip(el) {\n const group = el.parentElement;\n group.querySelectorAll('.chip').forEach(c => c.classList.remove('active'));\n el.classList.add('active');\n\n // Auth provider visibility\n if (group.id === 'auth-provider') {\n const val = el.dataset.value;\n document.getElementById('auth-env-fields').classList.toggle('hidden', val !== 'env');\n document.getElementById('auth-local-fields').classList.toggle('hidden', val !== 'local');\n }\n\n updatePreview();\n}\n\nfunction getChipValue(groupId) {\n const active = document.querySelector('#' + groupId + ' .chip.active');\n return active ? active.dataset.value : '';\n}\n\nfunction setChipValue(groupId, value) {\n const group = document.getElementById(groupId);\n if (!group) return;\n group.querySelectorAll('.chip').forEach(c => {\n c.classList.toggle('active', c.dataset.value === value);\n });\n}\n\n// ─── Custom Patterns ─────────────────────────────────────────────────\nfunction addCustomPattern() {\n customPatterns.push({ name: '', pattern: '', severity: 'medium', action: 'audit' });\n renderCustomPatterns();\n}\n\nfunction renderCustomPatterns() {\n const container = document.getElementById('dlp-custom-patterns');\n container.innerHTML = '';\n customPatterns.forEach((p, i) => {\n const div = document.createElement('div');\n div.className = 'pattern-item';\n div.innerHTML =\n '<input type=\"text\" placeholder=\"Name\" value=\"' + esc(p.name) + '\" onchange=\"customPatterns[' + i + '].name=this.value;updatePreview()\">' +\n '<input type=\"text\" placeholder=\"Regex pattern\" value=\"' + esc(p.pattern) + '\" onchange=\"customPatterns[' + i + '].pattern=this.value;updatePreview()\">' +\n '<select onchange=\"customPatterns[' + i + '].severity=this.value;updatePreview()\">' +\n '<option value=\"low\"' + (p.severity==='low'?' selected':'') + '>Low</option>' +\n '<option value=\"medium\"' + (p.severity==='medium'?' selected':'') + '>Medium</option>' +\n '<option value=\"high\"' + (p.severity==='high'?' selected':'') + '>High</option>' +\n '<option value=\"critical\"' + (p.severity==='critical'?' selected':'') + '>Critical</option>' +\n '</select>' +\n '<button class=\"btn-remove\" onclick=\"customPatterns.splice(' + i + ',1);renderCustomPatterns();updatePreview()\">&times;</button>';\n container.appendChild(div);\n });\n}\n\n// ─── Allowlist ───────────────────────────────────────────────────────\nfunction addAllowlistEntry() {\n allowlistEntries.push('');\n renderAllowlist();\n}\n\nfunction renderAllowlist() {\n const container = document.getElementById('dlp-allowlist');\n container.innerHTML = '';\n allowlistEntries.forEach((entry, i) => {\n const div = document.createElement('div');\n div.className = 'allowlist-item';\n div.innerHTML =\n '<input type=\"text\" placeholder=\"Pattern to allow\" value=\"' + esc(entry) + '\" onchange=\"allowlistEntries[' + i + ']=this.value;updatePreview()\">' +\n '<button class=\"btn-remove\" onclick=\"allowlistEntries.splice(' + i + ',1);renderAllowlist();updatePreview()\">&times;</button>';\n container.appendChild(div);\n });\n}\n\n// ─── Audit Sinks ─────────────────────────────────────────────────────\nfunction addAuditSink() {\n auditSinks.push({ type: 'jsonl', path: '' });\n renderAuditSinks();\n}\n\nfunction renderAuditSinks() {\n const container = document.getElementById('audit-sinks');\n container.innerHTML = '';\n auditSinks.forEach((sink, i) => {\n const div = document.createElement('div');\n div.className = 'sink-item';\n let inner = '<button class=\"btn-remove\" onclick=\"auditSinks.splice(' + i + ',1);renderAuditSinks();updatePreview()\">&times;</button>';\n inner += '<div class=\"field\"><label>Sink Type</label>' +\n '<select onchange=\"auditSinks[' + i + '].type=this.value;renderAuditSinks();updatePreview()\">' +\n '<option value=\"jsonl\"' + (sink.type==='jsonl'?' selected':'') + '>JSONL File</option>' +\n '<option value=\"webhook\"' + (sink.type==='webhook'?' selected':'') + '>Webhook</option>' +\n '<option value=\"postgres\"' + (sink.type==='postgres'?' selected':'') + '>PostgreSQL</option>' +\n '</select></div>';\n if (sink.type === 'jsonl') {\n inner += '<div class=\"field\"><label>File Path</label>' +\n '<input type=\"text\" value=\"' + esc(sink.path || '') + '\" placeholder=\"~/.pi/agent/audit.jsonl\" ' +\n 'onchange=\"auditSinks[' + i + '].path=this.value;updatePreview()\"></div>';\n } else if (sink.type === 'webhook') {\n inner += '<div class=\"field\"><label>Webhook URL</label>' +\n '<input type=\"text\" value=\"' + esc(sink.url || '') + '\" placeholder=\"https://...\" ' +\n 'onchange=\"auditSinks[' + i + '].url=this.value;updatePreview()\"></div>';\n } else if (sink.type === 'postgres') {\n inner += '<div class=\"field\"><label>Connection String</label>' +\n '<input type=\"text\" value=\"' + esc(sink.connection || '') + '\" placeholder=\"postgresql://...\" ' +\n 'onchange=\"auditSinks[' + i + '].connection=this.value;updatePreview()\"></div>';\n }\n div.innerHTML = inner;\n container.appendChild(div);\n });\n}\n\n// ─── Preview Tabs ────────────────────────────────────────────────────\nfunction switchTab(el) {\n document.querySelectorAll('.preview-tab').forEach(t => t.classList.remove('active'));\n el.classList.add('active');\n activePreviewTab = el.dataset.tab;\n updatePreview();\n}\n\n// ─── YAML Generator ──────────────────────────────────────────────────\nfunction toYaml(obj, indent) {\n indent = indent || 0;\n const pad = ' '.repeat(indent);\n let out = '';\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return ' []\\\\n';\n for (const item of obj) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const keys = Object.keys(item);\n if (keys.length > 0) {\n out += pad + '- ' + keys[0] + ': ' + formatScalar(item[keys[0]]) + '\\\\n';\n for (let k = 1; k < keys.length; k++) {\n const val = item[keys[k]];\n if (typeof val === 'object' && val !== null) {\n out += pad + ' ' + keys[k] + ':\\\\n' + toYaml(val, indent + 2);\n } else {\n out += pad + ' ' + keys[k] + ': ' + formatScalar(val) + '\\\\n';\n }\n }\n }\n } else {\n out += pad + '- ' + formatScalar(item) + '\\\\n';\n }\n }\n return out;\n }\n\n if (typeof obj === 'object' && obj !== null) {\n for (const [key, val] of Object.entries(obj)) {\n if (val === undefined || val === null) continue;\n if (typeof val === 'object') {\n const yamlVal = toYaml(val, indent + 1);\n if (Array.isArray(val) && val.length === 0) {\n out += pad + key + ': []\\\\n';\n } else {\n out += pad + key + ':\\\\n' + yamlVal;\n }\n } else {\n out += pad + key + ': ' + formatScalar(val) + '\\\\n';\n }\n }\n return out;\n }\n\n return pad + formatScalar(obj) + '\\\\n';\n}\n\nfunction formatScalar(val) {\n if (typeof val === 'boolean') return val ? 'true' : 'false';\n if (typeof val === 'number') return String(val);\n if (typeof val === 'string') {\n if (val === '') return \"''\";\n if (val === 'true' || val === 'false' || !isNaN(val)) return \"'\" + val + \"'\";\n if (/[:#{}\\\\[\\\\],&*?|\\\\->!%@]/.test(val) || val.includes('\\\\\\\\')) return \"'\" + val.replace(/'/g, \"''\") + \"'\";\n return val;\n }\n return String(val);\n}\n\n// ─── Build Config Objects ────────────────────────────────────────────\nfunction buildGovernanceConfig() {\n const cfg = {};\n\n // Auth\n const authProvider = getChipValue('auth-provider');\n cfg.auth = { provider: authProvider };\n if (authProvider === 'env') {\n cfg.auth.env = {\n user_var: document.getElementById('auth-user-var').value || 'PI_GOV_USER',\n role_var: document.getElementById('auth-role-var').value || 'PI_GOV_ROLE',\n org_unit_var: document.getElementById('auth-org-unit-var').value || 'PI_GOV_ORG_UNIT'\n };\n } else if (authProvider === 'local') {\n cfg.auth.local = {\n users_file: document.getElementById('auth-users-file').value || './users.yaml'\n };\n }\n\n // Policy\n cfg.policy = {\n engine: 'yaml',\n yaml: { rules_file: './governance-rules.yaml' }\n };\n\n // HITL\n cfg.hitl = {\n default_mode: getChipValue('hitl-mode') || 'supervised',\n approval_channel: document.getElementById('hitl-channel').value,\n timeout_seconds: parseInt(document.getElementById('hitl-timeout').value) || 300\n };\n if (cfg.hitl.approval_channel === 'webhook') {\n const url = document.getElementById('hitl-webhook-url').value;\n if (url) cfg.hitl.webhook = { url: url };\n }\n\n // Audit\n cfg.audit = { sinks: auditSinks.filter(s => {\n if (s.type === 'jsonl') return s.path;\n if (s.type === 'webhook') return s.url;\n if (s.type === 'postgres') return s.connection;\n return false;\n }).map(s => {\n if (s.type === 'jsonl') return { type: 'jsonl', path: s.path };\n if (s.type === 'webhook') return { type: 'webhook', url: s.url };\n if (s.type === 'postgres') return { type: 'postgres', connection: s.connection };\n return s;\n })};\n\n // DLP\n if (document.getElementById('dlp-enabled').checked) {\n cfg.dlp = {\n enabled: true,\n mode: getChipValue('dlp-mode') || 'audit'\n };\n const onInput = document.getElementById('dlp-on-input').value;\n const onOutput = document.getElementById('dlp-on-output').value;\n if (onInput) cfg.dlp.on_input = onInput;\n if (onOutput) cfg.dlp.on_output = onOutput;\n cfg.dlp.masking = {\n strategy: document.getElementById('dlp-mask-strategy').value,\n show_chars: parseInt(document.getElementById('dlp-mask-show').value) || 4,\n placeholder: document.getElementById('dlp-mask-placeholder').value || '***'\n };\n cfg.dlp.severity_threshold = getChipValue('dlp-severity') || 'low';\n cfg.dlp.built_in = {\n secrets: document.getElementById('dlp-secrets').checked,\n pii: document.getElementById('dlp-pii').checked\n };\n const patterns = customPatterns.filter(p => p.name && p.pattern);\n if (patterns.length > 0) cfg.dlp.custom_patterns = patterns;\n const al = allowlistEntries.filter(Boolean);\n if (al.length > 0) cfg.dlp.allowlist = al.map(p => ({ pattern: p }));\n } else {\n cfg.dlp = { enabled: false };\n }\n\n return cfg;\n}\n\nfunction buildRulesConfig() {\n const roles = {};\n for (const [key, sel] of Object.entries(selectedRoles)) {\n if (!sel) continue;\n const r = PRESET_ROLES[key];\n const role = {\n allowed_tools: r.allowed_tools,\n blocked_tools: r.blocked_tools,\n prompt_template: r.prompt_template,\n execution_mode: r.execution_mode,\n human_approval: r.human_approval,\n token_budget_daily: r.token_budget_daily,\n allowed_paths: r.allowed_paths,\n blocked_paths: r.blocked_paths\n };\n if (r.bash_overrides) role.bash_overrides = r.bash_overrides;\n roles[key] = role;\n }\n return { roles: roles };\n}\n\n// ─── Update Preview ──────────────────────────────────────────────────\nfunction updatePreview() {\n const el = document.getElementById('preview-yaml');\n if (activePreviewTab === 'governance') {\n const cfg = buildGovernanceConfig();\n el.textContent = '# governance.yaml\\\\n# Generated by Pi Governance Setup Wizard\\\\n\\\\n' + toYaml(cfg);\n } else {\n const rules = buildRulesConfig();\n el.textContent = '# governance-rules.yaml\\\\n# Generated by Pi Governance Setup Wizard\\\\n\\\\n' + toYaml(rules);\n }\n}\n\n// ─── Save ────────────────────────────────────────────────────────────\nasync function handleSave() {\n const btn = document.getElementById('btn-save');\n const status = document.getElementById('save-status');\n btn.disabled = true;\n status.textContent = 'Saving...';\n status.className = 'save-status';\n\n try {\n const payload = {\n governance: buildGovernanceConfig(),\n rules: buildRulesConfig()\n };\n const res = await fetch('/api/save', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload)\n });\n if (!res.ok) {\n const err = await res.text();\n throw new Error(err || 'Server error');\n }\n const result = await res.json();\n showToast('Configuration saved!', 'success');\n status.textContent = 'Saved: ' + (result.files || []).join(', ');\n status.className = 'save-status success';\n } catch (e) {\n showToast('Failed to save: ' + e.message, 'error');\n status.textContent = 'Error: ' + e.message;\n status.className = 'save-status error';\n } finally {\n btn.disabled = false;\n }\n}\n\nasync function handleClose() {\n try { await fetch('/api/close', { method: 'POST' }); } catch (e) { /* ignore */ }\n window.close();\n}\n\n// ─── Toast ───────────────────────────────────────────────────────────\nfunction showToast(msg, type) {\n const toast = document.getElementById('toast');\n toast.textContent = msg;\n toast.className = 'toast ' + type + ' visible';\n setTimeout(() => { toast.classList.remove('visible'); }, 3000);\n}\n\n// ─── Util ────────────────────────────────────────────────────────────\nfunction esc(s) {\n return String(s).replace(/&/g,'&amp;').replace(/\"/g,'&quot;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n}\n</script>\n</body>\n</html>`;\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { writeFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { stringify } from 'yaml';\nimport type { GovernanceConfig } from '../config/schema.js';\nimport { DEFAULTS } from '../config/defaults.js';\nimport { WIZARD_HTML } from './html.js';\n\nexport interface WizardServerOptions {\n workingDirectory: string;\n existingConfig?: GovernanceConfig;\n onComplete: (files: { path: string; content: string }[]) => void;\n onError: (error: Error) => void;\n}\n\nconst AUTO_SHUTDOWN_MS = 10 * 60 * 1000;\n\nconst BUILTIN_ROLES = {\n analyst: {\n allowed_tools: ['read', 'grep', 'find', 'ls'],\n blocked_tools: ['bash', 'write', 'edit'],\n hitl_mode: 'dry_run' as const,\n },\n project_lead: {\n allowed_tools: ['read', 'write', 'edit', 'grep', 'find', 'ls', 'bash'],\n blocked_tools: [],\n hitl_mode: 'supervised' as const,\n },\n admin: {\n allowed_tools: ['read', 'write', 'edit', 'grep', 'find', 'ls', 'bash'],\n blocked_tools: [],\n hitl_mode: 'autonomous' as const,\n },\n auditor: {\n allowed_tools: ['read', 'grep', 'find', 'ls'],\n blocked_tools: ['bash', 'write', 'edit'],\n hitl_mode: 'dry_run' as const,\n },\n};\n\nfunction setCorsHeaders(res: ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', 'http://localhost');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n}\n\nfunction sendJson(res: ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n\nexport function startWizardServer(\n options: WizardServerOptions,\n): Promise<{ port: number; close: () => void }> {\n return new Promise((resolve, reject) => {\n let shutdownTimer: ReturnType<typeof setTimeout> | undefined;\n\n const server = createServer((req, res) => {\n setCorsHeaders(res);\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const url = req.url ?? '/';\n\n try {\n if (req.method === 'GET' && url === '/') {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(WIZARD_HTML);\n return;\n }\n\n if (req.method === 'GET' && url === '/api/config') {\n sendJson(res, 200, options.existingConfig ?? DEFAULTS);\n return;\n }\n\n if (req.method === 'GET' && url === '/api/defaults') {\n sendJson(res, 200, { defaults: DEFAULTS, roles: BUILTIN_ROLES });\n return;\n }\n\n if (req.method === 'POST' && url === '/api/save') {\n readBody(req)\n .then((body) => {\n const parsed: unknown = JSON.parse(body);\n if (typeof parsed !== 'object' || parsed === null || !('governance' in parsed)) {\n sendJson(res, 400, { error: 'Request body must include \"governance\" property' });\n return;\n }\n\n const payload = parsed as { governance: GovernanceConfig; rules?: unknown };\n const governanceYaml = stringify(payload.governance);\n const piDir = join(options.workingDirectory, '.pi');\n const governancePath = join(piDir, 'governance.yaml');\n\n mkdirSync(piDir, { recursive: true });\n writeFileSync(governancePath, governanceYaml, 'utf-8');\n\n const files: { path: string; content: string }[] = [\n { path: governancePath, content: governanceYaml },\n ];\n\n if (payload.rules !== undefined) {\n const rulesYaml = stringify(payload.rules);\n const rulesPath = join(options.workingDirectory, 'governance-rules.yaml');\n writeFileSync(rulesPath, rulesYaml, 'utf-8');\n files.push({ path: rulesPath, content: rulesYaml });\n }\n\n sendJson(res, 200, { ok: true, files: files.map((f) => f.path) });\n options.onComplete(files);\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n sendJson(res, 400, { error: `Invalid request body: ${message}` });\n });\n return;\n }\n\n if (req.method === 'POST' && url === '/api/close') {\n sendJson(res, 200, { ok: true });\n setTimeout(() => {\n closeServer();\n }, 100);\n return;\n }\n\n sendJson(res, 404, { error: 'Not found' });\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n options.onError(error);\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n\n function closeServer(): void {\n if (shutdownTimer !== undefined) {\n clearTimeout(shutdownTimer);\n shutdownTimer = undefined;\n }\n server.close();\n }\n\n server.on('error', (err) => {\n options.onError(err);\n reject(err);\n });\n\n server.listen(0, () => {\n const addr = server.address();\n if (addr === null || typeof addr === 'string') {\n const err = new Error('Failed to get server address');\n options.onError(err);\n reject(err);\n return;\n }\n\n shutdownTimer = setTimeout(() => {\n closeServer();\n }, AUTO_SHUTDOWN_MS);\n\n resolve({ port: addr.port, close: closeServer });\n });\n });\n}\n","export { startWizardServer } from './server.js';\nexport type { WizardServerOptions } from './server.js';\n","// 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 { resolve } from 'node:path';\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 let protectedPaths: Set<string> = new Set();\n\n const stats = {\n configTampered: 0,\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 // 1b. Compute protected config paths (hardcoded — cannot be overridden)\n const paths = new Set<string>();\n if (loaded.source !== 'built-in') {\n paths.add(resolve(loaded.source));\n }\n const rulesFileCfg = config.policy?.yaml?.rules_file ?? './governance-rules.yaml';\n paths.add(resolve(rulesFileCfg));\n // Fallback well-known paths\n paths.add(resolve(ctx.workingDirectory, '.pi/governance.yaml'));\n paths.add(resolve(ctx.workingDirectory, 'governance-rules.yaml'));\n protectedPaths = paths;\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 // Only warn if the user explicitly configured a rules file path\n if (config.policy?.yaml?.rules_file) {\n ctx.ui.notify(`Rules file not found: ${rulesFile} — using built-in defaults`, 'warning');\n }\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 if (!audit || !policyEngine || !identity) return undefined;\n\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 // 0. Hardcoded config self-protection — cannot be bypassed by policy\n if (WRITE_TOOLS.has(toolName)) {\n const filePath = extractPath(toolName, input);\n if (filePath && protectedPaths.has(resolve(filePath))) {\n stats.configTampered++;\n await audit.log({\n ...baseRecord,\n event: 'config_tampered',\n decision: 'denied',\n reason: `Config self-protection: write to governance file blocked (${filePath})`,\n });\n return {\n block: true,\n reason: `Governance config files are protected and cannot be modified by agents`,\n };\n }\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 if (!audit || !identity) return;\n\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 if (!audit) return;\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: budgetTracker\n ? { used: budgetTracker.used(), remaining: budgetTracker.remaining() }\n : undefined,\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 ` Config tampered: ${stats.configTampered}`,\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 if (subcommand === 'init') {\n const { startWizardServer } = await import('../lib/wizard/index.js');\n\n ctx.ui.notify('Starting governance configuration wizard...', 'info');\n\n const { port, close } = await startWizardServer({\n workingDirectory: ctx.workingDirectory,\n existingConfig: config,\n onComplete: (files) => {\n const names = files.map((f) => f.path).join(', ');\n ctx.ui.notify(`Configuration saved: ${names}`, 'info');\n close();\n },\n onError: (err) => {\n ctx.ui.notify(`Wizard error: ${err.message}`, 'error');\n close();\n },\n });\n\n const url = `http://localhost:${port}`;\n const { exec } = await import('node:child_process');\n const openCmd =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${openCmd} ${url}`);\n\n ctx.ui.notify(`Wizard running at ${url}`, 'info');\n } else {\n ctx.ui.notify('Usage: /governance status | init', '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['PI_GOV_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: 'PI_GOV_USER' }),\n role_var: Type.String({ default: 'PI_GOV_ROLE' }),\n org_unit_var: Type.String({ default: 'PI_GOV_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 { IdentityProvider, ResolvedIdentity } from './provider.js';\n\nexport class EnvIdentityProvider implements IdentityProvider {\n name = 'env';\n\n constructor(\n private userVar: string = 'PI_GOV_USER',\n private roleVar: string = 'PI_GOV_ROLE',\n private orgUnitVar: string = 'PI_GOV_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 // Governance config tampering — shell-based writes to governance files\n /(cat|echo|printf)\\s.*>\\s*.*governance(-rules)?\\.yaml/,\n /\\btee\\s+.*governance(-rules)?\\.yaml/,\n /sed\\s+-i.*governance(-rules)?\\.yaml/,\n /(cp|mv|rm)\\s.*governance(-rules)?\\.yaml/,\n /(cat|echo|printf)\\s.*>\\s*.*\\.pi\\/governance/,\n /\\btee\\s+.*\\.pi\\/governance/,\n /sed\\s+-i.*\\.pi\\/governance/,\n /(cp|mv|rm)\\s.*\\.pi\\/governance/,\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,IAEa;AAFb;AAAA;AAAA;AAEO,IAAM,WAA6B;AAAA,MACxC,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,KAAK;AAAA,UACH,UAAU;AAAA,UACV,UAAU;AAAA,UACV,cAAc;AAAA,QAChB;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,UACJ,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AAAA,MACA,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,iBAAiB;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,QACL,OAAO,CAAC,EAAE,MAAM,SAAS,MAAM,0BAA0B,CAAC;AAAA,MAC5D;AAAA,MACA,KAAK;AAAA,QACH,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,UACP,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,aAAa;AAAA,QACf;AAAA,QACA,oBAAoB;AAAA,QACpB,UAAU;AAAA,UACR,SAAS;AAAA,UACT,KAAK;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC7CA,IAAa;AAAb;AAAA;AAAA;AAAO,IAAM,cAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["resolve","existsSync","readFileSync","parseYaml","readFileSync","parseYaml","readFileSync","parseYaml","Value","readFileSync","parseYaml","Value","existsSync","startWizardServer"]}