@sema-agent/core 7.55.0 → 7.57.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 +1054 -0
- package/LICENSE +1 -1
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.js +1 -0
- package/dist/agents/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- package/dist/agents/list-agents-tool.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +7 -7
- package/dist/agents/org-delivery-gate.js +3 -4
- package/dist/agents/peer-directory.d.ts +22 -4
- package/dist/agents/peer-directory.js +24 -2
- package/dist/agents/peer-held-queue.d.ts +69 -49
- package/dist/agents/peer-held-queue.js +255 -106
- package/dist/agents/peer-session-drain.js +65 -45
- package/dist/agents/repair-loop.js +2 -2
- package/dist/agents/send-message-tool.js +7 -6
- package/dist/agents/subagent.d.ts +6 -4
- package/dist/agents/subagent.js +72 -68
- package/dist/agents/tool-filter.d.ts +7 -5
- package/dist/agents/tool-filter.js +12 -9
- package/dist/agents/verify.d.ts +3 -2
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +45 -80
- package/dist/brain/media-degrade.d.ts +18 -7
- package/dist/brain/media-degrade.js +13 -2
- package/dist/brain/model-capability.d.ts +37 -0
- package/dist/brain/model-capability.js +34 -0
- package/dist/brain/model-presets.d.ts +2 -8
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +23 -34
- package/dist/brain/openai.js +25 -96
- package/dist/brain/provider-dialect.d.ts +3 -2
- package/dist/brain/provider-dialect.js +2 -2
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +11 -11
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +13 -4
- package/dist/brain/request-params.js +21 -5
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/brain/stream-engine.d.ts +9 -0
- package/dist/brain/stream-engine.js +24 -10
- package/dist/brain/stream-shared.d.ts +5 -4
- package/dist/brain/stream-shared.js +4 -4
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/allow-entry.d.ts +23 -23
- package/dist/core/allow-entry.js +42 -46
- package/dist/core/allow-rule-shadow.d.ts +3 -3
- package/dist/core/approval-object.d.ts +21 -5
- package/dist/core/approval-object.js +44 -17
- package/dist/core/ask-origin.d.ts +66 -20
- package/dist/core/ask-origin.js +63 -23
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +3 -4
- package/dist/core/ask-unresolvable-notice.d.ts +8 -3
- package/dist/core/ask-unresolvable-notice.js +16 -2
- package/dist/core/auto-compaction.d.ts +71 -6
- package/dist/core/auto-compaction.js +42 -26
- package/dist/core/background-agent-store.d.ts +6 -2
- package/dist/core/background-agent-store.js +1 -1
- package/dist/core/checkpoint-generation.d.ts +53 -0
- package/dist/core/checkpoint-generation.js +35 -0
- package/dist/core/checkpoint-queries.d.ts +180 -0
- package/dist/core/checkpoint-queries.js +272 -0
- package/dist/core/checkpoint-requirements.d.ts +19 -1
- package/dist/core/checkpoint-requirements.js +6 -0
- package/dist/core/checkpoint-store.d.ts +105 -53
- package/dist/core/checkpoint-store.js +43 -20
- package/dist/core/cross-boundary-taint.d.ts +6 -5
- package/dist/core/cross-boundary-taint.js +5 -5
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +17 -17
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/engine-attestation.d.ts +93 -0
- package/dist/core/engine-attestation.js +70 -0
- package/dist/core/engine-capabilities.d.ts +4 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +32 -12
- package/dist/core/engine-notice.js +6 -0
- package/dist/core/file-history-store.d.ts +104 -22
- package/dist/core/file-history-store.js +37 -19
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +22 -10
- package/dist/core/gate-lanes.js +73 -65
- package/dist/core/gate-outcome.d.ts +26 -5
- package/dist/core/gate-outcome.js +26 -0
- package/dist/core/governance-codes.d.ts +5 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +19 -18
- package/dist/core/hooks.js +3 -1
- package/dist/core/host-floor.d.ts +128 -0
- package/dist/core/host-floor.js +206 -0
- package/dist/core/host-target.d.ts +38 -3
- package/dist/core/host-target.js +38 -5
- package/dist/core/mailbox-store.d.ts +62 -1
- package/dist/core/mailbox-store.js +59 -0
- package/dist/core/mcp-name-judge.d.ts +46 -0
- package/dist/core/mcp-name-judge.js +61 -0
- package/dist/core/mcp-probe.d.ts +1 -1
- package/dist/core/mcp-probe.js +2 -5
- package/dist/core/mcp.d.ts +5 -1
- package/dist/core/mcp.js +70 -64
- package/dist/core/memory-engine/consolidation-driver.js +4 -3
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/distiller.js +26 -17
- package/dist/core/memory-engine/engine.js +4 -4
- package/dist/core/memory-engine/layout.d.ts +60 -8
- package/dist/core/memory-engine/layout.js +70 -8
- package/dist/core/model-seat.d.ts +10 -3
- package/dist/core/mods/classic-events.d.ts +67 -0
- package/dist/core/mods/classic-events.js +1 -0
- package/dist/core/mods/dollar.d.ts +13 -0
- package/dist/core/mods/extension-call.d.ts +31 -0
- package/dist/core/mods/extension-call.js +43 -0
- package/dist/core/mods/kernel/dispatch.d.ts +20 -3
- package/dist/core/mods/kernel/dispatch.js +140 -69
- package/dist/core/mods/kernel/events.d.ts +47 -11
- package/dist/core/mods/kernel/events.js +66 -42
- package/dist/core/mods/kernel/index.d.ts +4 -4
- package/dist/core/mods/kernel/index.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -5
- package/dist/core/mods/kernel/receive.js +290 -17
- package/dist/core/mods/kernel/registration.d.ts +33 -2
- package/dist/core/mods/kernel/registration.js +6 -7
- package/dist/core/mods/kernel/site-rules.d.ts +44 -16
- package/dist/core/mods/kernel/site-rules.js +24 -42
- package/dist/core/mods/spec-seats.d.ts +69 -0
- package/dist/core/mods/spec-seats.js +114 -0
- package/dist/core/mods/stations.d.ts +28 -8
- package/dist/core/mods/stations.js +29 -13
- package/dist/core/mods/tool-call.d.ts +79 -0
- package/dist/core/mods/tool-call.js +152 -0
- package/dist/core/namespaced-rule-name.d.ts +32 -38
- package/dist/core/namespaced-rule-name.js +29 -36
- package/dist/core/parent-spec-seat.d.ts +6 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +3 -0
- package/dist/core/permission-rule-consent.d.ts +24 -3
- package/dist/core/permission-rule-consent.js +136 -41
- package/dist/core/permission-rule-model.d.ts +57 -5
- package/dist/core/permission-rule-model.js +90 -31
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +8 -4
- package/dist/core/permission-rule-provider.d.ts +5 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +3 -2
- package/dist/core/permission-rule-store.js +11 -2
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rule-syntax.d.ts +5 -4
- package/dist/core/permission-rule-syntax.js +2 -2
- package/dist/core/permission-rules.d.ts +4 -4
- package/dist/core/permission-rules.js +11 -20
- package/dist/core/persisted-rule-arms.d.ts +2 -2
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/principal-name.d.ts +20 -0
- package/dist/core/principal-name.js +22 -0
- package/dist/core/prompt-section-seat.js +4 -6
- package/dist/core/protocol-http-auth.d.ts +40 -5
- package/dist/core/protocol-http-auth.js +168 -4
- package/dist/core/protocol-naming.d.ts +20 -0
- package/dist/core/protocol-naming.js +20 -3
- package/dist/core/read-only-shell.d.ts +20 -5
- package/dist/core/read-only-shell.js +29 -14
- package/dist/core/remote-env.d.ts +37 -1
- package/dist/core/remote-env.js +11 -0
- package/dist/core/resume-startup-cause.d.ts +24 -2
- package/dist/core/resume-startup-cause.js +20 -1
- package/dist/core/retired-keys.d.ts +16 -0
- package/dist/core/retired-keys.js +16 -4
- package/dist/core/rewrite-rejudge.d.ts +60 -0
- package/dist/core/rewrite-rejudge.js +36 -0
- package/dist/core/roles.d.ts +28 -1
- package/dist/core/roles.js +81 -26
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- package/dist/core/rule-owner.d.ts +3 -3
- package/dist/core/rule-owner.js +3 -2
- package/dist/core/runner/announce-once-ledger.d.ts +14 -0
- package/dist/core/runner/announce-once-ledger.js +5 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/call-hook-stations.d.ts +3 -2
- package/dist/core/runner/caller-roster.d.ts +16 -4
- package/dist/core/runner/caller-roster.js +33 -6
- package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
- package/dist/core/runner/capability-withheld-seat.js +24 -0
- package/dist/core/runner/classifier-ladder.d.ts +7 -9
- package/dist/core/runner/classifier-ladder.js +3 -3
- package/dist/core/runner/compact-session.d.ts +10 -0
- package/dist/core/runner/compact-session.js +202 -0
- package/dist/core/runner/compaction-call-options.d.ts +2 -2
- package/dist/core/runner/compaction-seams.d.ts +21 -1
- package/dist/core/runner/compaction-seams.js +11 -8
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +50 -40
- package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
- package/dist/core/runner/cross-boundary-lane.js +40 -27
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/denial-limit-arms.js +1 -1
- package/dist/core/runner/derived-route-fallback.d.ts +13 -0
- package/dist/core/runner/derived-route-fallback.js +6 -0
- package/dist/core/runner/env-capability-census.d.ts +3 -2
- package/dist/core/runner/env-capability-census.js +9 -3
- package/dist/core/runner/file-history-request.d.ts +18 -0
- package/dist/core/runner/file-history-request.js +21 -13
- package/dist/core/runner/file-history-restore.d.ts +45 -0
- package/dist/core/runner/file-history-restore.js +46 -0
- package/dist/core/runner/gate-exit.d.ts +3 -3
- package/dist/core/runner/gate-exit.js +4 -3
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/permission-rule-lanes.d.ts +11 -11
- package/dist/core/runner/permission-rule-lanes.js +39 -17
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +18 -7
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
- package/dist/core/runner/prepare-ask-lane.js +5 -2
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
- package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
- package/dist/core/runner/prepare-config-doors.d.ts +35 -38
- package/dist/core/runner/prepare-config-doors.js +46 -28
- package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
- package/dist/core/runner/prepare-defer-classify.js +7 -8
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +7 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-gate-stations.js +10 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +5 -9
- package/dist/core/runner/prepare-hands-readface.js +17 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
- package/dist/core/runner/prepare-inherited-gate.js +5 -3
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.d.ts +2 -0
- package/dist/core/runner/prepare-park-ask.js +7 -7
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
- package/dist/core/runner/prepare-policy-chain.js +67 -76
- package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
- package/dist/core/runner/prepare-prompt-assembly.js +10 -8
- package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
- package/dist/core/runner/prepare-prompt-inputs.js +3 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
- package/dist/core/runner/prepare-protocol-tools.js +3 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-safety-scan.js +0 -17
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -6
- package/dist/core/runner/prepare-task.d.ts +5 -2
- package/dist/core/runner/prepare-task.js +48 -43
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +20 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +33 -23
- package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -7
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
- package/dist/core/runner/prepare-wiring-manifest.js +3 -3
- package/dist/core/runner/resume-admission.js +1 -1
- package/dist/core/runner/resume-apply.js +11 -12
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/resume-claim.d.ts +4 -2
- package/dist/core/runner/resume-claim.js +15 -8
- package/dist/core/runner/retired-runner-deps.js +1 -0
- package/dist/core/runner/rewind-files.d.ts +12 -0
- package/dist/core/runner/rewind-files.js +90 -0
- package/dist/core/runner/run-attachment-seats.js +2 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -1
- package/dist/core/runner/run-brain-sinks.js +4 -2
- package/dist/core/runner/run-harness-handlers.js +12 -4
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +40 -39
- package/dist/core/runner/run-notification-lane.d.ts +2 -0
- package/dist/core/runner/run-notification-lane.js +2 -2
- package/dist/core/runner/run-recovery-lanes.js +3 -4
- package/dist/core/runner/run-settle-and-teardown.js +7 -12
- package/dist/core/runner/run-terminal-adoption.js +3 -4
- package/dist/core/runner/run-turn-boundary.js +4 -15
- package/dist/core/runner/runtask.d.ts +10 -0
- package/dist/core/runner/runtask.js +35 -42
- package/dist/core/runner/send-message-continuation.js +1 -1
- package/dist/core/runner/session-read-file-states.d.ts +15 -0
- package/dist/core/runner/session-read-file-states.js +28 -0
- package/dist/core/runner/session-rule-policy.js +4 -3
- package/dist/core/runner/session-verb-doors.d.ts +28 -0
- package/dist/core/runner/session-verb-doors.js +48 -0
- package/dist/core/runner/session-write-ledger.d.ts +30 -0
- package/dist/core/runner/session-write-ledger.js +101 -0
- package/dist/core/runner/shell-env-withheld.d.ts +33 -0
- package/dist/core/runner/shell-env-withheld.js +51 -0
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +12 -15
- package/dist/core/runner/sub-agent-deny-lists.d.ts +25 -3
- package/dist/core/runner/sub-agent-deny-lists.js +25 -17
- package/dist/core/runner/synthetic-tools.d.ts +6 -0
- package/dist/core/runner/synthetic-tools.js +4 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -0
- package/dist/core/runner/teardown-bounded.js +1 -0
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +1 -3
- package/dist/core/runner/tool-end-body.d.ts +1 -1
- package/dist/core/runner/tool-end-body.js +10 -9
- package/dist/core/runner/tool-not-executed.d.ts +5 -0
- package/dist/core/runner/tool-not-executed.js +11 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -0
- package/dist/core/runner/tool-occurrence.js +7 -0
- package/dist/core/runner/turn-attachments.d.ts +33 -15
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +7 -7
- package/dist/core/safety-axis-vocab.d.ts +6 -4
- package/dist/core/safety-axis-vocab.js +6 -5
- package/dist/core/safety-merge-corpus.js +11 -3
- package/dist/core/secret-env.d.ts +30 -3
- package/dist/core/secret-env.js +47 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/session-policy-store.d.ts +32 -15
- package/dist/core/session-policy-store.js +156 -36
- package/dist/core/session-store.d.ts +29 -10
- package/dist/core/session-store.js +51 -19
- package/dist/core/session.d.ts +82 -16
- package/dist/core/session.js +53 -0
- package/dist/core/shell-read-silence.d.ts +11 -12
- package/dist/core/shell-read-silence.js +9 -5
- package/dist/core/shell-run-candidates.js +3 -1
- package/dist/core/shell-wrapper-projection.d.ts +1 -1
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/shell-wrapper-table.d.ts +14 -7
- package/dist/core/shell-wrapper-table.js +5 -4
- package/dist/core/side-query.js +10 -1
- package/dist/core/skill-grant.d.ts +7 -2
- package/dist/core/skill-grant.js +5 -0
- package/dist/core/skills-directory.js +6 -2
- package/dist/core/store-contracts/background-agent-store-contract.js +1 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +141 -2
- package/dist/core/store-contracts/file-history-store-contract.js +40 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +49 -1
- package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
- package/dist/core/store-contracts/peer-directory-contract.js +14 -2
- package/dist/core/store-contracts/session-repo-contract.js +51 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
- package/dist/core/store-contracts/session-store-contract.js +150 -14
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +32 -4
- package/dist/core/task-notification.d.ts +16 -12
- package/dist/core/task-registry-agent.d.ts +8 -4
- package/dist/core/task-registry-agent.js +14 -8
- package/dist/core/task-registry-shared.d.ts +35 -6
- package/dist/core/task-registry-shared.js +11 -0
- package/dist/core/task-registry.d.ts +10 -1
- package/dist/core/task-registry.js +12 -2
- package/dist/core/task-result.d.ts +18 -0
- package/dist/core/task-spec.d.ts +18 -13
- package/dist/core/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +23 -0
- package/dist/core/tool-catalog-entries.js +14 -2
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- package/dist/core/tool-model-gate.d.ts +2 -2
- package/dist/core/tool-name-aliases.d.ts +48 -18
- package/dist/core/tool-name-aliases.js +36 -19
- package/dist/core/tool-name-readings.d.ts +6 -32
- package/dist/core/tool-name-readings.js +2 -9
- package/dist/core/tool-policy.d.ts +78 -204
- package/dist/core/tool-policy.js +152 -204
- package/dist/core/tool-result-store.js +3 -0
- package/dist/core/tool-roster.d.ts +14 -19
- package/dist/core/tool-roster.js +11 -44
- package/dist/core/tool-spec-members.js +7 -2
- package/dist/core/tool-spec.d.ts +19 -11
- package/dist/core/tools.js +49 -9
- package/dist/core/trace.d.ts +6 -3
- package/dist/core/trace.js +2 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/untrusted-egress.d.ts +20 -0
- package/dist/core/untrusted-egress.js +77 -3
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/wiring-manifest.d.ts +9 -0
- package/dist/core/wiring-manifest.js +1 -0
- package/dist/core/workflow-journal-store.js +1 -1
- package/dist/engine/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
- package/dist/engine/execution-env/node-execution-env.js +11 -2
- package/dist/engine/harness/agent-harness.d.ts +32 -6
- package/dist/engine/harness/agent-harness.js +65 -9
- package/dist/engine/harness/types.d.ts +29 -2
- package/dist/engine/llm/types.d.ts +28 -11
- package/dist/engine/loop/agent-loop.d.ts +23 -4
- package/dist/engine/loop/agent-loop.js +42 -30
- package/dist/engine/loop/types.d.ts +16 -6
- package/dist/engine/session/memory-repo.d.ts +9 -2
- package/dist/engine/session/memory-repo.js +11 -1
- package/dist/engine/session/repo-utils.d.ts +6 -5
- package/dist/engine/session/repo-utils.js +14 -6
- package/dist/index.d.ts +34 -17
- package/dist/index.js +22 -11
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +2 -1
- package/dist/internal/harness.js +1 -0
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +6 -4
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +36 -18
- package/dist/primitives/credential-ref.d.ts +89 -0
- package/dist/primitives/credential-ref.js +125 -0
- package/dist/primitives/index.d.ts +2 -0
- package/dist/primitives/index.js +1 -0
- package/dist/prompt-assembly/artifact.d.ts +2 -2
- package/dist/prompt-assembly/artifact.js +5 -3
- package/dist/prompt-assembly/assemble.d.ts +3 -2
- package/dist/prompt-assembly/assemble.js +1 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
- package/dist/prompt-assembly/catalog/schema.js +34 -2
- package/dist/prompt-assembly/catalog/sections.js +0 -1
- package/dist/prompt-assembly/composer.d.ts +3 -1
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/overlay.js +3 -3
- package/dist/prompt-assembly/renderers.d.ts +1 -1
- package/dist/prompt-assembly/renderers.js +0 -3
- package/dist/prompt-assembly/role-base.d.ts +15 -0
- package/dist/prompt-assembly/role-base.js +9 -0
- package/dist/prompt-assembly/select.d.ts +39 -14
- package/dist/prompt-assembly/select.js +47 -16
- package/dist/prompt-assembly/sugar.d.ts +17 -11
- package/dist/prompt-assembly/sugar.js +8 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
- package/dist/prompt-assembly/tool-catalog.js +114 -4
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
- package/dist/prompt-assembly/turn-snapshot.js +0 -3
- package/dist/prompt-assembly/types.d.ts +0 -7
- package/dist/scenarios/full-body.d.ts +11 -11
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.js +4 -3
- package/dist/stores/file/adoption/marker.js +3 -2
- package/dist/stores/file/checkpoint-store.d.ts +21 -4
- package/dist/stores/file/checkpoint-store.js +38 -7
- package/dist/stores/file/file-history-store.js +18 -11
- package/dist/stores/file/index.js +2 -1
- package/dist/stores/file/mailbox-store.d.ts +2 -1
- package/dist/stores/file/mailbox-store.js +26 -1
- package/dist/stores/file/permission-rule-adopt.js +4 -3
- package/dist/stores/file/permission-rule-store.js +11 -5
- package/dist/stores/file/session-store.d.ts +29 -6
- package/dist/stores/file/session-store.js +42 -50
- package/dist/tools/artifact/artifact-tool.js +3 -2
- package/dist/tools/fs/bash-program-position.d.ts +19 -2
- package/dist/tools/fs/bash-program-position.js +56 -9
- package/dist/tools/fs/bash-readonly-classifier.d.ts +15 -19
- package/dist/tools/fs/bash-readonly-classifier.js +5 -10
- package/dist/tools/fs/fs-bash.js +15 -8
- package/dist/tools/fs/fs-glob.d.ts +86 -0
- package/dist/tools/fs/fs-glob.js +226 -0
- package/dist/tools/fs/fs-read.js +14 -14
- package/dist/tools/fs/fs-search-tools.js +7 -7
- package/dist/tools/fs/pattern-kill-guard.d.ts +23 -0
- package/dist/tools/fs/pattern-kill-guard.js +429 -0
- package/dist/tools/fs/pdf.d.ts +9 -6
- package/dist/tools/fs/pdf.js +3 -3
- package/dist/tools/fs/program-read-model.d.ts +57 -7
- package/dist/tools/fs/program-read-model.js +11 -1
- package/dist/tools/fs/program-read-model.rows.js +78 -21
- package/dist/tools/fs/read-deny-home.js +3 -2
- package/dist/tools/fs/removal-targets.d.ts +17 -7
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/search.d.ts +10 -0
- package/dist/tools/fs/search.js +20 -26
- package/dist/tools/fs/shell-read-argv.js +89 -12
- package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
- package/dist/tools/fs/shell-read-bindings.js +41 -0
- package/dist/tools/fs/shell-read-check.d.ts +10 -0
- package/dist/tools/fs/shell-read-check.js +13 -20
- package/dist/tools/fs/shell-read-environment.d.ts +5 -1
- package/dist/tools/fs/shell-read-environment.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +15 -0
- package/dist/tools/fs/shell-read-establish.js +19 -20
- package/dist/tools/fs/shell-read-identity.d.ts +12 -9
- package/dist/tools/fs/shell-read-identity.js +9 -4
- package/dist/tools/fs/shell-read-plan.js +24 -16
- package/dist/tools/fs/shell-read-start.d.ts +6 -1
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
- package/dist/tools/fs/shell-read-write-targets.js +2 -3
- package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
- package/dist/tools/fs/shell-reentry-text.js +40 -2
- package/dist/tools/todo.js +63 -63
- package/dist/tools/web.d.ts +19 -14
- package/dist/tools/web.js +46 -61
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +221 -7
- package/wire-changes/core-stores-sql@7.57.0.json +29 -0
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/core@7.57.0.json +1487 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -0
- package/wire-changes/mods-kernel@7.57.0.json +29 -0
- package/wire-changes/primitives@7.57.0.json +245 -0
|
@@ -1,11 +1,111 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { escapeForDisclosure, hasUnrenderableCharacters, parseRuleText, ruleAdmitsCommand, ruleBreadthWarningsOf,
|
|
2
|
+
import { COMMAND_RULE_TOOL, cardRuleFormOf, escapeForDisclosure, hasUnrenderableCharacters, parseRuleText, ruleAdmitsCommand, ruleBreadthWarningsOf, segmentCoverageOf, suggestRuleForHost, suggestRuleForName, suggestRuleForTool, suggestRulesForCommand, EDITED_RULE_BREADTH_WARNING_CODES, RULE_OFFER_KINDS, UNCOVERED_SEGMENT_REASONS, RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, isRuleBehavior, } from "./permission-rule-model.js";
|
|
3
3
|
import { readRuleOwner, sameRuleOwner } from "./rule-owner.js";
|
|
4
|
+
import { principalNameOf, readPrincipal } from "./principal-name.js";
|
|
5
|
+
import { isPlainRecord } from "./mods/kernel/receive.js";
|
|
4
6
|
import { effectiveOrThrow } from "./permission-rule-provider.js";
|
|
5
7
|
import { errText, isValidConsentScope, landRuleAdd, sameScope, writerOf } from "./permission-rule-store.js";
|
|
6
8
|
const isUncoveredSegmentReason = (v) => UNCOVERED_SEGMENT_REASONS.some((word) => v === word);
|
|
7
9
|
export const RULE_APPROVAL_KINDS = Object.freeze(["card", "import", "starter"]);
|
|
8
10
|
export const RULE_APPROVAL_STATES = Object.freeze(["pending", "approved", "redeemed"]);
|
|
11
|
+
const RECORD_OPTION_MEMBERS = { single: ["kind", "candidate"], batch: ["kind", "candidates", "segments", "uncoveredSegments", "uncoveredDetail"] };
|
|
12
|
+
export function readRuleOffer2(raw) {
|
|
13
|
+
if (!isPlainRecord(raw))
|
|
14
|
+
return { problem: "malformed" };
|
|
15
|
+
const kind = raw.kind;
|
|
16
|
+
if (typeof kind !== "string")
|
|
17
|
+
return { problem: "malformed" };
|
|
18
|
+
const word = RULE_OFFER_KINDS.find((k) => k === kind);
|
|
19
|
+
if (word === undefined)
|
|
20
|
+
return { problem: "unknown_word" };
|
|
21
|
+
const declared = RECORD_OPTION_MEMBERS[word];
|
|
22
|
+
if (Object.keys(raw).some((name) => !declared.includes(name)))
|
|
23
|
+
return { problem: "malformed" };
|
|
24
|
+
switch (word) {
|
|
25
|
+
case "single": {
|
|
26
|
+
const candidate = raw.candidate;
|
|
27
|
+
return isCandidateIndex(candidate) ? { offer: { kind: "single", candidate } } : { problem: "malformed" };
|
|
28
|
+
}
|
|
29
|
+
case "batch": {
|
|
30
|
+
const candidates = indexListOf(raw.candidates);
|
|
31
|
+
if (candidates === undefined || candidates.length === 0)
|
|
32
|
+
return { problem: "malformed" };
|
|
33
|
+
const segments = raw.segments;
|
|
34
|
+
const uncoveredSegments = raw.uncoveredSegments;
|
|
35
|
+
const detail = raw.uncoveredDetail;
|
|
36
|
+
const segmentList = segments === undefined ? undefined : stringListOf(segments);
|
|
37
|
+
if (segments !== undefined && segmentList === undefined)
|
|
38
|
+
return { problem: "malformed" };
|
|
39
|
+
if (uncoveredSegments !== undefined && !isCandidateIndex(uncoveredSegments))
|
|
40
|
+
return { problem: "malformed" };
|
|
41
|
+
const rows = detail === undefined ? undefined : reasonRowsOf(detail);
|
|
42
|
+
if (rows !== undefined && "problem" in rows)
|
|
43
|
+
return rows;
|
|
44
|
+
return {
|
|
45
|
+
offer: {
|
|
46
|
+
kind: "batch",
|
|
47
|
+
candidates,
|
|
48
|
+
...(segmentList !== undefined ? { segments: segmentList } : {}),
|
|
49
|
+
...(uncoveredSegments !== undefined ? { uncoveredSegments } : {}),
|
|
50
|
+
...(rows !== undefined ? { uncoveredDetail: rows.rows } : {}),
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
default: {
|
|
55
|
+
const unhandled = word;
|
|
56
|
+
return unhandled;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function isCandidateIndex(value) {
|
|
61
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
62
|
+
}
|
|
63
|
+
function indexListOf(value) {
|
|
64
|
+
if (!Array.isArray(value))
|
|
65
|
+
return undefined;
|
|
66
|
+
const length = value.length;
|
|
67
|
+
const out = [];
|
|
68
|
+
for (let i = 0; i < length; i++) {
|
|
69
|
+
const item = value[i];
|
|
70
|
+
if (!isCandidateIndex(item))
|
|
71
|
+
return undefined;
|
|
72
|
+
out.push(item);
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
function stringListOf(value) {
|
|
77
|
+
if (!Array.isArray(value))
|
|
78
|
+
return undefined;
|
|
79
|
+
const length = value.length;
|
|
80
|
+
const out = [];
|
|
81
|
+
for (let i = 0; i < length; i++) {
|
|
82
|
+
const item = value[i];
|
|
83
|
+
if (typeof item !== "string")
|
|
84
|
+
return undefined;
|
|
85
|
+
out.push(item);
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
function reasonRowsOf(value) {
|
|
90
|
+
if (!Array.isArray(value))
|
|
91
|
+
return { problem: "malformed" };
|
|
92
|
+
const length = value.length;
|
|
93
|
+
const rows = [];
|
|
94
|
+
for (let i = 0; i < length; i++) {
|
|
95
|
+
const row = value[i];
|
|
96
|
+
if (!isPlainRecord(row) || Object.keys(row).some((name) => name !== "segment" && name !== "reason"))
|
|
97
|
+
return { problem: "malformed" };
|
|
98
|
+
const segment = row.segment;
|
|
99
|
+
const reason = row.reason;
|
|
100
|
+
if (typeof segment !== "string" || typeof reason !== "string")
|
|
101
|
+
return { problem: "malformed" };
|
|
102
|
+
const word = UNCOVERED_SEGMENT_REASONS.find((r) => r === reason);
|
|
103
|
+
if (word === undefined)
|
|
104
|
+
return { problem: "unknown_word" };
|
|
105
|
+
rows.push({ segment, reason: word });
|
|
106
|
+
}
|
|
107
|
+
return { rows };
|
|
108
|
+
}
|
|
9
109
|
export const RULE_APPROVAL_RECORD_SCHEMA = 4;
|
|
10
110
|
export class InMemoryRuleApprovalRecordStore {
|
|
11
111
|
rows = new Map();
|
|
@@ -48,25 +148,25 @@ function mintId(deps, prefix) {
|
|
|
48
148
|
return `${prefix}_${Date.now().toString(36)}_${randomBytes(9).toString("base64url")}`;
|
|
49
149
|
}
|
|
50
150
|
function requirePrincipal(principal, entry) {
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
151
|
+
const name = principalNameOf(principal);
|
|
152
|
+
if (name === undefined) {
|
|
53
153
|
throw new Error(`${entry} requires a verified principal — refusing to create an approval record without one`);
|
|
54
154
|
}
|
|
55
|
-
return
|
|
155
|
+
return name;
|
|
56
156
|
}
|
|
57
157
|
function resolveCallerOwner(principal, owner, entry) {
|
|
58
158
|
if (owner !== undefined) {
|
|
59
159
|
const given = readRuleOwner(owner);
|
|
60
160
|
if (given === undefined) {
|
|
61
|
-
throw new Error(`${entry} requires a verified principal or the local owner — the owner given is neither (a principal owner names a
|
|
161
|
+
throw new Error(`${entry} requires a verified principal or the local owner — the owner given is neither (a principal owner names a principal name)`);
|
|
62
162
|
}
|
|
63
163
|
if (given.kind === "principal") {
|
|
64
|
-
if (
|
|
164
|
+
if (readPrincipal(principal).kind !== "absent" && principal !== given.principal) {
|
|
65
165
|
throw new Error(`${entry}: contradictory identity — principal "${principal}" and owner principal "${given.principal}" disagree`);
|
|
66
166
|
}
|
|
67
167
|
return given;
|
|
68
168
|
}
|
|
69
|
-
if (
|
|
169
|
+
if (readPrincipal(principal).kind !== "absent") {
|
|
70
170
|
throw new Error(`${entry}: contradictory identity — a principal and a local-owner were both given; a bucket has one owner`);
|
|
71
171
|
}
|
|
72
172
|
return given;
|
|
@@ -114,19 +214,17 @@ function approvalRecordDamageOf(rec) {
|
|
|
114
214
|
if (!Array.isArray(rec.offers) || rec.offers.length === 0)
|
|
115
215
|
return "the record carries no offers";
|
|
116
216
|
const claimed = new Set();
|
|
117
|
-
for (const [at,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return `offer ${at} has an unknown kind`;
|
|
122
|
-
if (offer.kind === "batch" && (!Array.isArray(offer.candidates) || offer.candidates.length === 0)) {
|
|
123
|
-
return `batch offer ${at} has no members`;
|
|
217
|
+
for (const [at, stored] of rec.offers.entries()) {
|
|
218
|
+
const read = readRuleOffer2(stored);
|
|
219
|
+
if ("problem" in read) {
|
|
220
|
+
return `offer ${at} is not a record option this engine reads (${read.problem}): an option is an object whose kind is ${RULE_OFFER_KINDS.join(" or ")}, whose candidate indices are non-negative integers (a batch with no members is not one), whose reason rows are segment/reason rows from the closed reason set, and which carries no other member`;
|
|
124
221
|
}
|
|
222
|
+
const offer = read.offer;
|
|
125
223
|
const members = offerMembersOf(offer);
|
|
126
224
|
const seen = new Set();
|
|
127
225
|
for (const member of members) {
|
|
128
|
-
if (
|
|
129
|
-
return `offer ${at} references candidate ${
|
|
226
|
+
if (rec.candidates[member] === undefined) {
|
|
227
|
+
return `offer ${at} references candidate ${member}, which the record does not carry`;
|
|
130
228
|
}
|
|
131
229
|
const cand = rec.candidates[member];
|
|
132
230
|
if (typeof cand !== "object" || cand === null || typeof cand.rule !== "string") {
|
|
@@ -138,6 +236,12 @@ function approvalRecordDamageOf(rec) {
|
|
|
138
236
|
if (rec.kind === "card" && cand.behavior !== "allow") {
|
|
139
237
|
return `card offer ${at} references candidate ${member}, a ${cand.behavior} rule — a card mints allow candidates only`;
|
|
140
238
|
}
|
|
239
|
+
if (rec.kind === "card") {
|
|
240
|
+
const read = parseRuleText(cand.rule, cand.behavior);
|
|
241
|
+
if ("rule" in read && read.rule.match === "tool" && (typeof rec.command === "string" || cardRuleFormOf(read.rule.tool) !== "tool")) {
|
|
242
|
+
return `card offer ${at} references candidate ${member}, the whole-tool rule "${escapeForDisclosure(read.rule.rule)}" — the engine mints one only on the whole-tool card of a tool with no rule grammar`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
141
245
|
if (!isValidConsentScope(cand.scope)) {
|
|
142
246
|
return `offer ${at} references candidate ${member}, whose scope is not a consent-face scope (global, project, or session)`;
|
|
143
247
|
}
|
|
@@ -150,29 +254,21 @@ function approvalRecordDamageOf(rec) {
|
|
|
150
254
|
}
|
|
151
255
|
if (offer.kind === "batch") {
|
|
152
256
|
if (rec.kind === "card") {
|
|
153
|
-
if (
|
|
257
|
+
if (offer.segments === undefined || offer.segments.length !== offer.candidates.length) {
|
|
154
258
|
return `card batch offer ${at} must carry exactly one source segment per member`;
|
|
155
259
|
}
|
|
156
|
-
if (
|
|
260
|
+
if (offer.uncoveredSegments === undefined) {
|
|
157
261
|
return `card batch offer ${at} must carry a non-negative uncovered-segment count`;
|
|
158
262
|
}
|
|
159
263
|
const detail = offer.uncoveredDetail;
|
|
160
|
-
if (
|
|
264
|
+
if (detail === undefined)
|
|
161
265
|
return `card batch offer ${at} must carry its uncovered-segment reason rows`;
|
|
162
266
|
if (detail.length !== offer.uncoveredSegments) {
|
|
163
267
|
return `card batch offer ${at} carries ${detail.length} reason rows for an uncovered-segment count of ${offer.uncoveredSegments} — one fact, two seats, and they must agree`;
|
|
164
268
|
}
|
|
165
|
-
for (const [ri, row] of detail.entries()) {
|
|
166
|
-
if (typeof row !== "object" ||
|
|
167
|
-
row === null ||
|
|
168
|
-
typeof row.segment !== "string" ||
|
|
169
|
-
!UNCOVERED_SEGMENT_REASONS.some((word) => row.reason === word)) {
|
|
170
|
-
return `card batch offer ${at} reason row ${ri} is not a segment/reason row from the closed reason set`;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
269
|
if (detail.length > 0) {
|
|
174
270
|
const rows = detail;
|
|
175
|
-
const table = typeof rec.command === "string" ? segmentCoverageOf(rec.command, { persisted: [] }, { tool:
|
|
271
|
+
const table = typeof rec.command === "string" ? segmentCoverageOf(rec.command, { persisted: [] }, { tool: COMMAND_RULE_TOOL, cwd: undefined }) : undefined;
|
|
176
272
|
if (table === undefined) {
|
|
177
273
|
return `card batch offer ${at} carries reason rows but the record's command cannot back them — a row without a readable source command is a row nobody can audit`;
|
|
178
274
|
}
|
|
@@ -289,10 +385,10 @@ export async function prepareCardApproval(opts) {
|
|
|
289
385
|
e.code = "config.invalid_argument";
|
|
290
386
|
throw e;
|
|
291
387
|
}
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
if (opts.toolName !== CARD_RULE_TOOL && oneRuleCard === undefined)
|
|
388
|
+
const form = cardRuleFormOf(opts.toolName);
|
|
389
|
+
if (form === undefined)
|
|
295
390
|
return undefined;
|
|
391
|
+
const oneRuleCard = form === "command" ? undefined : form;
|
|
296
392
|
const scope = (() => {
|
|
297
393
|
if (opts.scope !== undefined) {
|
|
298
394
|
if (!isValidConsentScope(opts.scope)) {
|
|
@@ -319,14 +415,14 @@ export async function prepareCardApproval(opts) {
|
|
|
319
415
|
try {
|
|
320
416
|
const view = await effectiveOrThrow(storeForOwner(opts.deps.provider, owner), opts.sessionId !== undefined ? { sessionId: opts.sessionId } : undefined);
|
|
321
417
|
const table = view.rules;
|
|
322
|
-
coverage = segmentCoverageOf(opts.command, { persisted: table }, { tool:
|
|
418
|
+
coverage = segmentCoverageOf(opts.command, { persisted: table }, { tool: COMMAND_RULE_TOOL, cwd: opts.cwd, sessionId: opts.sessionId, ...(opts.execCwd !== undefined ? { execCwd: opts.execCwd } : {}) });
|
|
323
419
|
}
|
|
324
420
|
catch {
|
|
325
421
|
coverage = undefined;
|
|
326
422
|
}
|
|
327
423
|
}
|
|
328
424
|
const suggested = oneRuleCard !== undefined
|
|
329
|
-
? [oneRuleCard === "name" ? suggestRuleForName(opts.toolName, opts.command) : suggestRuleForHost(opts.toolName, opts.command)].filter((o) => o !== undefined)
|
|
425
|
+
? [oneRuleCard === "name" ? suggestRuleForName(opts.toolName, opts.command) : oneRuleCard === "domain" ? suggestRuleForHost(opts.toolName, opts.command) : opts.command === "" ? suggestRuleForTool(opts.toolName) : undefined].filter((o) => o !== undefined)
|
|
330
426
|
: suggestRulesForCommand(opts.command, {
|
|
331
427
|
...(coverage !== undefined ? { coverage } : {}),
|
|
332
428
|
scope,
|
|
@@ -378,7 +474,6 @@ export async function prepareCardApproval(opts) {
|
|
|
378
474
|
candidates,
|
|
379
475
|
};
|
|
380
476
|
}
|
|
381
|
-
const CARD_RULE_TOOL = "Bash";
|
|
382
477
|
export async function confirmRuleApproval(opts) {
|
|
383
478
|
const caller = resolveCallerOwner(opts.principal, opts.owner, "confirmRuleApproval");
|
|
384
479
|
const no = (reason, detail) => ({
|
|
@@ -456,6 +551,9 @@ function checkEditedRuleText(text, command) {
|
|
|
456
551
|
const parsed = parseSubmittedSpelling(text);
|
|
457
552
|
if ("reject" in parsed)
|
|
458
553
|
return { ok: false, code: parsed.reject.code, message: parsed.reject.message };
|
|
554
|
+
if (parsed.rule.match === "tool") {
|
|
555
|
+
return { ok: false, message: `the edited rule "${parsed.rule.rule}" names the whole tool — a card's edit names a command rule, and a standing yes to every command is not one a card mints` };
|
|
556
|
+
}
|
|
459
557
|
if (!ruleAdmitsCommand(parsed.rule, command)) {
|
|
460
558
|
return {
|
|
461
559
|
ok: false,
|
|
@@ -748,18 +846,15 @@ export async function prepareCcImport(opts) {
|
|
|
748
846
|
skipped.push({ rule: String(entry), reason: `settings ${behavior} entry is not a string` });
|
|
749
847
|
continue;
|
|
750
848
|
}
|
|
751
|
-
if (!/^[A-Za-z][A-Za-z0-9_]*\(.*\)$/.test(entry)) {
|
|
752
|
-
const reason = /^[A-Za-z][A-Za-z0-9_-]*$/.test(entry)
|
|
753
|
-
? "unsupported.form: a bare tool-name entry is a name-set item, not a command rule — it stays in the settings file, unimported"
|
|
754
|
-
: "unsupported.form: not a command rule spelling this version imports — it stays in the settings file, unimported";
|
|
755
|
-
skipped.push({ rule: entry, reason });
|
|
756
|
-
continue;
|
|
757
|
-
}
|
|
758
849
|
const parsed = parseRuleText(entry, behavior);
|
|
759
850
|
if ("reject" in parsed) {
|
|
760
851
|
skipped.push({ rule: entry, reason: `${parsed.reject.code}: ${parsed.reject.message}` });
|
|
761
852
|
continue;
|
|
762
853
|
}
|
|
854
|
+
if (parsed.rule.match === "tool") {
|
|
855
|
+
skipped.push({ rule: entry, reason: "unsupported.form: a bare tool-name entry is a name-set item the host carries from the settings layer's own lists — it stays in the settings file, unimported" });
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
763
858
|
if (candidates.some((c) => c.behavior === behavior && c.rule === parsed.rule.rule && sameScope(c.scope, scope)))
|
|
764
859
|
continue;
|
|
765
860
|
candidates.push({ behavior, rule: parsed.rule.rule, scope });
|
|
@@ -77,6 +77,7 @@ import { type DenyFace } from "../tools/fs/read-deny.js";
|
|
|
77
77
|
import type { AssertAllKeysHandled, RuleOffersAbsence } from "./ask-origin.js";
|
|
78
78
|
import { type ToolCallLike } from "./tool-registry.js";
|
|
79
79
|
import { type HostReading } from "./host-target.js";
|
|
80
|
+
import { type NamedCall } from "./tool-name-readings.js";
|
|
80
81
|
import { type PathDenialEvidence, type PathFamily, type PathIdentity } from "../tools/fs/safety.js";
|
|
81
82
|
import { type TargetViews } from "./path-rule-binding.js";
|
|
82
83
|
/**
|
|
@@ -284,6 +285,18 @@ export declare const DOMAIN_RULE_MARKER = "domain:";
|
|
|
284
285
|
*/
|
|
285
286
|
export type RuleGrammar = "command" | "path" | "name" | "domain";
|
|
286
287
|
export declare function ruleToolGrammarOf(toolName: string): RuleGrammar | undefined;
|
|
288
|
+
/**
|
|
289
|
+
* THE rule a tool's approval card mints a "don't ask again" option in — one answer, read by the offer factory and the consent door
|
|
290
|
+
* alike: `command` for the command rule word (the shell card's command rules), `name` / `domain` for a tool of those grammars (the one
|
|
291
|
+
* exact value rule), `tool` for a call no rule word speaks for under any name it answers to ({@link laneToolNamesOf} empty: the
|
|
292
|
+
* whole-tool rule, the reference's fallback card), and `undefined` for the rest — a path tool (no path offer is minted), a shell-face
|
|
293
|
+
* sibling of the command word (its commands are `Bash(…)` rules), and a tool that answers to one of those under an alias it declares
|
|
294
|
+
* (a caller's shell wearing `Bash`: a one-click whole-tool yes on it would be a licence for every program): its card names that it has
|
|
295
|
+
* no rule to offer. `toolName` is the wire name the card mints on; `call` the call's names (absent: the wire name alone — the
|
|
296
|
+
* consent door, which holds no face).
|
|
297
|
+
*/
|
|
298
|
+
export type CardRuleForm = "command" | "name" | "domain" | "tool";
|
|
299
|
+
export declare function cardRuleFormOf(toolName: string, call?: NamedCall): CardRuleForm | undefined;
|
|
287
300
|
/** The parameter a shell-face tool's rule content names as one of the tool's own scalar arguments (`Monitor(description:*)`,
|
|
288
301
|
* `Bash(timeout:5)`), or undefined — the content is then a command spelling. */
|
|
289
302
|
export declare function shellRuleParamOf(tool: string, content: string): string | undefined;
|
|
@@ -311,11 +324,11 @@ export declare function nameRuleSubjectOf(toolName: string, args: unknown): stri
|
|
|
311
324
|
* domain tool's its own name — so a stored `Bash(…)` or `Edit(…)` row reaches a tool that answers to that name under another wire
|
|
312
325
|
* name, as a policy's rule does. Every lane that judges a call by a rule's word reads it here: the policy compiler, the
|
|
313
326
|
* person's stored rows, the org partition, the allow lists. Empty ⇒ no grammar speaks for the call. */
|
|
314
|
-
export declare function laneToolNamesOf(req:
|
|
327
|
+
export declare function laneToolNamesOf(req: NamedCall): readonly string[];
|
|
315
328
|
/** The match words a persisted rule is stored with, spelled once: {@link PersistedRuleMatch} is derived from this
|
|
316
329
|
* tuple (each form is documented there). A store backend that checks a stored row's `match` reads this value
|
|
317
330
|
* rather than keeping its own list. */
|
|
318
|
-
export declare const PERSISTED_RULE_MATCHES: readonly ["exact", "prefix", "wildcard", "pattern", "subpath", "path", "name", "name_prefix", "host", "subdomain"];
|
|
331
|
+
export declare const PERSISTED_RULE_MATCHES: readonly ["exact", "prefix", "wildcard", "pattern", "subpath", "path", "name", "name_prefix", "host", "subdomain", "tool"];
|
|
319
332
|
/**
|
|
320
333
|
* Match forms, one family per grammar (`prefix` and `wildcard` are one predicate):
|
|
321
334
|
* · `exact` — admits the one string the rule spells.
|
|
@@ -347,6 +360,8 @@ export declare const PERSISTED_RULE_MATCHES: readonly ["exact", "prefix", "wildc
|
|
|
347
360
|
* · `name` / `name_prefix` — the NAME grammar ({@link parseNameRuleContent}).
|
|
348
361
|
* · `host` / `subdomain` — the DOMAIN grammar ({@link parseDomainRuleContent}): one exact host, or every
|
|
349
362
|
* host below one domain.
|
|
363
|
+
* · `tool` — the WHOLE-TOOL form, a rule with no content (`SendUserFile`, `Bash`, `mcp__srv__get_issue`), on any tool:
|
|
364
|
+
* `command` is empty and the rule reaches every call that answers to the name it spells ({@link wholeToolRuleReaches}).
|
|
350
365
|
*/
|
|
351
366
|
export type PersistedRuleMatch = (typeof PERSISTED_RULE_MATCHES)[number];
|
|
352
367
|
/**
|
|
@@ -460,6 +475,9 @@ export type RuleRejectCode = "invalid.grammar" | "invalid.empty_command" | "inva
|
|
|
460
475
|
export interface RuleReject {
|
|
461
476
|
code: RuleRejectCode;
|
|
462
477
|
message: string;
|
|
478
|
+
/** For a text that is no rule spelling only because of white space (a tab, a no-break space included) around it or before its `(`:
|
|
479
|
+
* the rule spelling it is a blank away from ({@link respelledRuleTextOf}) — named in `message`, never read in its place. */
|
|
480
|
+
respelling?: string;
|
|
463
481
|
}
|
|
464
482
|
/** The parsed, canonical shape of one rule text under one behavior — everything but the scope and the
|
|
465
483
|
* provenance. The behavior is the parser's INPUT (it decides which validator floor applies), carried
|
|
@@ -718,6 +736,13 @@ export declare function ruleContentOf(parsed: ParsedPermissionRule): string | un
|
|
|
718
736
|
* most wants. The tightening behaviors therefore admit the interpreter-headed prefix form and change
|
|
719
737
|
* nothing else; the allow floor is unchanged.
|
|
720
738
|
*/
|
|
739
|
+
/**
|
|
740
|
+
* The rule spelling a text the rule syntax cannot read is a blank away from: the text with the white space (tabs included) around
|
|
741
|
+
* it and before its first `(` taken off, when that reads as a rule under `behavior` — its canonical text — else `undefined`. A text
|
|
742
|
+
* holding an invisible format character never gets here (its one caller refuses it first: `invalid.control_chars`, or `invalid.too_long`). Only what a refusal SAYS: a rule text is read as written ({@link parseRuleText}), so the way out is named, never
|
|
743
|
+
* taken (a door that reads the respelled text would be a second reading of the same text).
|
|
744
|
+
*/
|
|
745
|
+
export declare function respelledRuleTextOf(text: string, behavior: RuleBehavior): string | undefined;
|
|
721
746
|
export declare function parseRuleText(text: string, behavior: RuleBehavior): {
|
|
722
747
|
rule: ParsedRule;
|
|
723
748
|
} | {
|
|
@@ -745,8 +770,8 @@ export type NameRuleReach = "reached" | "not_reached" | "unread";
|
|
|
745
770
|
export declare function nameRuleReach(rule: Pick<PersistedRule, "tool" | "behavior" | "match" | "command">, name: string, values: readonly string[] | undefined): NameRuleReach;
|
|
746
771
|
/** Why a call is unread against a mounted row's rule ({@link nameRuleReach} `unread`) — the sentence every reader carries. */
|
|
747
772
|
export declare function nameValuesUnreadReason(tool: string): string;
|
|
748
|
-
/** Does a domain rule reach this host (as `hostOfUrl` reads it)?
|
|
749
|
-
*
|
|
773
|
+
/** Does a domain rule reach this host (as `hostOfUrl` reads it)? The pattern's own reach ({@link hostPatternAdmits}); a rule of
|
|
774
|
+
* any other family reaches no host. */
|
|
750
775
|
export declare function domainRuleAdmits(rule: Pick<PersistedRule, "match" | "command">, host: string): boolean;
|
|
751
776
|
/**
|
|
752
777
|
* The closed set of BASES a path-form pattern resolves against — facts of the CALL (its execution
|
|
@@ -1255,7 +1280,8 @@ export interface CallHosts {
|
|
|
1255
1280
|
* that does not parse, is not http(s), carries credentials, or names a host that does not read back as itself) is REFUSED by the
|
|
1256
1281
|
* tool's first eligible deny row, whatever host that row names, and otherwise ASKED by its first eligible ask row in the
|
|
1257
1282
|
* fail-closed form (`unreadable`, never a matched ask); no allow row reaches it, and with no deny or ask row it is reached by
|
|
1258
|
-
* nothing.
|
|
1283
|
+
* nothing. A stored row whose text the rule reader reads as no rule reaches this walk from the person's rule lane only as a deny
|
|
1284
|
+
* or an ask (its fields still tighten); the lane answers a call none of the rows refuses as one it cannot judge.
|
|
1259
1285
|
*/
|
|
1260
1286
|
export declare function adjudicatePersistedDomainRules(rules: readonly PersistedRule[], call: {
|
|
1261
1287
|
tool: string;
|
|
@@ -1264,6 +1290,32 @@ export declare function adjudicatePersistedDomainRules(rules: readonly Persisted
|
|
|
1264
1290
|
sessionId?: string;
|
|
1265
1291
|
scopeIdentity?: ScopeRootIdentity;
|
|
1266
1292
|
}): PersistedRuleVerdict | undefined;
|
|
1293
|
+
/**
|
|
1294
|
+
* THE predicate of a whole-tool rule (`match: "tool"`) over one call: the rule reaches the call iff the call answers to the name it
|
|
1295
|
+
* spells, under every name the call answers to (the model's spelling, the wire name, the aliases that resolve to it) — the
|
|
1296
|
+
* reference's tool-wide matcher. Every reader of a rule with no content asks it: an entry list's whole-tool row and a person's stored
|
|
1297
|
+
* whole-tool row alike.
|
|
1298
|
+
*/
|
|
1299
|
+
export declare function wholeToolRuleReaches(tool: string, call: NamedCall): boolean;
|
|
1300
|
+
/**
|
|
1301
|
+
* The whole-tool sibling of {@link adjudicatePersistedRules}: the same precedence walk (deny > ask > allow) over the whole-tool rows
|
|
1302
|
+
* (`match: "tool"`) that reach the call ({@link wholeToolRuleReaches}) and are eligible under their own tool ({@link eligiblePersisted},
|
|
1303
|
+
* the one predicate); the first behavior with such a row decides, the first table-order row of it is the answer.
|
|
1304
|
+
*/
|
|
1305
|
+
export declare function adjudicatePersistedToolRules(rules: readonly PersistedRule[], call: {
|
|
1306
|
+
request: NamedCall;
|
|
1307
|
+
cwd: string | undefined;
|
|
1308
|
+
sessionId?: string;
|
|
1309
|
+
scopeIdentity?: ScopeRootIdentity;
|
|
1310
|
+
}): PersistedRuleVerdict | undefined;
|
|
1311
|
+
/**
|
|
1312
|
+
* The ONE offer the card of a tool with no rule grammar carries ({@link cardRuleFormOf} `tool`): the whole-tool rule on its name (the
|
|
1313
|
+
* reference's fallback card, "don't ask again for <tool>"), or undefined when the name has no such rule (the round-trip law: the bare
|
|
1314
|
+
* name, parsed back as an allow, must be the whole-tool rule on that very name).
|
|
1315
|
+
*/
|
|
1316
|
+
export declare function suggestRuleForTool(tool: string): Extract<RuleOffer, {
|
|
1317
|
+
kind: "single";
|
|
1318
|
+
}> | undefined;
|
|
1267
1319
|
/**
|
|
1268
1320
|
* The ONE offer a host tool's approval card carries: the exact rule for the host the call reaches (`WebFetch(domain:<host>)`, the
|
|
1269
1321
|
* reference's "don't ask again for <host>" row), or undefined when no rule spells exactly that host (the round-trip law: the
|
|
@@ -2,13 +2,15 @@ import { homedir } from "node:os";
|
|
|
2
2
|
import { shellWordsOf } from "../shell/shell-words.js";
|
|
3
3
|
import { lexShell } from "../shell/lex.js";
|
|
4
4
|
import { readProgramPosition } from "../tools/fs/bash-program-position.js";
|
|
5
|
-
import { parsePermissionRule } from "./permission-rule-syntax.js";
|
|
5
|
+
import { isNameableToolName, parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
6
|
+
import { isCoveringRuleName } from "./namespaced-rule-name.js";
|
|
7
|
+
import { toolNameFaultOf } from "./tool-name-aliases.js";
|
|
6
8
|
import { compileReadDeny } from "../tools/fs/read-deny.js";
|
|
7
9
|
import { carriesShellRedirection, parseLeadingCommandName, splitShellCompoundSegments } from "../tools/fs/bash-readonly-classifier.js";
|
|
8
10
|
import { INLINE_TRUNCATION_MARK, inlineUntrusted } from "./untrusted-text.js";
|
|
9
|
-
import { catalogRuleFaceOf, hostTargetOf, isShellFaceToolName, pathTargetOf, protectivePathTargetOf } from "./tool-registry.js";
|
|
10
|
-
import { HOST_UNREADABLE_SENTENCE,
|
|
11
|
-
import { heldValues } from "./tool-name-readings.js";
|
|
11
|
+
import { catalogRuleFaceOf, catalogToolNames, hostTargetOf, isShellFaceToolName, pathTargetOf, protectivePathTargetOf } from "./tool-registry.js";
|
|
12
|
+
import { HOST_UNREADABLE_SENTENCE, hostPatternAdmits, readHostPattern, spelledHostPattern } from "./host-target.js";
|
|
13
|
+
import { heldBy, heldValues } from "./tool-name-readings.js";
|
|
12
14
|
import { carriesDotSegment, isAbsoluteForFamily, isIdentityDir, isPathIdentity, isShellRootedSpellingUnmapped, isUncIdentity, pathFamilyOf, pathIdentityOf } from "../tools/fs/safety.js";
|
|
13
15
|
import { bindPathRules, judgeRuleRows, rowsWhereTheyLead } from "./path-rule-binding.js";
|
|
14
16
|
import { readShellCommand } from "./shell-run-candidates.js";
|
|
@@ -135,6 +137,14 @@ export function ruleToolGrammarOf(toolName) {
|
|
|
135
137
|
return "domain";
|
|
136
138
|
return pathTargetOf(toolName) !== undefined ? "path" : undefined;
|
|
137
139
|
}
|
|
140
|
+
export function cardRuleFormOf(toolName, call = { toolName }) {
|
|
141
|
+
if (toolName === COMMAND_RULE_TOOL)
|
|
142
|
+
return "command";
|
|
143
|
+
const grammar = ruleToolGrammarOf(toolName);
|
|
144
|
+
if (grammar === "name" || grammar === "domain")
|
|
145
|
+
return grammar;
|
|
146
|
+
return grammar === undefined && laneToolNamesOf(call).length === 0 && laneToolNamesOf({ toolName }).length === 0 ? "tool" : undefined;
|
|
147
|
+
}
|
|
138
148
|
export function shellRuleParamOf(tool, content) {
|
|
139
149
|
const colon = content.indexOf(":");
|
|
140
150
|
if (colon <= 0)
|
|
@@ -172,7 +182,7 @@ function ruleWordOf(name) {
|
|
|
172
182
|
return COMMAND_RULE_TOOL;
|
|
173
183
|
return ruleToolGrammarOf(name) !== undefined ? name : undefined;
|
|
174
184
|
}
|
|
175
|
-
export const PERSISTED_RULE_MATCHES = Object.freeze(["exact", "prefix", "wildcard", "pattern", "subpath", "path", "name", "name_prefix", "host", "subdomain"]);
|
|
185
|
+
export const PERSISTED_RULE_MATCHES = Object.freeze(["exact", "prefix", "wildcard", "pattern", "subpath", "path", "name", "name_prefix", "host", "subdomain", "tool"]);
|
|
176
186
|
function isCommandMatch(match) {
|
|
177
187
|
return match === "exact" || match === "prefix" || match === "wildcard" || match === "pattern";
|
|
178
188
|
}
|
|
@@ -406,6 +416,28 @@ export function ruleContentOf(parsed) {
|
|
|
406
416
|
const content = parsed.ruleContent;
|
|
407
417
|
return content === undefined || (parsed.toolName === COMMAND_RULE_TOOL && foldSpacing(content) === "*") ? undefined : content;
|
|
408
418
|
}
|
|
419
|
+
export function respelledRuleTextOf(text, behavior) {
|
|
420
|
+
const outer = text.trim();
|
|
421
|
+
const open = outer.indexOf("(");
|
|
422
|
+
const candidate = open < 0 ? outer : outer.slice(0, open).replace(/\s+$/u, "") + outer.slice(open);
|
|
423
|
+
if (candidate === text || ruleSpellingOf(candidate) === undefined)
|
|
424
|
+
return undefined;
|
|
425
|
+
const read = parseRuleText(candidate, behavior);
|
|
426
|
+
return "rule" in read ? read.rule.rule : undefined;
|
|
427
|
+
}
|
|
428
|
+
function parseWholeToolRule(text, tool, behavior) {
|
|
429
|
+
if (!isNameableToolName(tool) || isCoveringRuleName(tool, behavior)) {
|
|
430
|
+
return reject("invalid.grammar", `"${text}" names a set of tools — a stored rule names one tool, or one tool's content; a set of tools is a list entry's form`);
|
|
431
|
+
}
|
|
432
|
+
const fault = toolNameFaultOf(tool, catalogToolNames(), behavior);
|
|
433
|
+
if (fault === undefined)
|
|
434
|
+
return { rule: { behavior, rule: tool, tool, match: "tool", command: "" } };
|
|
435
|
+
const why = fault.reason === "near_miss"
|
|
436
|
+
? `is another spelling of "${fault.currentName}", which the engine's tool catalog names — a rule names its tool exactly as spelled, so this one would reach no tool`
|
|
437
|
+
: `names no tool under that name${fault.guidance !== undefined ? ` — ${fault.guidance}` : ""}`;
|
|
438
|
+
const write = fault.currentName !== undefined && !why.includes(`"${fault.currentName}"`) ? `; write "${fault.currentName}"` : "";
|
|
439
|
+
return reject("unsupported.tool", `"${text}" ${why}${write}`);
|
|
440
|
+
}
|
|
409
441
|
export function parseRuleText(text, behavior) {
|
|
410
442
|
if (!isRuleBehavior(behavior)) {
|
|
411
443
|
return reject("invalid.grammar", `rule "${text}" was parsed under behavior ${escapeForDisclosure(behavior)}, which is not one of ${RULE_BEHAVIORS.join("/")}`);
|
|
@@ -417,11 +449,20 @@ export function parseRuleText(text, behavior) {
|
|
|
417
449
|
if (CONTROL_CHARS_RE.test(text)) {
|
|
418
450
|
return reject("invalid.control_chars", "rule text contains control characters (C0/C1, tab excepted), which cannot be part of a readable command");
|
|
419
451
|
}
|
|
420
|
-
const parsed =
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
return
|
|
452
|
+
const parsed = ruleSpellingOf(text);
|
|
453
|
+
if (parsed === undefined) {
|
|
454
|
+
const respelling = respelledRuleTextOf(text, behavior);
|
|
455
|
+
return {
|
|
456
|
+
reject: {
|
|
457
|
+
code: "invalid.grammar",
|
|
458
|
+
message: `"${text}" is not a rule spelling — a rule is the tool's name exactly as spelled, then its content in parentheses (no blank, tab or invisible character around the rule or before the "("), and the ")" ends it${respelling !== undefined ? `; spelled as a rule it is "${respelling}"` : ""}`,
|
|
459
|
+
...(respelling !== undefined ? { respelling } : {}),
|
|
460
|
+
},
|
|
461
|
+
};
|
|
424
462
|
}
|
|
463
|
+
const ruleContent = ruleContentOf(parsed);
|
|
464
|
+
if (ruleContent === undefined)
|
|
465
|
+
return parseWholeToolRule(text, parsed.toolName, behavior);
|
|
425
466
|
if (parsed.toolName !== COMMAND_RULE_TOOL) {
|
|
426
467
|
const grammar = ruleToolGrammarOf(parsed.toolName);
|
|
427
468
|
if (grammar === undefined) {
|
|
@@ -491,6 +532,8 @@ export function parseRuleText(text, behavior) {
|
|
|
491
532
|
return { rule: { behavior, rule: formatRuleText(command, match, COMMAND_RULE_TOOL), tool: COMMAND_RULE_TOOL, match, command } };
|
|
492
533
|
}
|
|
493
534
|
export function formatRuleText(command, match, tool) {
|
|
535
|
+
if (match === "tool")
|
|
536
|
+
return tool;
|
|
494
537
|
if (match === "subpath")
|
|
495
538
|
return `${tool}(//${command.startsWith("/") ? command.slice(1) : command}/**)`;
|
|
496
539
|
if (match === "path")
|
|
@@ -498,7 +541,7 @@ export function formatRuleText(command, match, tool) {
|
|
|
498
541
|
if (match === "name")
|
|
499
542
|
return `${tool}(${keyedValueParamOf(tool) !== undefined ? `${keyedValueParamOf(tool)}:` : ""}${command})`;
|
|
500
543
|
if (match === "host" || match === "subdomain")
|
|
501
|
-
return `${tool}(domain:${match
|
|
544
|
+
return `${tool}(domain:${spelledHostPattern({ match, host: command })})`;
|
|
502
545
|
return `${tool}(${command}${match === "prefix" || match === "name_prefix" ? ":*" : match === "wildcard" ? " *" : ""})`;
|
|
503
546
|
}
|
|
504
547
|
function parseNameRuleContent(text, tool, content, behavior, verifyCanonical = true) {
|
|
@@ -606,30 +649,26 @@ function parseDomainRuleContent(text, tool, content, behavior) {
|
|
|
606
649
|
if (!content.startsWith(DOMAIN_RULE_MARKER)) {
|
|
607
650
|
return reject("invalid.grammar", `a ${tool} rule names a host: ${tool}(domain:<host>) for one, ${tool}(domain:*.<domain>) for every host below a domain ("${text}")`);
|
|
608
651
|
}
|
|
609
|
-
const
|
|
610
|
-
if (
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
652
|
+
const read = readHostPattern(content.slice(DOMAIN_RULE_MARKER.length));
|
|
653
|
+
if ("problem" in read) {
|
|
654
|
+
switch (read.problem) {
|
|
655
|
+
case "every_host":
|
|
656
|
+
return reject("unsupported.wildcard", `"${text}" names every host — the whole tool is the bare ${tool} entry`);
|
|
657
|
+
case "inner_wildcard":
|
|
658
|
+
return reject("unsupported.wildcard", `a \`*\` in "${text}" other than a leading \`*.\` has no rule form — a ${tool} rule names one host, or every host below one domain with \`*.<domain>\``);
|
|
659
|
+
case "empty_label":
|
|
660
|
+
return reject("invalid.grammar", `"${text}" names a host with an empty label (a leading or doubled dot) — write the host itself, and every host below a domain as \`*.<domain>\``);
|
|
661
|
+
case "not_a_host":
|
|
662
|
+
return reject("invalid.grammar", `"${text}" does not name a host alone — write the host as a URL carries it, with no scheme, path, port or credentials`);
|
|
663
|
+
case "below_address":
|
|
664
|
+
return reject("invalid.grammar", `"${text}" names hosts below an address, which has none — write the address itself`);
|
|
665
|
+
}
|
|
620
666
|
}
|
|
621
|
-
|
|
622
|
-
return reject("invalid.grammar", `"${text}" names hosts below an address, which has none — write the address itself`);
|
|
623
|
-
const match = below ? "subdomain" : "host";
|
|
667
|
+
const { match, host } = read.pattern;
|
|
624
668
|
return { rule: { behavior, rule: formatRuleText(host, match, tool), tool, match, command: host } };
|
|
625
669
|
}
|
|
626
670
|
export function domainRuleAdmits(rule, host) {
|
|
627
|
-
|
|
628
|
-
return host === rule.command;
|
|
629
|
-
if (rule.match !== "subdomain" || isAddressHost(host) || !host.endsWith(`.${rule.command}`))
|
|
630
|
-
return false;
|
|
631
|
-
const labels = host.slice(0, -(rule.command.length + 1));
|
|
632
|
-
return labels !== "" && !labels.split(".").includes("");
|
|
671
|
+
return (rule.match === "host" || rule.match === "subdomain") && hostPatternAdmits({ match: rule.match, host: rule.command }, host);
|
|
633
672
|
}
|
|
634
673
|
function parsePathRuleContent(text, tool, content, behavior) {
|
|
635
674
|
if (behavior === "allow" && PATH_RULE_FACES[tool]?.allow === undefined) {
|
|
@@ -1303,7 +1342,7 @@ export function commandCoverageOf(rules, call) {
|
|
|
1303
1342
|
return covering.length > 0 ? { covering } : { uncovered: undefined };
|
|
1304
1343
|
}
|
|
1305
1344
|
function readsOnlyAsSegment(segment, lineObjection, whole) {
|
|
1306
|
-
return lineObjection === undefined && !movesShellCursor(segment) && readOnlyShellVerdict(segment,
|
|
1345
|
+
return lineObjection === undefined && !movesShellCursor(segment) && readOnlyShellVerdict(segment, { bound: () => lineDescriptorsOfText(whole) }).readOnly;
|
|
1307
1346
|
}
|
|
1308
1347
|
function firstEligibleDirectoryRule(rules, directory, call) {
|
|
1309
1348
|
for (const rule of rules) {
|
|
@@ -1419,6 +1458,26 @@ export function adjudicatePersistedDomainRules(rules, call) {
|
|
|
1419
1458
|
}
|
|
1420
1459
|
return undefined;
|
|
1421
1460
|
}
|
|
1461
|
+
export function wholeToolRuleReaches(tool, call) {
|
|
1462
|
+
return heldBy("policy.persistedToolRule", { has: (name) => name === tool }, call);
|
|
1463
|
+
}
|
|
1464
|
+
export function adjudicatePersistedToolRules(rules, call) {
|
|
1465
|
+
const at = { cwd: call.cwd, ...(call.sessionId !== undefined ? { sessionId: call.sessionId } : {}), ...(call.scopeIdentity !== undefined ? { scopeIdentity: call.scopeIdentity } : {}) };
|
|
1466
|
+
for (const behavior of RULE_BEHAVIORS_BY_PRECEDENCE) {
|
|
1467
|
+
const row = rules.find((rule) => rule.match === "tool" && wholeToolRuleReaches(rule.tool, call.request) && eligiblePersisted(rule, { ...at, tool: rule.tool }, behavior));
|
|
1468
|
+
if (row !== undefined)
|
|
1469
|
+
return { behavior, rules: [row] };
|
|
1470
|
+
}
|
|
1471
|
+
return undefined;
|
|
1472
|
+
}
|
|
1473
|
+
export function suggestRuleForTool(tool) {
|
|
1474
|
+
if (cardRuleFormOf(tool) !== "tool")
|
|
1475
|
+
return undefined;
|
|
1476
|
+
const parsed = parseRuleText(formatRuleText("", "tool", tool), "allow");
|
|
1477
|
+
if (!("rule" in parsed) || parsed.rule.match !== "tool" || parsed.rule.tool !== tool)
|
|
1478
|
+
return undefined;
|
|
1479
|
+
return { kind: "single", rule: parsed.rule.rule, match: "tool", command: "" };
|
|
1480
|
+
}
|
|
1422
1481
|
export function suggestRuleForHost(tool, host) {
|
|
1423
1482
|
if (ruleToolGrammarOf(tool) !== "domain")
|
|
1424
1483
|
return undefined;
|
|
@@ -224,6 +224,9 @@ export interface UnreadableOrgRow {
|
|
|
224
224
|
readonly rule: string;
|
|
225
225
|
readonly code: RuleRejectCode;
|
|
226
226
|
readonly detail?: string;
|
|
227
|
+
/** The rule spelling a row that is no rule spelling only because of white space (a tab, a no-break space) is a blank away from — the
|
|
228
|
+
* text to republish it as; the row itself is still read as unreadable (one spelling reader, fail-closed). */
|
|
229
|
+
readonly respelling?: string;
|
|
227
230
|
readonly behavior: "deny" | "ask";
|
|
228
231
|
readonly reach: OrgRowReach;
|
|
229
232
|
}
|
|
@@ -327,8 +330,9 @@ export declare function unenforceableOrgRules(rules: readonly OrgPermissionRule[
|
|
|
327
330
|
rule: string;
|
|
328
331
|
code: RuleRejectCode;
|
|
329
332
|
}>;
|
|
330
|
-
/** The reason an unreadable row's verdict carries — its place in the snapshot, its code, and the repair
|
|
331
|
-
|
|
333
|
+
/** The reason an unreadable row's verdict carries — its place in the snapshot, its code, and the repair: for a row that is no rule
|
|
334
|
+
* spelling only because of white space (a tab, a no-break space), its text and the spelling to republish it as. */
|
|
335
|
+
export declare function unreadableOrgRowReason(row: Pick<UnreadableOrgRow, "index" | "code" | "detail" | "rule" | "respelling">): string;
|
|
332
336
|
/** The ONE clause for an org verdict that carries an `unreadable` reason — a rule the call could not be read against, or
|
|
333
337
|
* a row this layer cannot read — on a refusal and on a question alike. */
|
|
334
338
|
export declare function orgUnreadableClause(reason: string): string;
|