@sema-agent/core 7.47.0 → 7.49.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/CHANGELOG.md +472 -0
- package/README.md +2 -2
- package/dist/agents/cascade.d.ts +2 -5
- package/dist/agents/child-failure.d.ts +20 -0
- package/dist/agents/child-failure.js +28 -0
- package/dist/agents/cross-session-ref.d.ts +11 -3
- package/dist/agents/cross-session-ref.js +6 -0
- package/dist/agents/cumulative-stats.d.ts +12 -15
- package/dist/agents/cumulative-stats.js +1 -1
- package/dist/agents/extra-tool-names.js +1 -1
- package/dist/agents/inherited-tool-pool.d.ts +17 -13
- package/dist/agents/inherited-tool-pool.js +4 -3
- package/dist/agents/peer-session-drain.d.ts +3 -2
- package/dist/agents/peer-session-drain.js +5 -4
- package/dist/agents/send-message-tool.js +2 -9
- package/dist/agents/subagent.d.ts +10 -29
- package/dist/agents/subagent.js +65 -53
- package/dist/agents/suspend-guard.d.ts +1 -1
- package/dist/agents/tool-filter.d.ts +76 -65
- package/dist/agents/tool-filter.js +122 -92
- package/dist/agents/verify.d.ts +4 -7
- package/dist/agents/verify.js +6 -7
- package/dist/bench/metrics.d.ts +1 -2
- package/dist/brain/anthropic.js +133 -79
- package/dist/brain/errors.d.ts +53 -6
- package/dist/brain/errors.js +22 -2
- package/dist/brain/input-too-long.d.ts +40 -19
- package/dist/brain/input-too-long.js +3 -16
- package/dist/brain/open-responses.js +19 -10
- package/dist/brain/openai.js +123 -32
- package/dist/brain/provider-dialect.d.ts +214 -0
- package/dist/brain/provider-dialect.js +186 -0
- package/dist/brain/request-params.d.ts +27 -8
- package/dist/brain/request-params.js +7 -12
- package/dist/brain/request-route.d.ts +84 -0
- package/dist/brain/request-route.js +41 -0
- package/dist/brain/retry.d.ts +8 -0
- package/dist/brain/retry.js +10 -4
- package/dist/brain/route-adjudicator.d.ts +7 -0
- package/dist/brain/route-adjudicator.js +5 -1
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +11 -0
- package/dist/brain/stream-engine.d.ts +52 -1
- package/dist/brain/stream-engine.js +81 -24
- package/dist/brain/stream-shared.d.ts +57 -11
- package/dist/brain/stream-shared.js +28 -2
- package/dist/core/a2a.d.ts +1 -0
- package/dist/core/agent-config-dir.js +3 -2
- package/dist/core/allow-entry.d.ts +21 -12
- package/dist/core/allow-entry.js +39 -32
- package/dist/core/arg-summary.d.ts +17 -24
- package/dist/core/arg-summary.js +169 -68
- package/dist/core/ask-origin.d.ts +42 -24
- package/dist/core/ask-origin.js +18 -13
- package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
- package/dist/core/auto-mode-prompt-assets.js +1 -1
- package/dist/core/auto-mode-prompt.d.ts +11 -1
- package/dist/core/auto-mode-prompt.js +13 -10
- package/dist/core/auto-mode-rebuild.d.ts +7 -0
- package/dist/core/auto-mode-rebuild.js +4 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.js +2 -1
- package/dist/core/checkpoint-requirements.d.ts +892 -0
- package/dist/core/checkpoint-requirements.js +333 -0
- package/dist/core/checkpoint-store.d.ts +95 -66
- package/dist/core/checkpoint-store.js +14 -26
- package/dist/core/child-clamp-seats.d.ts +228 -69
- package/dist/core/child-clamp-seats.js +211 -17
- package/dist/core/classifier-unavailable-arm.d.ts +5 -1
- package/dist/core/classifier-unavailable-arm.js +3 -3
- package/dist/core/compliance.d.ts +3 -0
- package/dist/core/compliance.js +9 -4
- package/dist/core/credential-vocabulary.d.ts +140 -0
- package/dist/core/credential-vocabulary.js +131 -0
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/effective-path-target.d.ts +73 -16
- package/dist/core/effective-path-target.js +63 -33
- package/dist/core/engine-notice.d.ts +32 -7
- package/dist/core/file-history-store.js +2 -2
- package/dist/core/fs-write-gate-policy.d.ts +4 -0
- package/dist/core/fs-write-gate-policy.js +22 -5
- package/dist/core/gate-bounded-await.d.ts +28 -13
- package/dist/core/gate-bounded-await.js +41 -4
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -25
- package/dist/core/gate-lanes.js +16 -15
- package/dist/core/gate-outcome.d.ts +20 -5
- package/dist/core/gate-outcome.js +5 -0
- package/dist/core/governance-codes.d.ts +11 -4
- package/dist/core/governance-codes.js +14 -3
- package/dist/core/hooks.d.ts +4 -0
- package/dist/core/locked-config.d.ts +8 -0
- package/dist/core/locked-config.js +14 -2
- package/dist/core/lsp.js +3 -5
- package/dist/core/mailbox-store.d.ts +3 -4
- package/dist/core/mcp-connection-pool.d.ts +75 -0
- package/dist/core/mcp-connection-pool.js +128 -0
- package/dist/core/mcp-failure.d.ts +2 -1
- package/dist/core/mcp-failure.js +13 -2
- package/dist/core/mcp-server-spec.d.ts +1 -1
- package/dist/core/mcp.d.ts +4 -0
- package/dist/core/mcp.js +70 -43
- package/dist/core/memory-engine/content-origin.js +2 -14
- package/dist/core/memory-engine/engine.d.ts +32 -22
- package/dist/core/memory-engine/engine.js +103 -55
- package/dist/core/memory-engine/file-backend.d.ts +13 -30
- package/dist/core/memory-engine/file-backend.js +37 -252
- package/dist/core/memory-engine/index.d.ts +1 -1
- package/dist/core/memory-engine/index.js +1 -1
- package/dist/core/memory-engine/layout.d.ts +139 -9
- package/dist/core/memory-engine/layout.js +350 -7
- package/dist/core/memory-engine/scope-contract.d.ts +10 -0
- package/dist/core/memory-engine/scope-contract.js +8 -0
- package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
- package/dist/core/memory-engine/session-incarnation.js +5 -2
- package/dist/core/memory-engine/types.d.ts +10 -1
- package/dist/core/memory.js +5 -17
- package/dist/core/model-seat.d.ts +4 -4
- package/dist/core/model-seat.js +1 -1
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +19 -0
- package/dist/core/namespaced-rule-name.d.ts +29 -0
- package/dist/core/namespaced-rule-name.js +52 -0
- package/dist/core/park-selfcheck.d.ts +1 -1
- package/dist/core/park-selfcheck.js +16 -6
- package/dist/core/path-guard-rows.d.ts +99 -0
- package/dist/core/path-guard-rows.js +45 -0
- package/dist/core/path-identity.d.ts +22 -16
- package/dist/core/path-identity.js +10 -10
- package/dist/core/path-rule-binding.d.ts +2 -1
- package/dist/core/path-rule-binding.js +3 -1
- package/dist/core/pause-registry.d.ts +16 -2
- package/dist/core/pause-registry.js +6 -0
- package/dist/core/permission-rule-consent.js +0 -7
- package/dist/core/permission-rule-model.d.ts +68 -24
- package/dist/core/permission-rule-model.js +105 -24
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/permission-rules.d.ts +3 -30
- package/dist/core/permission-rules.js +4 -54
- package/dist/core/read-root-candidate.d.ts +1 -3
- package/dist/core/read-root-candidate.js +4 -15
- package/dist/core/real-approval.d.ts +4 -3
- package/dist/core/retired-keys.d.ts +13 -0
- package/dist/core/retired-keys.js +14 -0
- package/dist/core/roles.d.ts +2 -3
- package/dist/core/roles.js +15 -6
- package/dist/core/runner/assemble-result.d.ts +0 -7
- package/dist/core/runner/assemble-result.js +19 -31
- package/dist/core/runner/caller-roster.d.ts +78 -0
- package/dist/core/runner/caller-roster.js +219 -0
- package/dist/core/runner/checkpoint-scope.d.ts +16 -16
- package/dist/core/runner/checkpoint-scope.js +2 -2
- package/dist/core/runner/child-tree.js +2 -2
- package/dist/core/runner/contracts.d.ts +68 -35
- package/dist/core/runner/decide-continuation.d.ts +51 -3
- package/dist/core/runner/decide-continuation.js +76 -21
- package/dist/core/runner/denial-limit-arms.d.ts +17 -5
- package/dist/core/runner/denial-limit-arms.js +11 -9
- package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
- package/dist/core/runner/extra-body-dropped-seat.js +22 -0
- package/dist/core/runner/finish-reason-seat.d.ts +9 -0
- package/dist/core/runner/finish-reason-seat.js +40 -0
- package/dist/core/runner/gate-exit.d.ts +44 -32
- package/dist/core/runner/gate-exit.js +112 -25
- package/dist/core/runner/inherited-ask-grants.js +6 -4
- package/dist/core/runner/mcp-redial.d.ts +3 -3
- package/dist/core/runner/mcp-redial.js +3 -4
- package/dist/core/runner/park-commit.d.ts +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
- package/dist/core/runner/permission-rule-lanes.js +5 -4
- package/dist/core/runner/prepare-artifact.d.ts +4 -0
- package/dist/core/runner/prepare-artifact.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
- package/dist/core/runner/prepare-ask-lane.js +12 -6
- package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
- package/dist/core/runner/prepare-boundary-parks.js +4 -7
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
- package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
- package/dist/core/runner/prepare-config-doors.d.ts +9 -9
- package/dist/core/runner/prepare-config-doors.js +10 -5
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-defer-classify.js +5 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-delegation-surface.js +3 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
- package/dist/core/runner/prepare-gate-stations.js +9 -7
- package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
- package/dist/core/runner/prepare-hands-readface.js +7 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
- package/dist/core/runner/prepare-inherited-gate.js +14 -15
- package/dist/core/runner/prepare-listings.d.ts +7 -24
- package/dist/core/runner/prepare-listings.js +4 -5
- package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
- package/dist/core/runner/prepare-memory-engine-session.js +4 -3
- package/dist/core/runner/prepare-memory.d.ts +6 -0
- package/dist/core/runner/prepare-memory.js +13 -13
- package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
- package/dist/core/runner/prepare-offload-wrappers.js +3 -3
- package/dist/core/runner/prepare-park-ask.d.ts +7 -8
- package/dist/core/runner/prepare-park-ask.js +17 -10
- package/dist/core/runner/prepare-policy-chain.js +24 -44
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +3 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -4
- package/dist/core/runner/prepare-run-refs.d.ts +3 -0
- package/dist/core/runner/prepare-run-refs.js +2 -1
- package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
- package/dist/core/runner/prepare-safety-scan.js +1 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
- package/dist/core/runner/prepare-suspend-saga.js +28 -12
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +67 -56
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
- package/dist/core/runner/prepare-wiring-manifest.js +5 -8
- package/dist/core/runner/resume-apply.js +7 -14
- package/dist/core/runner/resume-checkpoint-screen.js +11 -4
- package/dist/core/runner/resume-internals-and-config.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +5 -32
- package/dist/core/runner/resume-review-outcome.js +4 -1
- package/dist/core/runner/retired-runner-deps.d.ts +6 -0
- package/dist/core/runner/retired-runner-deps.js +10 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -0
- package/dist/core/runner/run-brain-sinks.js +5 -2
- package/dist/core/runner/run-harness-handlers.js +27 -34
- package/dist/core/runner/run-leg.d.ts +0 -2
- package/dist/core/runner/run-leg.js +32 -33
- package/dist/core/runner/run-terminal-adoption.js +4 -3
- package/dist/core/runner/runtask.js +8 -8
- package/dist/core/runner/session-rule-policy.js +5 -5
- package/dist/core/runner/stream-settle-backstop.js +7 -4
- package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
- package/dist/core/runner/sub-agent-deny-lists.js +111 -80
- package/dist/core/runner/terminal-account.d.ts +48 -0
- package/dist/core/runner/terminal-account.js +186 -0
- package/dist/core/runner/tool-end-body.d.ts +54 -17
- package/dist/core/runner/tool-end-body.js +27 -2
- package/dist/core/runner/tool-face-overlay.d.ts +3 -1
- package/dist/core/runner/tool-face-overlay.js +6 -4
- package/dist/core/runner/tool-occurrence.d.ts +106 -0
- package/dist/core/runner/tool-occurrence.js +123 -0
- package/dist/core/runner/tool-progress-lane.d.ts +16 -8
- package/dist/core/runner/tool-progress-lane.js +25 -34
- package/dist/core/runner/turn-attachments.d.ts +1 -1
- package/dist/core/runner/write-protection-station.d.ts +21 -9
- package/dist/core/runner/write-protection-station.js +20 -17
- package/dist/core/runner-deps.d.ts +12 -22
- package/dist/core/safety-axis-vocab.d.ts +1 -1
- package/dist/core/safety-merge-corpus.d.ts +1 -1
- package/dist/core/secret-env.d.ts +16 -5
- package/dist/core/secret-env.js +23 -63
- package/dist/core/sensitive-path-policy.d.ts +19 -18
- package/dist/core/sensitive-path-policy.js +73 -49
- package/dist/core/session-policy-store.d.ts +6 -3
- package/dist/core/session-policy-store.js +28 -10
- package/dist/core/session-reconcile.d.ts +3 -0
- package/dist/core/session-reconcile.js +5 -4
- package/dist/core/session-store.d.ts +5 -0
- package/dist/core/session-store.js +12 -0
- package/dist/core/session.d.ts +13 -0
- package/dist/core/shared-memory/normalize.d.ts +17 -4
- package/dist/core/shared-memory/normalize.js +7 -7
- package/dist/core/shell-lexer.js +5 -4
- package/dist/core/shell-wrapper-table.d.ts +2 -2
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/skill-grant.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +2 -2
- package/dist/core/task-event.d.ts +59 -5
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +42 -9
- package/dist/core/terminal-cause.d.ts +94 -11
- package/dist/core/tighten-task-spec.d.ts +5 -4
- package/dist/core/tighten-task-spec.js +20 -25
- package/dist/core/tool-catalog-entries.d.ts +5 -7
- package/dist/core/tool-catalog-entries.js +14 -15
- package/dist/core/tool-face.d.ts +47 -0
- package/dist/core/tool-face.js +5 -0
- package/dist/core/tool-model-gate.d.ts +5 -5
- package/dist/core/tool-name-aliases.d.ts +35 -10
- package/dist/core/tool-name-aliases.js +15 -0
- package/dist/core/tool-name-list.d.ts +30 -0
- package/dist/core/tool-name-list.js +55 -0
- package/dist/core/tool-name-readings.d.ts +1 -9
- package/dist/core/tool-name-readings.js +1 -3
- package/dist/core/tool-policy.d.ts +195 -85
- package/dist/core/tool-policy.js +165 -381
- package/dist/core/tool-registry.d.ts +44 -1
- package/dist/core/tool-registry.js +26 -0
- package/dist/core/tool-roster.d.ts +19 -1
- package/dist/core/tool-roster.js +21 -2
- package/dist/core/tool-spec-members.d.ts +45 -0
- package/dist/core/tool-spec-members.js +169 -0
- package/dist/core/tool-spec.d.ts +46 -8
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +8 -4
- package/dist/core/untrusted-egress.js +29 -26
- package/dist/core/untrusted-text.d.ts +13 -10
- package/dist/core/untrusted-text.js +6 -44
- package/dist/core/workflow-journal-store.d.ts +4 -1
- package/dist/core/write-protect.d.ts +65 -29
- package/dist/core/write-protect.js +235 -177
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
- package/dist/engine/execution-env/node-execution-env.js +16 -38
- package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
- package/dist/engine/execution-env/symlink-chain.js +32 -0
- package/dist/engine/harness/types.d.ts +7 -0
- package/dist/engine/llm/tool-turns.d.ts +3 -0
- package/dist/engine/llm/tool-turns.js +1 -0
- package/dist/engine/llm/types.d.ts +59 -23
- package/dist/engine/loop/agent-loop.js +16 -2
- package/dist/engine/session/memory-repo.js +11 -3
- package/dist/engine/session/repo-utils.d.ts +8 -0
- package/dist/engine/session/repo-utils.js +13 -0
- package/dist/index.d.ts +20 -23
- package/dist/index.js +17 -20
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/governance-baseline-validity.js +1 -1
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +16 -35
- package/dist/orchestration/run-workflow-tool.js +38 -78
- package/dist/orchestration/workflow-governance.d.ts +21 -25
- package/dist/orchestration/workflow-governance.js +38 -78
- package/dist/orchestration/workflow-primitives.d.ts +7 -22
- package/dist/orchestration/workflow-primitives.js +5 -12
- package/dist/orchestration/workflow-types.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +61 -11
- package/dist/orchestration/workflow.js +191 -119
- package/dist/prompt-assembly/types.d.ts +1 -1
- package/dist/scenarios/full-body.d.ts +1 -1
- package/dist/shell/lex.d.ts +0 -21
- package/dist/shell/lex.js +278 -70
- package/dist/shell/shell-words.d.ts +35 -0
- package/dist/shell/shell-words.js +65 -0
- package/dist/stores/file/checkpoint-store.d.ts +5 -5
- package/dist/stores/file/checkpoint-store.js +5 -2
- package/dist/stores/file/index.d.ts +0 -8
- package/dist/stores/file/index.js +0 -12
- package/dist/stores/file/session-store.d.ts +3 -0
- package/dist/stores/file/session-store.js +44 -19
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/bash-program-position.d.ts +17 -3
- package/dist/tools/fs/bash-program-position.js +25 -10
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/bash-readonly-classifier.js +8 -7
- package/dist/tools/fs/containment-face.d.ts +4 -0
- package/dist/tools/fs/containment-face.js +3 -0
- package/dist/tools/fs/fs-shared.d.ts +10 -0
- package/dist/tools/fs/fs-shared.js +18 -0
- package/dist/tools/fs/fs-write.js +4 -2
- package/dist/tools/fs/index.d.ts +3 -2
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/program-read-model.d.ts +99 -23
- package/dist/tools/fs/program-read-model.js +129 -55
- package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
- package/dist/tools/fs/program-read-model.rows.js +18 -10
- package/dist/tools/fs/read-deny-home.d.ts +35 -30
- package/dist/tools/fs/read-deny-home.js +45 -38
- package/dist/tools/fs/read-deny.d.ts +35 -27
- package/dist/tools/fs/read-deny.js +126 -92
- package/dist/tools/fs/removal-targets.d.ts +56 -23
- package/dist/tools/fs/removal-targets.js +74 -87
- package/dist/tools/fs/safety.d.ts +29 -22
- package/dist/tools/fs/safety.js +17 -11
- package/dist/tools/fs/search.js +10 -8
- package/dist/tools/fs/shell-read-argv.d.ts +4 -7
- package/dist/tools/fs/shell-read-argv.js +6 -8
- package/dist/tools/fs/shell-read-bindings.d.ts +203 -46
- package/dist/tools/fs/shell-read-bindings.js +488 -144
- package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
- package/dist/tools/fs/shell-read-builtins.js +43 -0
- package/dist/tools/fs/shell-read-check.d.ts +15 -1
- package/dist/tools/fs/shell-read-check.js +51 -42
- package/dist/tools/fs/shell-read-establish.js +9 -10
- package/dist/tools/fs/shell-read-functions.d.ts +22 -0
- package/dist/tools/fs/shell-read-functions.js +29 -0
- package/dist/tools/fs/shell-read-judge.d.ts +48 -18
- package/dist/tools/fs/shell-read-judge.js +33 -4
- package/dist/tools/fs/shell-read-plan.d.ts +13 -20
- package/dist/tools/fs/shell-read-plan.js +200 -194
- package/dist/tools/fs/shell-read-start.d.ts +80 -0
- package/dist/tools/fs/shell-read-start.js +99 -0
- package/dist/tools/fs/shell-read-word.d.ts +35 -6
- package/dist/tools/fs/shell-read-word.js +89 -9
- package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
- package/dist/tools/fs/shell-read-workdir.js +281 -0
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
- package/dist/tools/fs/shell-read-write-targets.js +14 -5
- package/dist/tools/fs/shell-reentry-text.d.ts +26 -26
- package/dist/tools/fs/shell-reentry-text.js +31 -34
- package/dist/tools/task-list.d.ts +1 -2
- package/dist/tools/web.js +1 -1
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +107 -143
- package/wire-changes/core@7.48.0.json +252 -0
- package/wire-changes/core@7.49.0.json +4765 -0
- package/dist/agents/teacher.d.ts +0 -159
- package/dist/agents/teacher.js +0 -577
- package/dist/agents/team.d.ts +0 -226
- package/dist/agents/team.js +0 -257
- package/dist/core/strategy-store.d.ts +0 -238
- package/dist/core/strategy-store.js +0 -253
- package/dist/orchestration/builtin-workflows.d.ts +0 -133
- package/dist/orchestration/builtin-workflows.js +0 -159
- package/dist/scenarios/env.d.ts +0 -40
- package/dist/scenarios/env.js +0 -39
- package/dist/scenarios/scenario-registry.d.ts +0 -110
- package/dist/scenarios/scenario-registry.js +0 -140
- package/dist/scenarios/teacher-quickstart.d.ts +0 -40
- package/dist/scenarios/teacher-quickstart.js +0 -12
- package/dist/stores/cc/lockfile.d.ts +0 -10
- package/dist/stores/cc/lockfile.js +0 -98
- package/dist/stores/cc/mailbox-store.d.ts +0 -20
- package/dist/stores/cc/mailbox-store.js +0 -255
- package/dist/stores/cc/roster-adapter.d.ts +0 -12
- package/dist/stores/cc/roster-adapter.js +0 -117
- package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
- package/dist/stores/cc/sidecar-transcript.js +0 -264
- package/dist/stores/cc/task-list-store.d.ts +0 -2
- package/dist/stores/cc/task-list-store.js +0 -125
- package/dist/stores/file/strategy-store.d.ts +0 -97
- package/dist/stores/file/strategy-store.js +0 -341
package/dist/core/allow-entry.js
CHANGED
|
@@ -3,15 +3,15 @@ import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, parsePermission
|
|
|
3
3
|
import { judgeRuleToolName, splitNamespacedName } from "./tool-name-aliases.js";
|
|
4
4
|
import { catalogToolNames, isShellFaceToolName } from "./tool-registry.js";
|
|
5
5
|
import { ALLOW_RULE_MEMBERS } from "./allow-rule-shadow.js";
|
|
6
|
-
import { COMMAND_RULE_TOOL,
|
|
6
|
+
import { COMMAND_RULE_TOOL, adjudicatePersistedDomainRules, adjudicatePersistedNameRules, domainRuleSubjectOf, findAdmittingRule, laneToolNamesOf, nameRuleSubjectOf, parseRuleText, programRunReachOf, ruleToolGrammarOf } from "./permission-rule-model.js";
|
|
7
7
|
import { pathRuleLaneAnswer } from "./runner/permission-rule-lanes.js";
|
|
8
8
|
import { callTargetReadingOf } from "./effective-path-target.js";
|
|
9
9
|
import { splitShellCompoundSegments } from "../tools/fs/bash-readonly-classifier.js";
|
|
10
10
|
import { mandateDisclosureOf } from "./ask-origin.js";
|
|
11
11
|
import { inlineUntrusted } from "./untrusted-text.js";
|
|
12
|
-
import { valueTypeLabel } from "
|
|
12
|
+
import { valueTypeLabel } from "./tool-name-list.js";
|
|
13
13
|
import { deliverEngineNotice } from "./engine-notice.js";
|
|
14
|
-
export const ALLOW_ENTRY_INERT_REASONS = Object.freeze(["wildcard_all", "namespace_wildcard", "
|
|
14
|
+
export const ALLOW_ENTRY_INERT_REASONS = Object.freeze(["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss"]);
|
|
15
15
|
export function nonStringMemberLabel(value) {
|
|
16
16
|
return `<not a string: ${valueTypeLabel(value)}>`;
|
|
17
17
|
}
|
|
@@ -69,30 +69,21 @@ function readAllowEntry(raw, behavior, roster) {
|
|
|
69
69
|
}
|
|
70
70
|
return row(isShellFaceToolName(name) ? { kind: "shell", name } : { kind: "tool", name });
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
if (ruleToolGrammarOf(name) === "path") {
|
|
84
|
-
const read = parseRuleText(raw, behavior);
|
|
85
|
-
if ("rule" in read) {
|
|
86
|
-
if (read.rule.match === "subpath" && read.rule.tool === READ_RULE_TOOL && behavior === "allow")
|
|
87
|
-
return row({ kind: "read_dir", rule: ruleRowOf(read.rule) });
|
|
88
|
-
if (behavior === "deny")
|
|
89
|
-
return row({ kind: "path", rule: ruleRowOf(read.rule) });
|
|
90
|
-
}
|
|
91
|
-
return inert("path_pattern");
|
|
72
|
+
const grammar = ruleToolGrammarOf(name);
|
|
73
|
+
if (grammar === undefined)
|
|
74
|
+
return inert("content_unsupported");
|
|
75
|
+
const read = parseRuleText(raw, behavior);
|
|
76
|
+
if ("rule" in read)
|
|
77
|
+
return row({ kind: grammar, rule: ruleRowOf(read.rule) });
|
|
78
|
+
if (grammar === "command" && behavior === "allow" && read.reject.code === "invalid.bare_interpreter_prefix") {
|
|
79
|
+
const wide = parseRuleText(raw, "deny");
|
|
80
|
+
if ("rule" in wide)
|
|
81
|
+
return row({ kind: "command", rule: ruleRowOf({ ...wide.rule, behavior: "allow" }) });
|
|
92
82
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
return inert(inertReasonOf(read.reject.code));
|
|
84
|
+
}
|
|
85
|
+
function inertReasonOf(code) {
|
|
86
|
+
return code === "unsupported.tool" ? "content_unsupported" : "grammar";
|
|
96
87
|
}
|
|
97
88
|
export function compileAllowEntry(raw, behavior, roster) {
|
|
98
89
|
const read = readAllowEntry(raw, behavior, roster);
|
|
@@ -150,8 +141,9 @@ export function autoStripped(compiled, call) {
|
|
|
150
141
|
case "command":
|
|
151
142
|
return shellContentStripped(shellRuleContent(compiled.rule));
|
|
152
143
|
case "namespace":
|
|
153
|
-
case "read_dir":
|
|
154
144
|
case "path":
|
|
145
|
+
case "name":
|
|
146
|
+
case "domain":
|
|
155
147
|
return false;
|
|
156
148
|
default: {
|
|
157
149
|
const exhaustive = compiled;
|
|
@@ -199,8 +191,7 @@ export function judgeAllowEntries(rows, req, behavior, ctx) {
|
|
|
199
191
|
}
|
|
200
192
|
}
|
|
201
193
|
}
|
|
202
|
-
const
|
|
203
|
-
const pathRows = live.filter((r) => r.compiled.kind === pathKind);
|
|
194
|
+
const pathRows = live.filter((r) => r.compiled.kind === "path");
|
|
204
195
|
if (pathRows.length > 0) {
|
|
205
196
|
const table = pathRows.map((r) => r.compiled.rule);
|
|
206
197
|
for (const name of laneToolNamesOf(req).filter((n) => ruleToolGrammarOf(n) === "path")) {
|
|
@@ -212,6 +203,18 @@ export function judgeAllowEntries(rows, req, behavior, ctx) {
|
|
|
212
203
|
}
|
|
213
204
|
}
|
|
214
205
|
}
|
|
206
|
+
for (const grammar of ["name", "domain"]) {
|
|
207
|
+
const familyRows = live.filter((r) => r.compiled.kind === grammar);
|
|
208
|
+
if (familyRows.length === 0)
|
|
209
|
+
continue;
|
|
210
|
+
const table = familyRows.map((r) => r.compiled.rule);
|
|
211
|
+
for (const name of laneToolNamesOf(req).filter((n) => ruleToolGrammarOf(n) === grammar)) {
|
|
212
|
+
const at = { tool: name, cwd: ctx.root, ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}) };
|
|
213
|
+
const verdict = grammar === "name" ? adjudicatePersistedNameRules(table, { ...at, name: nameRuleSubjectOf(name, req.args) }) : adjudicatePersistedDomainRules(table, { ...at, host: domainRuleSubjectOf(name, req.args) });
|
|
214
|
+
if (verdict !== undefined && verdict.behavior === behavior)
|
|
215
|
+
return [familyRows.find((r) => r.compiled.rule === verdict.rules[0]) ?? familyRows[0]];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
215
218
|
return undefined;
|
|
216
219
|
}
|
|
217
220
|
export function allowingRows(rows, req, mode) {
|
|
@@ -233,6 +236,9 @@ export class AllowEntryTable {
|
|
|
233
236
|
entries() {
|
|
234
237
|
return this.held.map((r) => r.entry);
|
|
235
238
|
}
|
|
239
|
+
holdsPathRows() {
|
|
240
|
+
return this.held.some((r) => r.compiled.kind === "path");
|
|
241
|
+
}
|
|
236
242
|
lane(ctx) {
|
|
237
243
|
return {
|
|
238
244
|
allowing: (req, mode) => {
|
|
@@ -319,6 +325,7 @@ const SHADOW_REASON = {
|
|
|
319
325
|
ancestor: "the task that delegated this one owns this question",
|
|
320
326
|
dangerous_delete: "this removal targets a protected location (the filesystem root, a top-level directory, a home directory, or a workspace directory or one of its ancestors) — it is cleared by confirming this call, never by an allow rule",
|
|
321
327
|
unverifiable_delete: "this removal could not be verified safe — it is cleared by confirming this call, never by an allow rule",
|
|
328
|
+
unverifiable_shell_text: "the text this shell will run cannot be read by the engine — it is cleared by confirming this call, never by an allow rule",
|
|
322
329
|
transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule",
|
|
323
330
|
org_rule: "an organization policy rule requires approval for this call",
|
|
324
331
|
governance_unavailable: "this deployment is org-governed and cannot currently read its organization policy",
|
|
@@ -329,7 +336,7 @@ const SHADOW_REASON = {
|
|
|
329
336
|
requires_user_interaction: "this tool's server declares that a call must be put to a person",
|
|
330
337
|
operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule",
|
|
331
338
|
shell_floor: mandateDisclosureOf("operator_always"),
|
|
332
|
-
|
|
339
|
+
target_unresolved: mandateDisclosureOf("target_unresolved"),
|
|
333
340
|
probe: mandateDisclosureOf("probe_mandate"),
|
|
334
341
|
write_protection: mandateDisclosureOf("write_protection"),
|
|
335
342
|
tool_marks_mcp: mandateDisclosureOf("tool_marks"),
|
|
@@ -405,7 +412,7 @@ export function inertEntryPhrase(e) {
|
|
|
405
412
|
case "unprefixed_namespace":
|
|
406
413
|
return 'tool_name: a "__" name with no protocol prefix';
|
|
407
414
|
case "unmintable_segment":
|
|
408
|
-
return `tool_name: a
|
|
415
|
+
return `tool_name: a namespaced name with a segment the engine never mints${spelling !== undefined ? `, write "${spelling}"` : ""}`;
|
|
409
416
|
default: {
|
|
410
417
|
const exhaustive = e.verdict;
|
|
411
418
|
return exhaustive;
|
|
@@ -422,7 +429,7 @@ export function allowedToolsNotGrantedNotice(inert, sessionId) {
|
|
|
422
429
|
return {
|
|
423
430
|
code: ALLOWED_TOOL_NOT_GRANTED_CODE,
|
|
424
431
|
message: `${inert.length} allowed-tools entr${inert.length === 1 ? "y grants" : "ies grant"} or refuse${inert.length === 1 ? "s" : ""} nothing — ${shown.join("; ")}${rest > 0 ? `; and ${rest} more` : ""}. ` +
|
|
425
|
-
"A list holding `*` voids the list, `mcp__*` names no server, a
|
|
432
|
+
"A list holding `*` voids the list, `mcp__*` names no server, a rule the grammar refuses (`grammar`) or one on a tool with no such rule form (`content_unsupported`: an allow by path is an `Edit(…)` or `Read(…)` rule) grants nothing, and a tool name must be spelled as the tool is mounted; name the tools (or `mcp__<server>`) instead." +
|
|
426
433
|
(refusing ? " Such an entry in a disallowed-tools list keeps its Skill from activating: a refusal that reads as nothing is not dropped." : ""),
|
|
427
434
|
detail: { ...(sessionId !== undefined ? { sessionId } : {}), entries: inert.map((e) => ({ ...e })) },
|
|
428
435
|
};
|
|
@@ -1,27 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/** every prefix is LEFT-ANCHORED with \`(?<![A-Za-z0-9])\` — without it, ordinary words whose
|
|
4
|
-
* TAIL spells a prefix were silently redacted (NETWORK-attached → NETWO[redacted], RTMARK-100,
|
|
5
|
-
* task_categories, monkey=abcd1234, MonkeyJumping…) while triggering unpredictably on suffix
|
|
6
|
-
* length. \`_\` is deliberately NOT in the anchor class: \`api_key=\`, \`STRIPE=sk_live_…\`-style glued
|
|
7
|
-
* assignments are REAL credential shapes that must keep scrubbing. The prefixed-token arm also
|
|
8
|
-
* drops the \`i\` flag: the real vendors' prefixes are lowercase-only (sk_/pk_/rk_/ghp_…), and the
|
|
9
|
-
* case-insensitive form is what turned every UPPERCASE technical word ending in RK/SK/PK into a
|
|
10
|
-
* false positive. */
|
|
11
|
-
export type RedactionConfidence = "high" | "medium" | "low";
|
|
12
|
-
/** Which module's rule table minted a finding (ANG-11 provenance). A closed set, and there is no public
|
|
13
|
-
* factory for a finding — a report's entries can only have been written by one of these tables running
|
|
14
|
-
* here, so "this finding says X" is an engine statement, not something a caller can hand-assemble into
|
|
15
|
-
* a report and have the pipeline endorse. */
|
|
16
|
-
export type RedactionSource = "arg-summary" | "untrusted-egress" | "secret-env";
|
|
1
|
+
import { type RedactionConfidence, type RedactionSource, type ValueFamilyRow } from "./credential-vocabulary.js";
|
|
2
|
+
export type { RedactionConfidence, RedactionSource } from "./credential-vocabulary.js";
|
|
17
3
|
/** One redaction hit: what was detected, where (ORIGINAL-input coordinates), how confidently, the marker
|
|
18
|
-
* literal written in its place,
|
|
4
|
+
* literal written in its place, which rule table minted it, and — present when a vocabulary row minted it — the
|
|
5
|
+
* value family (the row's stable id; a host-leak hit such as a URL or a path names none). */
|
|
19
6
|
export interface RedactionFinding {
|
|
20
7
|
kind: string;
|
|
21
8
|
span: readonly [number, number];
|
|
22
9
|
confidence: RedactionConfidence;
|
|
23
10
|
marker: string;
|
|
24
11
|
source: RedactionSource;
|
|
12
|
+
family?: string;
|
|
25
13
|
}
|
|
26
14
|
/** The minimum a finding must declare to be summarizable. Both text findings ({@link RedactionFinding})
|
|
27
15
|
* and the env arm's entry findings satisfy it, so {@link summarizeRedactions} is ONE helper rather than
|
|
@@ -56,13 +44,15 @@ export interface RedactionPass {
|
|
|
56
44
|
kind: string;
|
|
57
45
|
confidence: RedactionConfidence;
|
|
58
46
|
marker: string;
|
|
59
|
-
/** The
|
|
60
|
-
*
|
|
61
|
-
* {@link SECRET_PASSES}) still attributes its hits to the table that owns the rule, not to whoever ran it. */
|
|
47
|
+
/** The rule table that owns this pass's rule — copied verbatim onto every finding it mints (ANG-11), whoever
|
|
48
|
+
* runs the pass. */
|
|
62
49
|
source: RedactionSource;
|
|
63
50
|
re: RegExp;
|
|
64
51
|
/** A literal replacement (only `$1` substitution is used by these passes) or a replacer fn. */
|
|
65
52
|
replace: string | ((match: string, ...groups: string[]) => string);
|
|
53
|
+
/** The value family a hit belongs to: one id, or — for a pass joining several rows — the id of the row that
|
|
54
|
+
* matches at the hit's offset in the pass input. Absent = the pass is no vocabulary row. */
|
|
55
|
+
family?: string | ((input: string, at: number) => string);
|
|
66
56
|
}
|
|
67
57
|
/**
|
|
68
58
|
* Run the declared passes in order, collecting findings (original-input spans) when a report is given.
|
|
@@ -78,10 +68,13 @@ export interface RedactionPass {
|
|
|
78
68
|
* over-stripping, never a leak.
|
|
79
69
|
*/
|
|
80
70
|
export declare function runRedactionPasses(input: string, passes: readonly RedactionPass[], report?: RedactionReport): string;
|
|
81
|
-
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The egress view rendered as passes, in the vocabulary's order: one pass per group (a group of several rows is ONE
|
|
73
|
+
* leftmost alternation, its hits attributed to the row that matches at the hit's offset). A row whose wide form
|
|
74
|
+
* captures a label keeps it ahead of the marker; `replacers` renders a kind whose marker placement is a policy (the
|
|
75
|
+
* URL userinfo).
|
|
76
|
+
*/
|
|
77
|
+
export declare function egressPasses(groups: ReadonlyArray<readonly ValueFamilyRow[]>, replacers?: Readonly<Record<string, (match: string, ...groups: string[]) => string>>): RedactionPass[];
|
|
85
78
|
export declare function scrubSecrets(s: string, report?: RedactionReport): string;
|
|
86
79
|
/** A SHORT, SECRET-SCRUBBED primary-arg summary. Abbreviation REDUCES the surface; a final {@link scrubSecrets}
|
|
87
80
|
* pass is the leak boundary (the value is PERSISTED + SSE-forwarded and may be read by a platform operator in a
|
package/dist/core/arg-summary.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writtenAssignmentPrefix } from "../tools/fs/bash-program-position.js";
|
|
2
|
+
import { CREDENTIAL_VOCABULARY, egressPassGroups } from "./credential-vocabulary.js";
|
|
2
3
|
const ACTIVITY_ARG_MAX = 80;
|
|
3
4
|
const SENSITIVE_KEY = /token|secret|key|password|passwd|credential|auth/i;
|
|
4
5
|
export function summarizeRedactions(findings) {
|
|
@@ -12,72 +13,179 @@ export function summarizeRedactions(findings) {
|
|
|
12
13
|
const parts = [...counts].map(([label, n]) => `${label} x${n}`);
|
|
13
14
|
return `${findings.length} redaction${findings.length === 1 ? "" : "s"}: ${parts.join(", ")}`;
|
|
14
15
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
function passZeroMapper(batches) {
|
|
17
|
+
const cursors = batches.map(() => ({ i: 0, delta: 0 }));
|
|
18
|
+
return (pos) => {
|
|
19
|
+
let p = pos;
|
|
20
|
+
for (let b = batches.length - 1; b >= 0; b--) {
|
|
21
|
+
const edits = batches[b];
|
|
22
|
+
const c = cursors[b];
|
|
23
|
+
let mapped;
|
|
24
|
+
while (mapped === undefined && c.i < edits.length) {
|
|
25
|
+
const e = edits[c.i];
|
|
26
|
+
const outStart = e.at + c.delta;
|
|
27
|
+
if (p < outStart)
|
|
28
|
+
mapped = p - c.delta;
|
|
29
|
+
else if (p < outStart + e.insertedLen)
|
|
30
|
+
mapped = e.at;
|
|
31
|
+
else {
|
|
32
|
+
c.delta += e.insertedLen - e.removedLen;
|
|
33
|
+
c.i++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
p = mapped ?? p - c.delta;
|
|
37
|
+
}
|
|
38
|
+
return p;
|
|
39
|
+
};
|
|
27
40
|
}
|
|
28
41
|
const PREEXISTING_MARKER_RE = /\[redacted(?:-[a-z]+)?\]/g;
|
|
29
42
|
const FORMAT_CHAR_RE = /\p{Cf}/u;
|
|
30
43
|
const MAX_FORMAT_SLOT_SCANS = 64;
|
|
31
44
|
const REDACTED_WHOLE = "[redacted]";
|
|
32
|
-
function
|
|
45
|
+
function finding(pass, span, family) {
|
|
46
|
+
const f = { kind: pass.kind, confidence: pass.confidence, span, marker: pass.marker, source: pass.source };
|
|
47
|
+
if (family !== undefined)
|
|
48
|
+
f.family = family;
|
|
49
|
+
return f;
|
|
50
|
+
}
|
|
51
|
+
function insertedFor(pass, match, groups) {
|
|
52
|
+
return typeof pass.replace === "string"
|
|
53
|
+
? pass.replace.replace(/\$(\d)/g, (_m, d) => groups[Number(d) - 1] ?? "")
|
|
54
|
+
: pass.replace(match, ...groups);
|
|
55
|
+
}
|
|
56
|
+
function removedRegion(match, inserted) {
|
|
57
|
+
let head = 0;
|
|
58
|
+
while (head < match.length && head < inserted.length && match[head] === inserted[head])
|
|
59
|
+
head++;
|
|
60
|
+
let tail = 0;
|
|
61
|
+
while (tail < match.length - head && tail < inserted.length - head && match[match.length - 1 - tail] === inserted[inserted.length - 1 - tail])
|
|
62
|
+
tail++;
|
|
63
|
+
return [head, match.length - tail];
|
|
64
|
+
}
|
|
65
|
+
function soloHits(input, passes) {
|
|
66
|
+
const hits = [];
|
|
67
|
+
passes.forEach((pass, i) => {
|
|
68
|
+
for (const m of input.matchAll(new RegExp(pass.re.source, pass.re.flags.includes("g") ? pass.re.flags : `${pass.re.flags}g`))) {
|
|
69
|
+
const inserted = insertedFor(pass, m[0], m.slice(1));
|
|
70
|
+
if (inserted === m[0])
|
|
71
|
+
continue;
|
|
72
|
+
const [a, b] = removedRegion(m[0], inserted);
|
|
73
|
+
if (b <= a)
|
|
74
|
+
continue;
|
|
75
|
+
const at = m.index;
|
|
76
|
+
const family = typeof pass.family === "function" ? pass.family(input, at) : pass.family;
|
|
77
|
+
hits.push({ start: at + a, end: at + b, marker: inserted.slice(a, inserted.length - (m[0].length - b)), pass: i, family, matchStart: at, matchEnd: at + m[0].length });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return hits;
|
|
81
|
+
}
|
|
82
|
+
function enclosingHits(hits) {
|
|
83
|
+
const sorted = [...hits].sort((x, y) => x.start - y.start || y.end - x.end);
|
|
84
|
+
const outer = new Set();
|
|
85
|
+
let reach;
|
|
86
|
+
for (const r of sorted) {
|
|
87
|
+
if (reach !== undefined && reach.pass !== r.pass && reach.end >= r.end && reach.end - reach.start > r.end - r.start)
|
|
88
|
+
outer.add(reach);
|
|
89
|
+
if (reach === undefined || r.end > reach.end)
|
|
90
|
+
reach = r;
|
|
91
|
+
}
|
|
92
|
+
return [...outer];
|
|
93
|
+
}
|
|
94
|
+
function sequentialRemovals(batches) {
|
|
95
|
+
const removals = [];
|
|
96
|
+
for (let j = 0; j < batches.length; j++) {
|
|
97
|
+
const toPassZero = passZeroMapper(batches.slice(0, j));
|
|
98
|
+
for (const e of batches[j]) {
|
|
99
|
+
const start = toPassZero(e.at + e.head);
|
|
100
|
+
const end = toPassZero(e.at + e.removedLen - e.tail);
|
|
101
|
+
removals.push({ start, end: Math.max(start, end), marker: e.inserted.slice(e.head, e.insertedLen - e.tail), pass: e.pass, family: e.family });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return removals;
|
|
105
|
+
}
|
|
106
|
+
function renderRemovals(input, removals) {
|
|
107
|
+
const sorted = removals.filter((r) => r.end > r.start || r.marker !== "").sort((x, y) => x.start - y.start || y.end - x.end);
|
|
108
|
+
const edits = [];
|
|
109
|
+
let out = "";
|
|
110
|
+
let cursor = 0;
|
|
111
|
+
for (let i = 0; i < sorted.length;) {
|
|
112
|
+
const start = sorted[i].start;
|
|
113
|
+
let end = sorted[i].end;
|
|
114
|
+
let widest;
|
|
115
|
+
for (; i < sorted.length && (sorted[i].start < end || sorted[i].start === start || (sorted[i].marker === "" && sorted[i].start === end)); i++) {
|
|
116
|
+
const r = sorted[i];
|
|
117
|
+
if (r.end > end)
|
|
118
|
+
end = r.end;
|
|
119
|
+
if (r.marker !== "" && (widest === undefined || r.end - r.start > widest.end - widest.start))
|
|
120
|
+
widest = r;
|
|
121
|
+
}
|
|
122
|
+
const marker = widest?.marker ?? REDACTED_WHOLE;
|
|
123
|
+
out += input.slice(cursor, start) + marker;
|
|
124
|
+
cursor = end;
|
|
125
|
+
edits.push({ at: start, removedLen: end - start, insertedLen: marker.length, inserted: marker, family: widest?.family, head: 0, tail: 0, pass: widest?.pass ?? sorted[i - 1].pass });
|
|
126
|
+
}
|
|
127
|
+
return { out: out + input.slice(cursor), edits };
|
|
128
|
+
}
|
|
129
|
+
function runPasses(input, passes, findings, toOriginal) {
|
|
33
130
|
const batches = [];
|
|
34
131
|
let cur = input;
|
|
35
|
-
|
|
132
|
+
passes.forEach((pass, passIndex) => {
|
|
36
133
|
const edits = [];
|
|
134
|
+
const passInput = cur;
|
|
135
|
+
const toPassZero = passZeroMapper(batches.slice());
|
|
37
136
|
cur = cur.replace(pass.re, (...args) => {
|
|
38
137
|
const match = args[0];
|
|
39
138
|
const offset = args[args.length - 2];
|
|
40
139
|
const groups = args.slice(1, -2);
|
|
41
|
-
const inserted =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
s0 = mapBackOnePass(batches[i], s0);
|
|
50
|
-
e0 = mapBackOnePass(batches[i], e0);
|
|
51
|
-
}
|
|
52
|
-
report.findings.push({
|
|
53
|
-
kind: pass.kind,
|
|
54
|
-
confidence: pass.confidence,
|
|
55
|
-
span: [toOriginal(s0), toOriginal(e0)],
|
|
56
|
-
marker: pass.marker,
|
|
57
|
-
source: pass.source,
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
edits.push({ at: offset, removedLen: match.length, insertedLen: inserted.length, inserted });
|
|
61
|
-
}
|
|
140
|
+
const inserted = insertedFor(pass, match, groups);
|
|
141
|
+
if (inserted === match)
|
|
142
|
+
return inserted;
|
|
143
|
+
const family = typeof pass.family === "function" ? pass.family(passInput, offset) : pass.family;
|
|
144
|
+
if (findings !== undefined)
|
|
145
|
+
findings.push({ pass: passIndex, f: finding(pass, [toOriginal(toPassZero(offset)), toOriginal(toPassZero(offset + match.length))], family) });
|
|
146
|
+
const [a, b] = removedRegion(match, inserted);
|
|
147
|
+
edits.push({ at: offset, removedLen: match.length, insertedLen: inserted.length, inserted, family, head: a, tail: match.length - b, pass: passIndex });
|
|
62
148
|
return inserted;
|
|
63
149
|
});
|
|
64
150
|
batches.push(edits);
|
|
65
|
-
}
|
|
151
|
+
});
|
|
66
152
|
return { out: cur, batches };
|
|
67
153
|
}
|
|
154
|
+
function applyPasses(input, passes, report, toOriginal) {
|
|
155
|
+
const found = report === undefined ? undefined : [];
|
|
156
|
+
const plain = runPasses(input, passes, found, toOriginal);
|
|
157
|
+
const outer = enclosingHits(soloHits(input, passes));
|
|
158
|
+
const whole = outer.length === 0 ? undefined : renderRemovals(input, [...sequentialRemovals(plain.batches), ...outer]);
|
|
159
|
+
if (whole === undefined || whole.out === plain.out) {
|
|
160
|
+
if (report !== undefined)
|
|
161
|
+
report.findings.push(...found.map((x) => x.f));
|
|
162
|
+
return plain;
|
|
163
|
+
}
|
|
164
|
+
if (report !== undefined) {
|
|
165
|
+
const seen = new Set(found.map((x) => `${x.pass}:${x.f.span[0]}:${x.f.span[1]}`));
|
|
166
|
+
for (const h of outer) {
|
|
167
|
+
const span = [toOriginal(h.matchStart), toOriginal(h.matchEnd)];
|
|
168
|
+
const key = `${h.pass}:${span[0]}:${span[1]}`;
|
|
169
|
+
if (seen.has(key))
|
|
170
|
+
continue;
|
|
171
|
+
seen.add(key);
|
|
172
|
+
found.push({ pass: h.pass, f: finding(passes[h.pass], span, h.family) });
|
|
173
|
+
}
|
|
174
|
+
found.sort((x, y) => x.pass - y.pass || x.f.span[0] - y.f.span[0]);
|
|
175
|
+
report.findings.push(...found.map((x) => x.f));
|
|
176
|
+
}
|
|
177
|
+
return { out: whole.out, batches: [whole.edits] };
|
|
178
|
+
}
|
|
68
179
|
function replacedSpans(batches) {
|
|
69
180
|
const spans = [];
|
|
70
181
|
for (let j = 0; j < batches.length; j++) {
|
|
182
|
+
const toPassZero = passZeroMapper(batches.slice(0, j));
|
|
71
183
|
for (const e of batches[j]) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
for (let i = j - 1; i >= 0; i--) {
|
|
75
|
-
s0 = mapBackOnePass(batches[i], s0);
|
|
76
|
-
e0 = mapBackOnePass(batches[i], e0);
|
|
77
|
-
}
|
|
184
|
+
const s0 = toPassZero(e.at);
|
|
185
|
+
const e0 = toPassZero(e.at + e.removedLen);
|
|
78
186
|
if (e0 - s0 !== e.removedLen)
|
|
79
187
|
return undefined;
|
|
80
|
-
spans.push({ start: s0, end: e0, inserted: e.inserted, pass:
|
|
188
|
+
spans.push({ start: s0, end: e0, inserted: e.inserted, pass: e.pass, family: e.family });
|
|
81
189
|
}
|
|
82
190
|
}
|
|
83
191
|
spans.sort((a, b) => a.start - b.start);
|
|
@@ -159,7 +267,7 @@ export function runRedactionPasses(input, passes, report) {
|
|
|
159
267
|
continue;
|
|
160
268
|
for (const c of cutSpans) {
|
|
161
269
|
const o = viewOffsetToOriginal(c.start + cut, c.end + cut);
|
|
162
|
-
extra.push({ start: o.start, end: o.end
|
|
270
|
+
extra.push({ ...c, start: o.start, end: o.end });
|
|
163
271
|
}
|
|
164
272
|
}
|
|
165
273
|
extra.sort((a, b) => a.start - b.start);
|
|
@@ -173,10 +281,8 @@ export function runRedactionPasses(input, passes, report) {
|
|
|
173
281
|
continue;
|
|
174
282
|
}
|
|
175
283
|
spans.push({ start: r.start, end: r.end, inserted: r.inserted });
|
|
176
|
-
if (report !== undefined)
|
|
177
|
-
|
|
178
|
-
report.findings.push({ kind: pass.kind, confidence: pass.confidence, span: [r.start, r.end], marker: pass.marker, source: pass.source });
|
|
179
|
-
}
|
|
284
|
+
if (report !== undefined)
|
|
285
|
+
report.findings.push(finding(passes[r.pass], [r.start, r.end], r.family));
|
|
180
286
|
spans.sort((a, b) => a.start - b.start);
|
|
181
287
|
}
|
|
182
288
|
for (let i = 1; i < spans.length;) {
|
|
@@ -196,27 +302,22 @@ export function runRedactionPasses(input, passes, report) {
|
|
|
196
302
|
result += input.slice(cursor);
|
|
197
303
|
return result;
|
|
198
304
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
source: "arg-summary",
|
|
214
|
-
re: /(?<![A-Za-z0-9])((?:token|secret|key|password|passwd|credential|authorization)["']?\s*[=:]\s*["']?)[^\s"';|&]{4,}/gi,
|
|
215
|
-
replace: "$1[redacted]",
|
|
216
|
-
},
|
|
217
|
-
];
|
|
305
|
+
const BRACKET_MARKER = { "url-credentials": "[redacted-credentials]" };
|
|
306
|
+
const bracketMarker = (kind) => BRACKET_MARKER[kind] ?? "[redacted]";
|
|
307
|
+
const capturesLabel = (re) => new RegExp(`${re.source}|`).exec("").length > 1;
|
|
308
|
+
export function egressPasses(groups, replacers = {}) {
|
|
309
|
+
return groups.map((rows) => {
|
|
310
|
+
const head = rows[0];
|
|
311
|
+
const marker = bracketMarker(head.kind);
|
|
312
|
+
const re = rows.length === 1 ? head.match : new RegExp(rows.map((r) => `(?:${r.match.source})`).join("|"), head.match.flags);
|
|
313
|
+
const sticky = rows.map((r) => ({ id: r.id, re: new RegExp(r.match.source, r.match.flags.replace("g", "") + "y") }));
|
|
314
|
+
const family = rows.length === 1 ? head.id : (input, at) => sticky.find((s) => ((s.re.lastIndex = at), s.re.test(input)))?.id ?? head.id;
|
|
315
|
+
return { kind: head.kind, confidence: head.confidence, marker, source: head.source, re, replace: replacers[head.kind] ?? (capturesLabel(head.match) ? `$1${marker}` : marker), family };
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
const SHAPE_PASSES = egressPasses(egressPassGroups(CREDENTIAL_VOCABULARY).filter((rows) => rows[0].source === "arg-summary"));
|
|
218
319
|
export function scrubSecrets(s, report) {
|
|
219
|
-
return runRedactionPasses(s,
|
|
320
|
+
return runRedactionPasses(s, SHAPE_PASSES, report);
|
|
220
321
|
}
|
|
221
322
|
function truncCodePoints(s) {
|
|
222
323
|
const cp = Array.from(s);
|