@provos/ironcurtain 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -19
- package/dist/cli-help.d.ts +12 -0
- package/dist/cli-help.js +21 -0
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.js +14 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/agent-model-guard.d.ts +14 -0
- package/dist/config/agent-model-guard.js +24 -0
- package/dist/config/agent-model-guard.js.map +1 -0
- package/dist/config/config-command.d.ts +33 -1
- package/dist/config/config-command.js +723 -11
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/first-start.js +2 -8
- package/dist/config/first-start.js.map +1 -1
- package/dist/config/model-provider.d.ts +9 -0
- package/dist/config/model-provider.js +13 -0
- package/dist/config/model-provider.js.map +1 -1
- package/dist/config/openrouter-catalog.d.ts +46 -0
- package/dist/config/openrouter-catalog.js +111 -0
- package/dist/config/openrouter-catalog.js.map +1 -0
- package/dist/config/openrouter-models-fallback.d.ts +15 -0
- package/dist/config/openrouter-models-fallback.js +49 -0
- package/dist/config/openrouter-models-fallback.js.map +1 -0
- package/dist/config/paths.d.ts +48 -6
- package/dist/config/paths.js +63 -8
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +8 -0
- package/dist/config/user-config.d.ts +179 -6
- package/dist/config/user-config.js +282 -5
- package/dist/config/user-config.js.map +1 -1
- package/dist/daemon/daemon-command.js +14 -5
- package/dist/daemon/daemon-command.js.map +1 -1
- package/dist/daemon/ironcurtain-daemon.d.ts +18 -0
- package/dist/daemon/ironcurtain-daemon.js +28 -1
- package/dist/daemon/ironcurtain-daemon.js.map +1 -1
- package/dist/daemon-client/daemon-client.d.ts +123 -0
- package/dist/daemon-client/daemon-client.js +324 -0
- package/dist/daemon-client/daemon-client.js.map +1 -0
- package/dist/docker/adapters/claude-code.js +109 -1
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/adapters/codex.d.ts +18 -0
- package/dist/docker/adapters/codex.js +376 -0
- package/dist/docker/adapters/codex.js.map +1 -0
- package/dist/docker/adapters/goose.js +38 -2
- package/dist/docker/adapters/goose.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +34 -6
- package/dist/docker/agent-adapter.js +2 -0
- package/dist/docker/agent-adapter.js.map +1 -1
- package/dist/docker/agent-registry.js +5 -0
- package/dist/docker/agent-registry.js.map +1 -1
- package/dist/docker/apple-container-manager.d.ts +49 -0
- package/dist/docker/apple-container-manager.js +486 -0
- package/dist/docker/apple-container-manager.js.map +1 -0
- package/dist/docker/ca.js +9 -2
- package/dist/docker/ca.js.map +1 -1
- package/dist/docker/code-mode-proxy.d.ts +11 -0
- package/dist/docker/code-mode-proxy.js +3 -1
- package/dist/docker/code-mode-proxy.js.map +1 -1
- package/dist/docker/container-lifecycle.d.ts +2 -2
- package/dist/docker/container-lifecycle.js +9 -0
- package/dist/docker/container-lifecycle.js.map +1 -1
- package/dist/docker/container-runtime.d.ts +29 -0
- package/dist/docker/container-runtime.js +76 -0
- package/dist/docker/container-runtime.js.map +1 -0
- package/dist/docker/docker-agent-session.d.ts +31 -0
- package/dist/docker/docker-agent-session.js +97 -7
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +232 -15
- package/dist/docker/docker-infrastructure.js +762 -118
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +25 -5
- package/dist/docker/docker-manager.js +388 -21
- package/dist/docker/docker-manager.js.map +1 -1
- package/dist/docker/docker-probe.d.ts +45 -0
- package/dist/docker/docker-probe.js +86 -0
- package/dist/docker/docker-probe.js.map +1 -0
- package/dist/docker/docker-progress-sink.d.ts +1 -1
- package/dist/docker/docker-resource-lifecycle.d.ts +71 -0
- package/dist/docker/docker-resource-lifecycle.js +454 -0
- package/dist/docker/docker-resource-lifecycle.js.map +1 -0
- package/dist/docker/gc-command.d.ts +2 -0
- package/dist/docker/gc-command.js +37 -0
- package/dist/docker/gc-command.js.map +1 -0
- package/dist/docker/mitm-proxy.d.ts +58 -5
- package/dist/docker/mitm-proxy.js +338 -26
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/network-topology.d.ts +88 -0
- package/dist/docker/network-topology.js +167 -0
- package/dist/docker/network-topology.js.map +1 -0
- package/dist/docker/oauth-credentials.d.ts +13 -0
- package/dist/docker/oauth-credentials.js +125 -0
- package/dist/docker/oauth-credentials.js.map +1 -1
- package/dist/docker/openrouter.d.ts +107 -0
- package/dist/docker/openrouter.js +236 -0
- package/dist/docker/openrouter.js.map +1 -0
- package/dist/docker/orientation.js +1 -1
- package/dist/docker/orientation.js.map +1 -1
- package/dist/docker/package-types.d.ts +1 -1
- package/dist/docker/platform.d.ts +3 -1
- package/dist/docker/platform.js +3 -1
- package/dist/docker/platform.js.map +1 -1
- package/dist/docker/provider-config.d.ts +35 -1
- package/dist/docker/provider-config.js +93 -3
- package/dist/docker/provider-config.js.map +1 -1
- package/dist/docker/provision-lock.d.ts +46 -0
- package/dist/docker/provision-lock.js +152 -0
- package/dist/docker/provision-lock.js.map +1 -0
- package/dist/docker/pty-session.d.ts +22 -0
- package/dist/docker/pty-session.js +238 -84
- package/dist/docker/pty-session.js.map +1 -1
- package/dist/docker/pty-types.d.ts +15 -0
- package/dist/docker/pty-types.js +8 -0
- package/dist/docker/pty-types.js.map +1 -1
- package/dist/docker/registry-proxy.d.ts +46 -0
- package/dist/docker/registry-proxy.js +255 -1
- package/dist/docker/registry-proxy.js.map +1 -1
- package/dist/docker/resource-limits.d.ts +14 -5
- package/dist/docker/resource-limits.js +11 -8
- package/dist/docker/resource-limits.js.map +1 -1
- package/dist/docker/sse-extractor.js +55 -5
- package/dist/docker/sse-extractor.js.map +1 -1
- package/dist/docker/stream-delay.d.ts +86 -0
- package/dist/docker/stream-delay.js +218 -0
- package/dist/docker/stream-delay.js.map +1 -0
- package/dist/docker/token-stream-types.d.ts +15 -0
- package/dist/docker/trajectory-capture.d.ts +79 -0
- package/dist/docker/trajectory-capture.js +521 -0
- package/dist/docker/trajectory-capture.js.map +1 -0
- package/dist/docker/trajectory-reassembler.d.ts +286 -0
- package/dist/docker/trajectory-reassembler.js +1010 -0
- package/dist/docker/trajectory-reassembler.js.map +1 -0
- package/dist/docker/trajectory-tap.d.ts +100 -0
- package/dist/docker/trajectory-tap.js +410 -0
- package/dist/docker/trajectory-tap.js.map +1 -0
- package/dist/docker/trajectory-types.d.ts +187 -0
- package/dist/docker/trajectory-types.js +43 -0
- package/dist/docker/trajectory-types.js.map +1 -0
- package/dist/docker/types.d.ts +116 -12
- package/dist/doctor/checks.d.ts +39 -6
- package/dist/doctor/checks.js +129 -25
- package/dist/doctor/checks.js.map +1 -1
- package/dist/doctor/doctor-command.js +39 -9
- package/dist/doctor/doctor-command.js.map +1 -1
- package/dist/doctor/mcp-liveness.d.ts +1 -1
- package/dist/doctor/mcp-liveness.js +12 -4
- package/dist/doctor/mcp-liveness.js.map +1 -1
- package/dist/escalation/escalation-watcher.js +6 -0
- package/dist/escalation/escalation-watcher.js.map +1 -1
- package/dist/{mux → escalation}/trusted-input.d.ts +7 -4
- package/dist/{mux → escalation}/trusted-input.js +8 -5
- package/dist/escalation/trusted-input.js.map +1 -0
- package/dist/hash.js.map +1 -1
- package/dist/index.js +65 -16
- package/dist/index.js.map +1 -1
- package/dist/mux/mux-app.d.ts +9 -0
- package/dist/mux/mux-app.js +18 -16
- package/dist/mux/mux-app.js.map +1 -1
- package/dist/mux/mux-command.js +26 -8
- package/dist/mux/mux-command.js.map +1 -1
- package/dist/mux/mux-input-handler.d.ts +26 -2
- package/dist/mux/mux-input-handler.js +93 -11
- package/dist/mux/mux-input-handler.js.map +1 -1
- package/dist/mux/mux-renderer.d.ts +2 -1
- package/dist/mux/mux-renderer.js +67 -0
- package/dist/mux/mux-renderer.js.map +1 -1
- package/dist/mux/provider-profile-snapshot.d.ts +44 -0
- package/dist/mux/provider-profile-snapshot.js +56 -0
- package/dist/mux/provider-profile-snapshot.js.map +1 -0
- package/dist/mux/types.d.ts +3 -2
- package/dist/mux/types.js +6 -2
- package/dist/mux/types.js.map +1 -1
- package/dist/observe/observe-command.js +112 -125
- package/dist/observe/observe-command.js.map +1 -1
- package/dist/persona/broad-policy-validator.d.ts +95 -0
- package/dist/persona/broad-policy-validator.js +171 -0
- package/dist/persona/broad-policy-validator.js.map +1 -0
- package/dist/persona/compile-persona-policy.d.ts +54 -2
- package/dist/persona/compile-persona-policy.js +29 -4
- package/dist/persona/compile-persona-policy.js.map +1 -1
- package/dist/persona/event-bus-progress-reporter.d.ts +57 -0
- package/dist/persona/event-bus-progress-reporter.js +66 -0
- package/dist/persona/event-bus-progress-reporter.js.map +1 -0
- package/dist/persona/persona-command.js +46 -76
- package/dist/persona/persona-command.js.map +1 -1
- package/dist/persona/persona-compile-orchestrator.d.ts +101 -0
- package/dist/persona/persona-compile-orchestrator.js +504 -0
- package/dist/persona/persona-compile-orchestrator.js.map +1 -0
- package/dist/persona/persona-service.d.ts +137 -0
- package/dist/persona/persona-service.js +263 -0
- package/dist/persona/persona-service.js.map +1 -0
- package/dist/persona/policy-mutation-audit.d.ts +109 -0
- package/dist/persona/policy-mutation-audit.js +179 -0
- package/dist/persona/policy-mutation-audit.js.map +1 -0
- package/dist/persona/rule-delta.d.ts +30 -0
- package/dist/persona/rule-delta.js +82 -0
- package/dist/persona/rule-delta.js.map +1 -0
- package/dist/persona/types.d.ts +12 -0
- package/dist/pipeline/annotate.js +10 -2
- package/dist/pipeline/annotate.js.map +1 -1
- package/dist/pipeline/compile.js +14 -2
- package/dist/pipeline/compile.js.map +1 -1
- package/dist/pipeline/constitution-compiler.js.map +1 -1
- package/dist/pipeline/generate-with-repair.js.map +1 -1
- package/dist/pipeline/pipeline-runner.d.ts +63 -4
- package/dist/pipeline/pipeline-runner.js +159 -50
- package/dist/pipeline/pipeline-runner.js.map +1 -1
- package/dist/pipeline/pipeline-shared.d.ts +32 -3
- package/dist/pipeline/pipeline-shared.js +76 -8
- package/dist/pipeline/pipeline-shared.js.map +1 -1
- package/dist/pipeline/refresh-lists.js +3 -5
- package/dist/pipeline/refresh-lists.js.map +1 -1
- package/dist/pipeline/scenario-schema-validator.js.map +1 -1
- package/dist/{mux → pty}/pty-bridge.d.ts +41 -3
- package/dist/{mux → pty}/pty-bridge.js +71 -18
- package/dist/pty/pty-bridge.js.map +1 -0
- package/dist/pty/resolve-ironcurtain-bin.d.ts +17 -0
- package/dist/pty/resolve-ironcurtain-bin.js +22 -0
- package/dist/pty/resolve-ironcurtain-bin.js.map +1 -0
- package/dist/sandbox/index.d.ts +19 -4
- package/dist/sandbox/index.js +31 -18
- package/dist/sandbox/index.js.map +1 -1
- package/dist/servers/fetch-server.js +2 -0
- package/dist/servers/fetch-server.js.map +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +20 -2
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +20 -35
- package/dist/session/preflight.js +92 -109
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/resource-budget-tracker.js +8 -0
- package/dist/session/resource-budget-tracker.js.map +1 -1
- package/dist/session/session-manager.d.ts +7 -0
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/types.d.ts +23 -0
- package/dist/signal/bot-command.js +6 -1
- package/dist/signal/bot-command.js.map +1 -1
- package/dist/signal/setup-signal.js +1 -1
- package/dist/signal/setup-signal.js.map +1 -1
- package/dist/signal/signal-bot-daemon.d.ts +1 -0
- package/dist/signal/signal-bot-daemon.js +9 -2
- package/dist/signal/signal-bot-daemon.js.map +1 -1
- package/dist/signal/signal-container.d.ts +3 -3
- package/dist/signal/signal-container.js +2 -2
- package/dist/signal/signal-container.js.map +1 -1
- package/dist/trusted-process/call-circuit-breaker.d.ts +6 -0
- package/dist/trusted-process/call-circuit-breaker.js +22 -3
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -1
- package/dist/trusted-process/container-command.d.ts +35 -0
- package/dist/trusted-process/container-command.js +49 -0
- package/dist/trusted-process/container-command.js.map +1 -0
- package/dist/trusted-process/mcp-error-utils.js +4 -1
- package/dist/trusted-process/mcp-error-utils.js.map +1 -1
- package/dist/trusted-process/mcp-proxy-server.js +37 -3
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/policy-engine.js +13 -2
- package/dist/trusted-process/policy-engine.js.map +1 -1
- package/dist/trusted-process/tcp-server-transport.d.ts +19 -1
- package/dist/trusted-process/tcp-server-transport.js +56 -10
- package/dist/trusted-process/tcp-server-transport.js.map +1 -1
- package/dist/trusted-process/tool-call-coordinator.d.ts +22 -8
- package/dist/trusted-process/tool-call-coordinator.js +149 -65
- package/dist/trusted-process/tool-call-coordinator.js.map +1 -1
- package/dist/trusted-process/tool-call-pipeline.d.ts +8 -0
- package/dist/trusted-process/tool-call-pipeline.js +68 -34
- package/dist/trusted-process/tool-call-pipeline.js.map +1 -1
- package/dist/util/atomic-write.d.ts +31 -0
- package/dist/util/atomic-write.js +43 -0
- package/dist/util/atomic-write.js.map +1 -0
- package/dist/utils/preflight-checks.js +1 -3
- package/dist/utils/preflight-checks.js.map +1 -1
- package/dist/utils/stdio-guard.d.ts +1 -0
- package/dist/utils/stdio-guard.js +27 -0
- package/dist/utils/stdio-guard.js.map +1 -0
- package/dist/web-ui/__tests__/config-dispatch.test.d.ts +13 -0
- package/dist/web-ui/__tests__/config-dispatch.test.js +383 -0
- package/dist/web-ui/__tests__/config-dispatch.test.js.map +1 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js +6 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js.map +1 -1
- package/dist/web-ui/conn-registry.d.ts +14 -0
- package/dist/web-ui/conn-registry.js +25 -0
- package/dist/web-ui/conn-registry.js.map +1 -0
- package/dist/web-ui/dispatch/config-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/config-dispatch.js +277 -0
- package/dist/web-ui/dispatch/config-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/escalation-dispatch.js +11 -2
- package/dist/web-ui/dispatch/escalation-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/persona-dispatch.d.ts +46 -2
- package/dist/web-ui/dispatch/persona-dispatch.js +209 -56
- package/dist/web-ui/dispatch/persona-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/pty-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/pty-dispatch.js +66 -0
- package/dist/web-ui/dispatch/pty-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/session-dispatch.js +89 -6
- package/dist/web-ui/dispatch/session-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/types.d.ts +35 -0
- package/dist/web-ui/dispatch/types.js +42 -1
- package/dist/web-ui/dispatch/types.js.map +1 -1
- package/dist/web-ui/dispatch/workflow-dispatch.js +116 -5
- package/dist/web-ui/dispatch/workflow-dispatch.js.map +1 -1
- package/dist/web-ui/json-rpc-dispatch.js +4 -1
- package/dist/web-ui/json-rpc-dispatch.js.map +1 -1
- package/dist/web-ui/pty-session-manager.d.ts +234 -0
- package/dist/web-ui/pty-session-manager.js +599 -0
- package/dist/web-ui/pty-session-manager.js.map +1 -0
- package/dist/web-ui/web-event-bus.d.ts +34 -1
- package/dist/web-ui/web-event-bus.js.map +1 -1
- package/dist/web-ui/web-session-transport.js.map +1 -1
- package/dist/web-ui/web-ui-server.d.ts +22 -0
- package/dist/web-ui/web-ui-server.js +41 -0
- package/dist/web-ui/web-ui-server.js.map +1 -1
- package/dist/web-ui/web-ui-types.d.ts +212 -5
- package/dist/web-ui/web-ui-types.js.map +1 -1
- package/dist/web-ui-static/assets/index-CCVI4nEK.css +1 -0
- package/dist/web-ui-static/assets/index-Dm012gvY.js +114 -0
- package/dist/web-ui-static/index.html +2 -2
- package/dist/workflow/cli-shared.d.ts +62 -0
- package/dist/workflow/cli-shared.js +117 -0
- package/dist/workflow/cli-shared.js.map +1 -0
- package/dist/workflow/cli-support.js +0 -2
- package/dist/workflow/cli-support.js.map +1 -1
- package/dist/workflow/container-snapshots.d.ts +29 -0
- package/dist/workflow/container-snapshots.js +137 -0
- package/dist/workflow/container-snapshots.js.map +1 -0
- package/dist/workflow/daemon-gate-commands.d.ts +21 -0
- package/dist/workflow/daemon-gate-commands.js +595 -0
- package/dist/workflow/daemon-gate-commands.js.map +1 -0
- package/dist/workflow/discovery.d.ts +29 -0
- package/dist/workflow/discovery.js +67 -7
- package/dist/workflow/discovery.js.map +1 -1
- package/dist/workflow/lane-template.d.ts +89 -0
- package/dist/workflow/lane-template.js +141 -0
- package/dist/workflow/lane-template.js.map +1 -0
- package/dist/workflow/lint.d.ts +7 -1
- package/dist/workflow/lint.js +186 -3
- package/dist/workflow/lint.js.map +1 -1
- package/dist/workflow/machine-builder.d.ts +90 -2
- package/dist/workflow/machine-builder.js +222 -29
- package/dist/workflow/machine-builder.js.map +1 -1
- package/dist/workflow/message-log.d.ts +15 -1
- package/dist/workflow/message-log.js.map +1 -1
- package/dist/workflow/orchestrator.d.ts +505 -1
- package/dist/workflow/orchestrator.js +1725 -69
- package/dist/workflow/orchestrator.js.map +1 -1
- package/dist/workflow/prompt-builder.js +2 -1
- package/dist/workflow/prompt-builder.js.map +1 -1
- package/dist/workflow/run-state-command.js +1 -1
- package/dist/workflow/run-state-command.js.map +1 -1
- package/dist/workflow/shutdown-signals.d.ts +7 -0
- package/dist/workflow/shutdown-signals.js +40 -0
- package/dist/workflow/shutdown-signals.js.map +1 -0
- package/dist/workflow/status-parser.js +19 -4
- package/dist/workflow/status-parser.js.map +1 -1
- package/dist/workflow/types.d.ts +123 -23
- package/dist/workflow/types.js +2 -0
- package/dist/workflow/types.js.map +1 -1
- package/dist/workflow/validate.d.ts +23 -1
- package/dist/workflow/validate.js +311 -22
- package/dist/workflow/validate.js.map +1 -1
- package/dist/workflow/workflow-command.d.ts +0 -17
- package/dist/workflow/workflow-command.js +118 -94
- package/dist/workflow/workflow-command.js.map +1 -1
- package/dist/workflow/workflow-discovery.d.ts +2 -0
- package/dist/workflow/workflow-discovery.js +22 -1
- package/dist/workflow/workflow-discovery.js.map +1 -1
- package/dist/workflow/workflow-manager.d.ts +34 -0
- package/dist/workflow/workflow-manager.js +52 -1
- package/dist/workflow/workflow-manager.js.map +1 -1
- package/dist/workflow/workflows/design-and-code/README.md +50 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
- package/dist/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
- package/dist/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
- package/dist/workflow/workflows/evolve/README.md +66 -0
- package/dist/workflow/workflows/evolve/scripts/LICENSE +201 -0
- package/dist/workflow/workflows/evolve/scripts/README.md +314 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-brief +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-db +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-eval +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-files +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-summary +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
- package/dist/workflow/workflows/evolve/scripts/requirements.txt +2 -0
- package/dist/workflow/workflows/evolve/workflow.yaml +646 -0
- package/dist/workflow/workflows/test-email-summary/workflow.yaml +1 -0
- package/dist/workflow/workflows/vuln-discovery/README.md +54 -0
- package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
- package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
- package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
- package/dist/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
- package/docker/Dockerfile.base +22 -0
- package/docker/Dockerfile.base.arm64 +18 -0
- package/docker/Dockerfile.claude-code +3 -1
- package/docker/Dockerfile.codex +17 -0
- package/docker/Dockerfile.goose +3 -1
- package/docker/entrypoint-claude-code.sh +28 -45
- package/docker/entrypoint-codex.sh +42 -0
- package/docker/entrypoint-goose.sh +5 -24
- package/docker/entrypoint-uid-remap.sh +93 -0
- package/package.json +39 -30
- package/src/workflow/workflows/design-and-code/README.md +50 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
- package/src/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
- package/src/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
- package/src/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
- package/src/workflow/workflows/evolve/README.md +66 -0
- package/src/workflow/workflows/evolve/scripts/LICENSE +201 -0
- package/src/workflow/workflows/evolve/scripts/README.md +314 -0
- package/src/workflow/workflows/evolve/scripts/evolve-brief +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-db +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-eval +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-files +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-summary +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
- package/src/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
- package/src/workflow/workflows/evolve/scripts/requirements.txt +2 -0
- package/src/workflow/workflows/evolve/workflow.yaml +646 -0
- package/src/workflow/workflows/test-email-summary/workflow.yaml +1 -0
- package/src/workflow/workflows/vuln-discovery/README.md +54 -0
- package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
- package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
- package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
- package/src/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
- package/dist/mux/pty-bridge.js.map +0 -1
- package/dist/mux/trusted-input.js.map +0 -1
- package/dist/web-ui-static/assets/index-BFO5z1js.js +0 -76
- package/dist/web-ui-static/assets/index-CCUwrkIL.css +0 -1
- package/packages/web-ui/README.md +0 -113
|
@@ -9,14 +9,10 @@
|
|
|
9
9
|
* Otherwise (pipe, --json, --no-tui), it falls back to the plain
|
|
10
10
|
* line-oriented renderer.
|
|
11
11
|
*/
|
|
12
|
-
import { parseArgs } from 'node:util';
|
|
13
|
-
import { readFileSync } from 'node:fs';
|
|
14
12
|
import chalk from 'chalk';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { getWebUiStatePath } from '../config/paths.js';
|
|
13
|
+
import { checkHelp, parseArgsStrict } from '../cli-help.js';
|
|
14
|
+
import { createDaemonClient, discoverDaemon, } from '../daemon-client/daemon-client.js';
|
|
18
15
|
import { renderEventBatch, renderConnected, renderSessionEnded } from './observe-renderer.js';
|
|
19
|
-
import { wsDataToString } from '../web-ui/ws-utils.js';
|
|
20
16
|
import { createObserveTui } from './observe-tui.js';
|
|
21
17
|
// ---------------------------------------------------------------------------
|
|
22
18
|
// Command spec (for --help)
|
|
@@ -44,25 +40,6 @@ const observeSpec = {
|
|
|
44
40
|
'ironcurtain observe --all --json # NDJSON output for piping',
|
|
45
41
|
],
|
|
46
42
|
};
|
|
47
|
-
/** Reads daemon connection info from the well-known state file. */
|
|
48
|
-
function loadWebUiState() {
|
|
49
|
-
try {
|
|
50
|
-
const raw = readFileSync(getWebUiStatePath(), 'utf-8');
|
|
51
|
-
return JSON.parse(raw);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// ---------------------------------------------------------------------------
|
|
58
|
-
// JSON-RPC helpers
|
|
59
|
-
// ---------------------------------------------------------------------------
|
|
60
|
-
let rpcIdCounter = 0;
|
|
61
|
-
function sendRpc(ws, method, params = {}) {
|
|
62
|
-
const id = `observe-${++rpcIdCounter}`;
|
|
63
|
-
ws.send(JSON.stringify({ id, method, params }));
|
|
64
|
-
return id;
|
|
65
|
-
}
|
|
66
43
|
// ---------------------------------------------------------------------------
|
|
67
44
|
// Plain renderer adapter
|
|
68
45
|
// ---------------------------------------------------------------------------
|
|
@@ -118,7 +95,7 @@ function handlePushEvent(event, payload, sink, targetLabel, cleanup) {
|
|
|
118
95
|
// Main command
|
|
119
96
|
// ---------------------------------------------------------------------------
|
|
120
97
|
export async function runObserveCommand(argv) {
|
|
121
|
-
const { values, positionals } =
|
|
98
|
+
const { values, positionals } = parseArgsStrict({
|
|
122
99
|
args: argv,
|
|
123
100
|
options: {
|
|
124
101
|
all: { type: 'boolean' },
|
|
@@ -129,8 +106,7 @@ export async function runObserveCommand(argv) {
|
|
|
129
106
|
help: { type: 'boolean', short: 'h' },
|
|
130
107
|
},
|
|
131
108
|
allowPositionals: true,
|
|
132
|
-
|
|
133
|
-
});
|
|
109
|
+
}, observeSpec.name);
|
|
134
110
|
if (checkHelp(values, observeSpec))
|
|
135
111
|
return;
|
|
136
112
|
const allMode = values.all;
|
|
@@ -171,47 +147,70 @@ export async function runObserveCommand(argv) {
|
|
|
171
147
|
else {
|
|
172
148
|
sink = createPlainSink(renderOptions);
|
|
173
149
|
}
|
|
174
|
-
//
|
|
175
|
-
const
|
|
176
|
-
if (!
|
|
150
|
+
// Discover daemon connection info; "no daemon" surfaces identically to before.
|
|
151
|
+
const endpoint = discoverDaemon();
|
|
152
|
+
if (!endpoint) {
|
|
153
|
+
tui?.destroy();
|
|
154
|
+
printConnectionError();
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
const client = createDaemonClient({ endpoint });
|
|
158
|
+
try {
|
|
159
|
+
await client.connect();
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// A connect failure is presentationally identical to "no daemon".
|
|
177
163
|
tui?.destroy();
|
|
178
|
-
|
|
179
|
-
chalk.dim('Start with: ironcurtain daemon --web-ui\n'));
|
|
164
|
+
printConnectionError();
|
|
180
165
|
process.exit(1);
|
|
181
166
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
167
|
+
await runObserveSession(client, { label, useTui, tui, sink });
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Drives a connected {@link DaemonClient}: subscribes to the token stream,
|
|
171
|
+
* routes push events to the sink, and tears down on session end, involuntary
|
|
172
|
+
* disconnect, or Ctrl+C. Resolves exactly once.
|
|
173
|
+
*/
|
|
174
|
+
async function runObserveSession(client, ctx) {
|
|
175
|
+
const { label, useTui, tui, sink } = ctx;
|
|
176
|
+
await new Promise((resolve) => {
|
|
188
177
|
let closing = false;
|
|
178
|
+
let unsubscribeEvents = null;
|
|
179
|
+
let unsubscribeClose = null;
|
|
180
|
+
let sigHandler = null;
|
|
181
|
+
const removeSignalHandlers = () => {
|
|
182
|
+
if (sigHandler) {
|
|
183
|
+
process.off('SIGINT', sigHandler);
|
|
184
|
+
process.off('SIGTERM', sigHandler);
|
|
185
|
+
sigHandler = null;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
// Deliberate teardown: destroy TUI, unsubscribe, then close the client.
|
|
189
|
+
// `client.close()` is what suppresses any onClose for this self-initiated
|
|
190
|
+
// disconnect, so connectionLost never fires for our own cleanup.
|
|
189
191
|
const cleanup = () => {
|
|
190
192
|
if (closing)
|
|
191
193
|
return;
|
|
192
194
|
closing = true;
|
|
193
|
-
// Destroy TUI before unsubscribing (restores terminal state)
|
|
195
|
+
// Destroy TUI before unsubscribing (restores terminal state).
|
|
194
196
|
tui?.destroy();
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
resolve();
|
|
211
|
-
}
|
|
197
|
+
unsubscribeEvents?.();
|
|
198
|
+
unsubscribeClose?.();
|
|
199
|
+
removeSignalHandlers();
|
|
200
|
+
const unsubscribe = label !== undefined
|
|
201
|
+
? client.call('sessions.unsubscribeTokenStream', { label })
|
|
202
|
+
: client.call('sessions.unsubscribeAllTokenStreams');
|
|
203
|
+
void unsubscribe
|
|
204
|
+
.catch(() => {
|
|
205
|
+
/* best-effort: we are tearing down regardless */
|
|
206
|
+
})
|
|
207
|
+
.then(() => client.close())
|
|
208
|
+
.catch(() => {
|
|
209
|
+
/* close() is idempotent and never throws meaningfully here */
|
|
210
|
+
})
|
|
211
|
+
.finally(resolve);
|
|
212
212
|
};
|
|
213
|
-
// Handle Ctrl+C -- only register for plain mode; TUI handles its own signals
|
|
214
|
-
let sigHandler = null;
|
|
213
|
+
// Handle Ctrl+C -- only register for plain mode; TUI handles its own signals.
|
|
215
214
|
if (!useTui) {
|
|
216
215
|
sigHandler = () => {
|
|
217
216
|
process.stderr.write(chalk.dim('\n'));
|
|
@@ -220,79 +219,67 @@ export async function runObserveCommand(argv) {
|
|
|
220
219
|
process.on('SIGINT', sigHandler);
|
|
221
220
|
process.on('SIGTERM', sigHandler);
|
|
222
221
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (label !== undefined) {
|
|
226
|
-
subscribeId = sendRpc(ws, 'sessions.subscribeTokenStream', { label });
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
subscribeId = sendRpc(ws, 'sessions.subscribeAllTokenStreams');
|
|
230
|
-
}
|
|
222
|
+
unsubscribeEvents = client.onEvent((e) => {
|
|
223
|
+
handlePushEvent(e.event, e.payload, sink, label, cleanup);
|
|
231
224
|
});
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
frame = JSON.parse(text);
|
|
237
|
-
}
|
|
238
|
-
catch {
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
// Response to a request
|
|
242
|
-
if ('id' in frame && typeof frame.id === 'string') {
|
|
243
|
-
if (frame.id === subscribeId) {
|
|
244
|
-
if (frame.ok) {
|
|
245
|
-
// In TUI mode the text panel shows state; in plain mode write to stderr
|
|
246
|
-
if (!useTui) {
|
|
247
|
-
process.stderr.write(renderConnected(label));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
const err = frame.error;
|
|
252
|
-
if (!useTui) {
|
|
253
|
-
process.stderr.write(chalk.red(`Error: ${err?.message ?? 'subscription failed'}\n`));
|
|
254
|
-
}
|
|
255
|
-
cleanup();
|
|
256
|
-
}
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
if (frame.id === unsubscribeId) {
|
|
260
|
-
// Unsubscribe response -- close handled by timeout
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
225
|
+
unsubscribeClose = client.onClose((info) => {
|
|
226
|
+
// An *involuntary* disconnect (our own cleanup uses client.close(), which
|
|
227
|
+
// never fires onClose). Mirror the old ws 'error'/'close' behavior.
|
|
228
|
+
if (closing)
|
|
263
229
|
return;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
230
|
+
closing = true;
|
|
231
|
+
removeSignalHandlers();
|
|
232
|
+
sink.connectionLost(info.reason);
|
|
233
|
+
// In TUI mode the TUI's own 3-second exit timer manages shutdown; the
|
|
234
|
+
// promise resolves so runObserveCommand returns, but the TUI's frame loop
|
|
235
|
+
// and stdin keep the event loop alive until its destroy() fires.
|
|
236
|
+
resolve();
|
|
269
237
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
//
|
|
276
|
-
|
|
277
|
-
|
|
238
|
+
void subscribe(client, label, useTui)
|
|
239
|
+
.then((ok) => {
|
|
240
|
+
if (closing)
|
|
241
|
+
return;
|
|
242
|
+
if (ok) {
|
|
243
|
+
// In TUI mode the text panel shows state; in plain mode write to stderr.
|
|
244
|
+
if (!useTui)
|
|
245
|
+
process.stderr.write(renderConnected(label));
|
|
278
246
|
}
|
|
279
247
|
else {
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
ws.on('close', (code) => {
|
|
284
|
-
// Remove signal handlers if we registered them (plain mode only)
|
|
285
|
-
if (sigHandler) {
|
|
286
|
-
process.off('SIGINT', sigHandler);
|
|
287
|
-
process.off('SIGTERM', sigHandler);
|
|
288
|
-
}
|
|
289
|
-
// If not a clean close triggered by our cleanup, notify the sink
|
|
290
|
-
if (!closing) {
|
|
291
|
-
sink.connectionLost(`WebSocket closed (code ${code})`);
|
|
292
|
-
// In TUI mode, the 3-second exit timer handles cleanup
|
|
248
|
+
cleanup();
|
|
293
249
|
}
|
|
294
|
-
|
|
250
|
+
})
|
|
251
|
+
.catch(() => {
|
|
252
|
+
// `subscribe()` awaits `client.call()`, which REJECTS on a transport
|
|
253
|
+
// failure (e.g. the socket drops in the subscribe window). Without this
|
|
254
|
+
// handler that becomes an unhandled rejection. The onClose path already
|
|
255
|
+
// tears down on involuntary disconnect, so here we only need to clean up
|
|
256
|
+
// if we are not already closing (mirrors awaitDecisionPoint's guard).
|
|
257
|
+
if (closing)
|
|
258
|
+
return;
|
|
259
|
+
cleanup();
|
|
295
260
|
});
|
|
296
261
|
});
|
|
297
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Subscribes to the token stream for `label` (or all sessions). Returns true on
|
|
265
|
+
* success; on an RPC error, writes the plain-mode error and returns false.
|
|
266
|
+
*/
|
|
267
|
+
async function subscribe(client, label, useTui) {
|
|
268
|
+
const result = label !== undefined
|
|
269
|
+
? await client.call('sessions.subscribeTokenStream', { label })
|
|
270
|
+
: await client.call('sessions.subscribeAllTokenStreams');
|
|
271
|
+
if (result.ok)
|
|
272
|
+
return true;
|
|
273
|
+
// Match the old plain-mode behavior: TUI mode swallows the message (the panel
|
|
274
|
+
// surfaces state); plain mode prints it. Cleanup is the caller's job.
|
|
275
|
+
if (!useTui) {
|
|
276
|
+
process.stderr.write(chalk.red(`Error: ${result.message || 'subscription failed'}\n`));
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
/** Prints the shared "cannot connect to daemon" guidance to stderr. */
|
|
281
|
+
function printConnectionError() {
|
|
282
|
+
process.stderr.write(chalk.red('Error: cannot connect to daemon. Is the daemon running with --web-ui?\n') +
|
|
283
|
+
chalk.dim('Start with: ironcurtain daemon --web-ui\n'));
|
|
284
|
+
}
|
|
298
285
|
//# sourceMappingURL=observe-command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe-command.js","sourceRoot":"","sources":["../../src/observe/observe-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"observe-command.js","sourceRoot":"","sources":["../../src/observe/observe-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/persona/broad-policy-validator.ts
|
|
3
|
+
*
|
|
4
|
+
* Broad-policy validator (Phase 1c, §7). Passed as the `validateCompiled` hook
|
|
5
|
+
* to `compilePersonaPolicy` by the persona-compile orchestrator. It runs on the
|
|
6
|
+
* in-memory `CompiledPolicyFile` BEFORE any artifact is written, so a rejection
|
|
7
|
+
* leaves the prior generation's files intact (no partial write).
|
|
8
|
+
*
|
|
9
|
+
* It defeats constitution prompt-injection toward an over-permissive policy in a
|
|
10
|
+
* way that is fully LLM-independent: it inspects the COMPILED rules, not the
|
|
11
|
+
* constitution text. A persona may only emit a "broad" policy if it has been
|
|
12
|
+
* explicitly opted in via the gated `personas.setBroadPolicyOptIn` flow
|
|
13
|
+
* (`persona.allowBroadPolicy === true`). Otherwise the following are rejected:
|
|
14
|
+
*
|
|
15
|
+
* - any "broad wildcard" `domains.allowed` entry (see isBroadDomainPattern),
|
|
16
|
+
* - any "broad wildcard" `lists[].allowed` entry,
|
|
17
|
+
* - any `paths.within` that resolves OUTSIDE the persona's workspace dir.
|
|
18
|
+
*
|
|
19
|
+
* A "broad wildcard" is not just the literal `*`. The runtime matcher
|
|
20
|
+
* (domainMatchesAllowlist in trusted-process/domain-utils.ts) treats any
|
|
21
|
+
* `*.`-prefixed pattern as a hostname suffix match, and the compiler is
|
|
22
|
+
* explicitly allowed to emit prefix wildcards (`*.example.com`). A TLD-level
|
|
23
|
+
* wildcard like `*.com`, `*.gov`, or the empty-suffix `*.` therefore grants
|
|
24
|
+
* near-wildcard egress and must be treated as broad — only a wildcard whose
|
|
25
|
+
* suffix has TWO OR MORE labels (e.g. `*.github.com`, scoped to a single
|
|
26
|
+
* registered domain) is considered narrow and allowed without opt-in.
|
|
27
|
+
*
|
|
28
|
+
* Rejection throws {@link BroadPolicyRejectedError}; the orchestrator maps the
|
|
29
|
+
* `code` (`BROAD_POLICY_REJECTED`) onto a terminal `persona.compile.failed`
|
|
30
|
+
* event.
|
|
31
|
+
*
|
|
32
|
+
* ZERO runtime value-imports from src/pipeline — the `CompiledPolicyFile` shape
|
|
33
|
+
* is a type-only import. Path containment uses the live-layer `resolveRealPath`
|
|
34
|
+
* helper (symlink-aware), consistent with the policy engine.
|
|
35
|
+
*
|
|
36
|
+
* @see docs/designs/web-ui-policy-persona-management.md §7
|
|
37
|
+
*/
|
|
38
|
+
import type { ErrorCode } from '../web-ui/web-ui-types.js';
|
|
39
|
+
import type { CompiledPolicyFile, DynamicListsFile } from '../pipeline/types.js';
|
|
40
|
+
/** Thrown when a compiled policy is "broad" but the persona is not opted in. */
|
|
41
|
+
export declare class BroadPolicyRejectedError extends Error {
|
|
42
|
+
readonly data?: {
|
|
43
|
+
broadenedDomains: string[];
|
|
44
|
+
outOfWorkspacePaths: string[];
|
|
45
|
+
} | undefined;
|
|
46
|
+
readonly code: ErrorCode;
|
|
47
|
+
constructor(message: string, data?: {
|
|
48
|
+
broadenedDomains: string[];
|
|
49
|
+
outOfWorkspacePaths: string[];
|
|
50
|
+
} | undefined);
|
|
51
|
+
}
|
|
52
|
+
/** Findings produced by inspecting a compiled policy for broadening. */
|
|
53
|
+
export interface BroadPolicyFindings {
|
|
54
|
+
/**
|
|
55
|
+
* Broad-wildcard entries found in any `domains.allowed` or `lists[].allowed`
|
|
56
|
+
* (the literal pattern, e.g. `*`, `*.`, `*.com`). See {@link isBroadDomainPattern}.
|
|
57
|
+
*/
|
|
58
|
+
readonly broadenedDomains: string[];
|
|
59
|
+
/** `paths.within` values resolving outside the workspace dir. */
|
|
60
|
+
readonly outOfWorkspacePaths: string[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns true iff `pattern` grants near-wildcard egress and therefore requires
|
|
64
|
+
* the broad-policy opt-in. This mirrors the runtime matcher semantics in
|
|
65
|
+
* `domainMatchesAllowlist` (trusted-process/domain-utils.ts), where `*` matches
|
|
66
|
+
* any non-IP host and `*.<suffix>` matches every host ending in `.<suffix>`.
|
|
67
|
+
*
|
|
68
|
+
* Broad (rejected without opt-in):
|
|
69
|
+
* - `*` — matches every (non-IP) host
|
|
70
|
+
* - `*.` — empty suffix; `endsWith('.')` matches ~everything
|
|
71
|
+
* - `*.com`/`*.gov`— TLD-only suffix (<= 1 label after the `*.`)
|
|
72
|
+
*
|
|
73
|
+
* Narrow (allowed without opt-in):
|
|
74
|
+
* - `*.github.com` — suffix has >= 2 labels (one registered domain)
|
|
75
|
+
* - `github.com` — bare hostname (no wildcard)
|
|
76
|
+
*/
|
|
77
|
+
export declare function isBroadDomainPattern(pattern: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Inspects a compiled policy and returns the set of "broad" findings. Pure /
|
|
80
|
+
* side-effect-free so it can also feed the ruleDelta computation. A path is
|
|
81
|
+
* "out of workspace" iff its real-resolved form is neither the workspace dir nor
|
|
82
|
+
* a descendant of it. When `dynamicLists` is supplied, `@list` references in
|
|
83
|
+
* `domains.allowed` / `lists[].allowed` are resolved to their concrete values so
|
|
84
|
+
* a list that resolves to a broad wildcard is detected (the validator passes it;
|
|
85
|
+
* callers without the resolved lists — e.g. the rule-delta report — still get the
|
|
86
|
+
* literal-pattern findings).
|
|
87
|
+
*/
|
|
88
|
+
export declare function findBroadPolicy(policy: CompiledPolicyFile, workspaceDir: string, dynamicLists?: DynamicListsFile): BroadPolicyFindings;
|
|
89
|
+
/**
|
|
90
|
+
* Builds a `validateCompiled` hook bound to a persona's workspace dir and
|
|
91
|
+
* opt-in flag. When `allowBroadPolicy` is true the hook is a no-op (broadening
|
|
92
|
+
* is permitted); otherwise it throws {@link BroadPolicyRejectedError} on any
|
|
93
|
+
* broad finding.
|
|
94
|
+
*/
|
|
95
|
+
export declare function makeBroadPolicyValidator(workspaceDir: string, allowBroadPolicy: boolean): (policy: CompiledPolicyFile, dynamicLists?: DynamicListsFile) => void;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/persona/broad-policy-validator.ts
|
|
3
|
+
*
|
|
4
|
+
* Broad-policy validator (Phase 1c, §7). Passed as the `validateCompiled` hook
|
|
5
|
+
* to `compilePersonaPolicy` by the persona-compile orchestrator. It runs on the
|
|
6
|
+
* in-memory `CompiledPolicyFile` BEFORE any artifact is written, so a rejection
|
|
7
|
+
* leaves the prior generation's files intact (no partial write).
|
|
8
|
+
*
|
|
9
|
+
* It defeats constitution prompt-injection toward an over-permissive policy in a
|
|
10
|
+
* way that is fully LLM-independent: it inspects the COMPILED rules, not the
|
|
11
|
+
* constitution text. A persona may only emit a "broad" policy if it has been
|
|
12
|
+
* explicitly opted in via the gated `personas.setBroadPolicyOptIn` flow
|
|
13
|
+
* (`persona.allowBroadPolicy === true`). Otherwise the following are rejected:
|
|
14
|
+
*
|
|
15
|
+
* - any "broad wildcard" `domains.allowed` entry (see isBroadDomainPattern),
|
|
16
|
+
* - any "broad wildcard" `lists[].allowed` entry,
|
|
17
|
+
* - any `paths.within` that resolves OUTSIDE the persona's workspace dir.
|
|
18
|
+
*
|
|
19
|
+
* A "broad wildcard" is not just the literal `*`. The runtime matcher
|
|
20
|
+
* (domainMatchesAllowlist in trusted-process/domain-utils.ts) treats any
|
|
21
|
+
* `*.`-prefixed pattern as a hostname suffix match, and the compiler is
|
|
22
|
+
* explicitly allowed to emit prefix wildcards (`*.example.com`). A TLD-level
|
|
23
|
+
* wildcard like `*.com`, `*.gov`, or the empty-suffix `*.` therefore grants
|
|
24
|
+
* near-wildcard egress and must be treated as broad — only a wildcard whose
|
|
25
|
+
* suffix has TWO OR MORE labels (e.g. `*.github.com`, scoped to a single
|
|
26
|
+
* registered domain) is considered narrow and allowed without opt-in.
|
|
27
|
+
*
|
|
28
|
+
* Rejection throws {@link BroadPolicyRejectedError}; the orchestrator maps the
|
|
29
|
+
* `code` (`BROAD_POLICY_REJECTED`) onto a terminal `persona.compile.failed`
|
|
30
|
+
* event.
|
|
31
|
+
*
|
|
32
|
+
* ZERO runtime value-imports from src/pipeline — the `CompiledPolicyFile` shape
|
|
33
|
+
* is a type-only import. Path containment uses the live-layer `resolveRealPath`
|
|
34
|
+
* helper (symlink-aware), consistent with the policy engine.
|
|
35
|
+
*
|
|
36
|
+
* @see docs/designs/web-ui-policy-persona-management.md §7
|
|
37
|
+
*/
|
|
38
|
+
import { resolveRealPath } from '../types/argument-roles.js';
|
|
39
|
+
/** Thrown when a compiled policy is "broad" but the persona is not opted in. */
|
|
40
|
+
export class BroadPolicyRejectedError extends Error {
|
|
41
|
+
data;
|
|
42
|
+
code = 'BROAD_POLICY_REJECTED';
|
|
43
|
+
constructor(message, data) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.data = data;
|
|
46
|
+
this.name = 'BroadPolicyRejectedError';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns true iff `pattern` grants near-wildcard egress and therefore requires
|
|
51
|
+
* the broad-policy opt-in. This mirrors the runtime matcher semantics in
|
|
52
|
+
* `domainMatchesAllowlist` (trusted-process/domain-utils.ts), where `*` matches
|
|
53
|
+
* any non-IP host and `*.<suffix>` matches every host ending in `.<suffix>`.
|
|
54
|
+
*
|
|
55
|
+
* Broad (rejected without opt-in):
|
|
56
|
+
* - `*` — matches every (non-IP) host
|
|
57
|
+
* - `*.` — empty suffix; `endsWith('.')` matches ~everything
|
|
58
|
+
* - `*.com`/`*.gov`— TLD-only suffix (<= 1 label after the `*.`)
|
|
59
|
+
*
|
|
60
|
+
* Narrow (allowed without opt-in):
|
|
61
|
+
* - `*.github.com` — suffix has >= 2 labels (one registered domain)
|
|
62
|
+
* - `github.com` — bare hostname (no wildcard)
|
|
63
|
+
*/
|
|
64
|
+
export function isBroadDomainPattern(pattern) {
|
|
65
|
+
if (pattern === '*')
|
|
66
|
+
return true;
|
|
67
|
+
if (!pattern.startsWith('*.'))
|
|
68
|
+
return false;
|
|
69
|
+
const suffix = pattern.slice(2); // drop the leading "*."
|
|
70
|
+
// Empty or single-label suffix (TLD-only) => broad. Count non-empty labels.
|
|
71
|
+
const labels = suffix.split('.').filter((l) => l.length > 0);
|
|
72
|
+
return labels.length <= 1;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Expands an `allowed` array (from `domains.allowed` or `lists[].allowed`) into
|
|
76
|
+
* the concrete values to test for breadth. A `@list` reference contributes its
|
|
77
|
+
* EFFECTIVE values (values + manualAdditions − manualRemovals), mirroring
|
|
78
|
+
* `PolicyEngine.getEffectiveListValues` — so a list that RESOLVES to a broad
|
|
79
|
+
* wildcard (e.g. a "major news sites" list containing `*.com`) is caught even
|
|
80
|
+
* though the rule only stores the `@list` symbol and the resolved values live
|
|
81
|
+
* separately in dynamic-lists.json. A missing list contributes nothing: the
|
|
82
|
+
* runtime fails closed (missing `@list` => empty => deny), so there is nothing
|
|
83
|
+
* broad to flag. `via` records the originating `@list` for a clear message.
|
|
84
|
+
*/
|
|
85
|
+
function expandAllowedForBreadth(allowed, dynamicLists) {
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const entry of allowed) {
|
|
88
|
+
if (!entry.startsWith('@')) {
|
|
89
|
+
out.push({ value: entry });
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const list = dynamicLists?.lists[entry.slice(1)];
|
|
93
|
+
if (!list)
|
|
94
|
+
continue;
|
|
95
|
+
const removals = new Set(list.manualRemovals);
|
|
96
|
+
for (const v of new Set([...list.values, ...list.manualAdditions])) {
|
|
97
|
+
if (!removals.has(v))
|
|
98
|
+
out.push({ value: v, via: entry });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Inspects a compiled policy and returns the set of "broad" findings. Pure /
|
|
105
|
+
* side-effect-free so it can also feed the ruleDelta computation. A path is
|
|
106
|
+
* "out of workspace" iff its real-resolved form is neither the workspace dir nor
|
|
107
|
+
* a descendant of it. When `dynamicLists` is supplied, `@list` references in
|
|
108
|
+
* `domains.allowed` / `lists[].allowed` are resolved to their concrete values so
|
|
109
|
+
* a list that resolves to a broad wildcard is detected (the validator passes it;
|
|
110
|
+
* callers without the resolved lists — e.g. the rule-delta report — still get the
|
|
111
|
+
* literal-pattern findings).
|
|
112
|
+
*/
|
|
113
|
+
export function findBroadPolicy(policy, workspaceDir, dynamicLists) {
|
|
114
|
+
const broadenedDomains = new Set();
|
|
115
|
+
const outOfWorkspacePaths = new Set();
|
|
116
|
+
const workspaceReal = resolveRealPath(workspaceDir);
|
|
117
|
+
const flagBroad = (entries) => {
|
|
118
|
+
for (const { value, via } of expandAllowedForBreadth(entries, dynamicLists)) {
|
|
119
|
+
if (isBroadDomainPattern(value))
|
|
120
|
+
broadenedDomains.add(via ? `${value} (via ${via})` : value);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
for (const rule of policy.rules) {
|
|
124
|
+
const cond = rule.if;
|
|
125
|
+
// Wildcard domains — incl. those reached through a resolved @list.
|
|
126
|
+
if (cond.domains?.allowed)
|
|
127
|
+
flagBroad(cond.domains.allowed);
|
|
128
|
+
// Wildcard list allowances.
|
|
129
|
+
if (cond.lists) {
|
|
130
|
+
for (const list of cond.lists)
|
|
131
|
+
flagBroad(list.allowed);
|
|
132
|
+
}
|
|
133
|
+
// Out-of-workspace path containment.
|
|
134
|
+
if (cond.paths?.within) {
|
|
135
|
+
const within = cond.paths.within;
|
|
136
|
+
const withinReal = resolveRealPath(within);
|
|
137
|
+
const contained = withinReal === workspaceReal || withinReal.startsWith(workspaceReal + '/');
|
|
138
|
+
if (!contained)
|
|
139
|
+
outOfWorkspacePaths.add(within);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
broadenedDomains: [...broadenedDomains],
|
|
144
|
+
outOfWorkspacePaths: [...outOfWorkspacePaths],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Builds a `validateCompiled` hook bound to a persona's workspace dir and
|
|
149
|
+
* opt-in flag. When `allowBroadPolicy` is true the hook is a no-op (broadening
|
|
150
|
+
* is permitted); otherwise it throws {@link BroadPolicyRejectedError} on any
|
|
151
|
+
* broad finding.
|
|
152
|
+
*/
|
|
153
|
+
export function makeBroadPolicyValidator(workspaceDir, allowBroadPolicy) {
|
|
154
|
+
return (policy, dynamicLists) => {
|
|
155
|
+
if (allowBroadPolicy)
|
|
156
|
+
return;
|
|
157
|
+
const findings = findBroadPolicy(policy, workspaceDir, dynamicLists);
|
|
158
|
+
if (findings.broadenedDomains.length === 0 && findings.outOfWorkspacePaths.length === 0) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const parts = [];
|
|
162
|
+
if (findings.broadenedDomains.length > 0) {
|
|
163
|
+
parts.push(`broad wildcard domain/list access: ${findings.broadenedDomains.join(', ')}`);
|
|
164
|
+
}
|
|
165
|
+
if (findings.outOfWorkspacePaths.length > 0) {
|
|
166
|
+
parts.push(`out-of-workspace path(s): ${findings.outOfWorkspacePaths.join(', ')}`);
|
|
167
|
+
}
|
|
168
|
+
throw new BroadPolicyRejectedError(`Compiled policy is too broad (${parts.join('; ')}). Enable broad policy for this persona to allow it.`, { broadenedDomains: findings.broadenedDomains, outOfWorkspacePaths: findings.outOfWorkspacePaths });
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=broad-policy-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broad-policy-validator.js","sourceRoot":"","sources":["../../src/persona/broad-policy-validator.ts"],"names":[],"mappings":"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"}
|