@sema-agent/core 7.54.1 → 7.56.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 +950 -0
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/builtin-agents.d.ts +12 -14
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.d.ts +36 -0
- package/dist/agents/cc-peer-directory.js +139 -0
- package/dist/agents/cc-peer-wire.d.ts +105 -0
- package/dist/agents/cc-peer-wire.js +98 -0
- package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
- package/dist/agents/cc-uds-peer-channel.js +457 -0
- package/dist/agents/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- package/dist/agents/cross-session-envelope.d.ts +4 -1
- package/dist/agents/cross-session-envelope.js +8 -1
- package/dist/agents/cross-session-judge.d.ts +2 -2
- package/dist/agents/list-agents-tool.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +9 -8
- package/dist/agents/observer.d.ts +4 -5
- package/dist/agents/observer.js +2 -1
- package/dist/agents/peer-admission.d.ts +6 -0
- package/dist/agents/peer-admission.js +4 -1
- package/dist/agents/peer-directory.d.ts +65 -13
- package/dist/agents/peer-directory.js +90 -25
- package/dist/agents/peer-notices.d.ts +1 -1
- package/dist/agents/peer-session-drain.d.ts +3 -1
- package/dist/agents/peer-session-drain.js +3 -2
- package/dist/agents/read-inbox-tool.js +2 -1
- package/dist/agents/repair-loop.js +2 -2
- package/dist/agents/retain-ledger.d.ts +1 -1
- package/dist/agents/roster-store.d.ts +1 -1
- package/dist/agents/send-message-tool.d.ts +10 -0
- package/dist/agents/send-message-tool.js +37 -8
- package/dist/agents/subagent.d.ts +39 -82
- package/dist/agents/subagent.js +109 -106
- package/dist/agents/tool-filter.d.ts +31 -46
- package/dist/agents/tool-filter.js +13 -33
- package/dist/agents/verify.d.ts +6 -5
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +43 -81
- package/dist/brain/errors.d.ts +15 -0
- package/dist/brain/errors.js +10 -0
- 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 +6 -12
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +27 -35
- package/dist/brain/openai.js +30 -98
- package/dist/brain/provider-dialect.d.ts +39 -3
- package/dist/brain/provider-dialect.js +28 -0
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +12 -12
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +62 -9
- package/dist/brain/request-params.js +42 -7
- package/dist/brain/retry.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +15 -0
- package/dist/brain/route-adjudicator.js +15 -0
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/brain/stream-engine.js +6 -5
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/advisor-verdict.d.ts +120 -0
- package/dist/core/advisor-verdict.js +92 -0
- package/dist/core/agent-definition.d.ts +17 -8
- package/dist/core/allow-entry.d.ts +69 -36
- package/dist/core/allow-entry.js +81 -52
- package/dist/core/allow-rule-shadow.d.ts +10 -3
- package/dist/core/approval-object.d.ts +2 -1
- package/dist/core/approval-object.js +6 -6
- package/dist/core/ask-origin.d.ts +127 -29
- package/dist/core/ask-origin.js +87 -25
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +12 -7
- 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 +11 -8
- package/dist/core/auto-compaction.js +4 -2
- package/dist/core/auto-mode-arming.d.ts +2 -2
- package/dist/core/auto-mode-defaults.d.ts +8 -8
- package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
- package/dist/core/auto-mode-prompt.d.ts +1 -1
- package/dist/core/auto-mode.d.ts +17 -9
- package/dist/core/auto-mode.js +9 -6
- package/dist/core/background-agent-store.d.ts +3 -3
- package/dist/core/canonical-json.d.ts +1 -1
- package/dist/core/canonical-json.js +2 -2
- 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 -4
- package/dist/core/checkpoint-requirements.js +8 -14
- package/dist/core/checkpoint-store.d.ts +165 -72
- package/dist/core/checkpoint-store.js +79 -82
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +3 -16
- package/dist/core/compliance.d.ts +2 -2
- package/dist/core/context-edit.d.ts +6 -7
- package/dist/core/cross-boundary-taint.d.ts +11 -4
- package/dist/core/cross-boundary-taint.js +3 -3
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +19 -19
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/effective-path-target.d.ts +1 -1
- 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 +45 -12
- package/dist/core/exec-output-tail.d.ts +1 -1
- package/dist/core/file-history-retention.d.ts +1 -1
- package/dist/core/file-history-store.d.ts +147 -21
- package/dist/core/file-history-store.js +58 -32
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -11
- package/dist/core/gate-lanes.js +81 -68
- package/dist/core/gate-outcome.d.ts +40 -6
- package/dist/core/gate-outcome.js +56 -0
- package/dist/core/governance-codes.d.ts +17 -3
- package/dist/core/governance-codes.js +16 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +21 -20
- 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 +84 -0
- package/dist/core/host-target.js +92 -0
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/lsp-diagnostics.d.ts +4 -4
- package/dist/core/lsp.d.ts +3 -3
- package/dist/core/mailbox-store.d.ts +4 -0
- package/dist/core/mcp-connection-pool.d.ts +18 -2
- package/dist/core/mcp-connection-pool.js +53 -6
- package/dist/core/mcp-failure.d.ts +23 -4
- package/dist/core/mcp-failure.js +26 -11
- package/dist/core/mcp-listing-drift.d.ts +10 -0
- package/dist/core/mcp-listing-drift.js +6 -0
- package/dist/core/mcp-server-link.d.ts +173 -0
- package/dist/core/mcp-server-link.js +127 -0
- package/dist/core/mcp-server-spec.d.ts +4 -2
- package/dist/core/mcp-session-end.d.ts +26 -0
- package/dist/core/mcp-session-end.js +29 -0
- package/dist/core/mcp-startup-request.d.ts +17 -0
- package/dist/core/mcp-startup-request.js +17 -0
- package/dist/core/mcp.d.ts +17 -13
- package/dist/core/mcp.js +240 -189
- package/dist/core/media-byte-cap.d.ts +1 -1
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/engine.d.ts +9 -9
- 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 +65 -6
- package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
- package/dist/core/memory-engine/tools.js +4 -1
- package/dist/core/mode-policy.d.ts +1 -1
- 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 +44 -24
- package/dist/core/namespaced-rule-name.js +50 -43
- package/dist/core/output-style.d.ts +1 -1
- package/dist/core/param-rule-reach.d.ts +15 -0
- package/dist/core/param-rule-reach.js +30 -0
- package/dist/core/parent-spec-seat.d.ts +13 -1
- package/dist/core/parent-spec-seat.js +6 -0
- package/dist/core/park-selfcheck.js +1 -0
- package/dist/core/pause-registry.d.ts +16 -5
- package/dist/core/pause-registry.js +6 -2
- package/dist/core/peer-channel.d.ts +70 -0
- package/dist/core/peer-channel.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +30 -5
- package/dist/core/permission-rule-consent.js +147 -50
- package/dist/core/permission-rule-model.d.ts +245 -65
- package/dist/core/permission-rule-model.js +421 -107
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +7 -3
- package/dist/core/permission-rule-provider.d.ts +6 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +22 -26
- package/dist/core/permission-rule-store.js +12 -6
- package/dist/core/permission-rule-sync.d.ts +11 -2
- package/dist/core/permission-rule-sync.js +11 -3
- 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 +53 -15
- package/dist/core/permission-rules.js +125 -100
- package/dist/core/persisted-rule-arms.d.ts +6 -4
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/present-plan-tool.js +3 -1
- 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 +26 -5
- package/dist/core/protocol-http-auth.js +137 -4
- package/dist/core/protocol-naming.d.ts +2 -2
- package/dist/core/read-only-shell-table.d.ts +1 -1
- package/dist/core/read-only-shell.d.ts +1 -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 +34 -3
- package/dist/core/roles.js +66 -53
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- package/dist/core/rule-offer-read.d.ts +53 -0
- package/dist/core/rule-offer-read.js +146 -0
- package/dist/core/rule-owner.d.ts +46 -0
- package/dist/core/rule-owner.js +29 -0
- package/dist/core/runner/advisor-instructions.d.ts +70 -0
- package/dist/core/runner/advisor-instructions.js +61 -0
- package/dist/core/runner/advisor-tool.d.ts +33 -0
- package/dist/core/runner/advisor-tool.js +112 -0
- package/dist/core/runner/announce-once-ledger.d.ts +18 -26
- package/dist/core/runner/announce-once-ledger.js +19 -46
- package/dist/core/runner/approval-feedback.js +6 -3
- package/dist/core/runner/assemble-result.d.ts +2 -1
- 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 +21 -2
- package/dist/core/runner/caller-roster.js +38 -0
- 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 +33 -13
- package/dist/core/runner/classifier-ladder.js +15 -14
- package/dist/core/runner/compaction-restate.d.ts +10 -6
- package/dist/core/runner/compaction-restate.js +9 -3
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +40 -33
- package/dist/core/runner/conversation-segment.d.ts +28 -0
- package/dist/core/runner/conversation-segment.js +42 -0
- package/dist/core/runner/cross-boundary-lane.d.ts +21 -16
- package/dist/core/runner/cross-boundary-lane.js +58 -34
- package/dist/core/runner/decide-continuation.d.ts +7 -4
- package/dist/core/runner/decide-continuation.js +2 -2
- package/dist/core/runner/denial-limit-arms.d.ts +4 -4
- package/dist/core/runner/denial-limit-arms.js +1 -1
- package/dist/core/runner/derived-route-fallback.d.ts +24 -24
- package/dist/core/runner/derived-route-fallback.js +9 -7
- 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 +9 -3
- package/dist/core/runner/gate-exit.js +11 -5
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/initial-run-state.js +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.js +38 -15
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +19 -8
- package/dist/core/runner/prepare-advisor.d.ts +63 -0
- package/dist/core/runner/prepare-advisor.js +77 -0
- 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 +5 -4
- package/dist/core/runner/prepare-config-doors.d.ts +31 -38
- package/dist/core/runner/prepare-config-doors.js +57 -34
- 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-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +41 -73
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -5
- package/dist/core/runner/prepare-gate-stations.js +12 -8
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
- package/dist/core/runner/prepare-hands-readface.js +15 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +11 -7
- package/dist/core/runner/prepare-inherited-gate.js +8 -6
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +12 -12
- package/dist/core/runner/prepare-policy-chain.d.ts +7 -4
- package/dist/core/runner/prepare-policy-chain.js +68 -81
- package/dist/core/runner/prepare-project-context.d.ts +5 -2
- package/dist/core/runner/prepare-project-context.js +6 -3
- 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 +4 -6
- package/dist/core/runner/prepare-protocol-tools.d.ts +4 -2
- package/dist/core/runner/prepare-protocol-tools.js +5 -4
- package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
- package/dist/core/runner/prepare-safety-scan.js +8 -23
- 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 +1 -1
- package/dist/core/runner/prepare-task.js +41 -35
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +24 -18
- 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 +11 -4
- 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/resume-policy-outcome.js +1 -1
- package/dist/core/runner/retired-runner-deps.js +2 -1
- package/dist/core/runner/rewind-files.d.ts +15 -0
- package/dist/core/runner/rewind-files.js +132 -0
- package/dist/core/runner/run-attachment-seats.js +2 -2
- 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-compaction-machinery.d.ts +1 -1
- package/dist/core/runner/run-compaction-machinery.js +2 -12
- package/dist/core/runner/run-git-lane.d.ts +1 -0
- package/dist/core/runner/run-harness-handlers.js +14 -7
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +43 -18
- package/dist/core/runner/run-settle-and-teardown.js +3 -2
- package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
- package/dist/core/runner/run-turn-boundary.d.ts +1 -0
- package/dist/core/runner/run-turn-boundary.js +15 -22
- package/dist/core/runner/runtask.d.ts +3 -0
- package/dist/core/runner/runtask.js +8 -9
- 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.d.ts +22 -21
- package/dist/core/runner/session-rule-policy.js +17 -31
- 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/side-call-account.d.ts +32 -8
- package/dist/core/runner/side-call-account.js +23 -1
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runner/strict-output-schema.d.ts +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -6
- package/dist/core/runner/synthetic-tools.d.ts +16 -13
- package/dist/core/runner/synthetic-tools.js +8 -3
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +3 -4
- 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-face-overlay.d.ts +2 -1
- package/dist/core/runner/tool-face-overlay.js +17 -1
- 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/tool-progress-lane.d.ts +2 -2
- package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
- package/dist/core/runner/turn-attachments.d.ts +91 -80
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +42 -42
- package/dist/core/runtime-caps.d.ts +4 -4
- 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 +26 -2
- package/dist/core/same-plain-value.d.ts +40 -0
- package/dist/core/same-plain-value.js +49 -0
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/secret-env.d.ts +26 -3
- package/dist/core/secret-env.js +44 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/session-policy-store.d.ts +102 -35
- package/dist/core/session-policy-store.js +210 -48
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +106 -37
- package/dist/core/session-store.js +165 -91
- package/dist/core/session.d.ts +101 -57
- package/dist/core/session.js +53 -0
- package/dist/core/shared-memory/tools.js +3 -1
- package/dist/core/shared-memory/types.d.ts +1 -1
- 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.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.d.ts +10 -0
- package/dist/core/side-query.js +15 -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/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +168 -3
- package/dist/core/store-contracts/file-history-store-contract.js +74 -4
- 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-policy-store-contract.d.ts +7 -0
- package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
- package/dist/core/store-contracts/session-repo-contract.js +176 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +6 -8
- package/dist/core/store-contracts/session-store-contract.js +361 -51
- package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/surrogate-safe-slice.d.ts +3 -3
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +42 -8
- package/dist/core/task-notification.d.ts +19 -15
- package/dist/core/task-registry-agent.d.ts +4 -4
- package/dist/core/task-registry-shared.d.ts +4 -4
- package/dist/core/task-registry-shared.js +1 -0
- package/dist/core/task-registry.d.ts +13 -4
- package/dist/core/task-registry.js +14 -2
- package/dist/core/task-result.d.ts +21 -3
- package/dist/core/task-spec.d.ts +69 -64
- package/dist/core/task-stream.d.ts +6 -6
- package/dist/core/task-tool-shape.d.ts +4 -4
- package/dist/core/tighten-task-spec.d.ts +1 -1
- package/dist/core/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +36 -2
- package/dist/core/tool-catalog-entries.js +69 -43
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- package/dist/core/tool-conformance.js +1 -0
- package/dist/core/tool-errors.d.ts +2 -2
- package/dist/core/tool-face-reader.js +5 -3
- package/dist/core/tool-face.d.ts +21 -2
- package/dist/core/tool-face.js +1 -1
- package/dist/core/tool-model-gate.d.ts +5 -5
- package/dist/core/tool-name-aliases.d.ts +29 -8
- package/dist/core/tool-name-aliases.js +22 -4
- package/dist/core/tool-name-readings.d.ts +10 -43
- package/dist/core/tool-name-readings.js +2 -11
- package/dist/core/tool-policy.d.ts +85 -196
- package/dist/core/tool-policy.js +150 -175
- package/dist/core/tool-registry.d.ts +14 -7
- package/dist/core/tool-registry.js +17 -7
- package/dist/core/tool-result-store.js +5 -1
- package/dist/core/tool-roster.d.ts +57 -33
- package/dist/core/tool-roster.js +56 -68
- package/dist/core/tool-spec-members.js +8 -3
- package/dist/core/tool-spec.d.ts +53 -31
- package/dist/core/tools.js +51 -10
- package/dist/core/trace.d.ts +6 -2
- package/dist/core/types.d.ts +1 -1
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/warm-resume.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +58 -0
- package/dist/core/wiring-manifest.js +14 -5
- package/dist/core/workflow-journal-store.d.ts +62 -0
- package/dist/core/workflow-journal-store.js +78 -2
- package/dist/core/workflow-run-store.d.ts +6 -0
- package/dist/core/workflow-run-store.js +2 -0
- package/dist/engine/compaction/compaction.d.ts +9 -9
- package/dist/engine/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +26 -8
- package/dist/engine/execution-env/node-execution-env.js +54 -24
- package/dist/engine/harness/agent-harness.d.ts +39 -9
- package/dist/engine/harness/agent-harness.js +87 -33
- package/dist/engine/harness/types.d.ts +58 -9
- package/dist/engine/harness/types.js +12 -1
- package/dist/engine/llm/types.d.ts +36 -19
- package/dist/engine/llm/validation.d.ts +4 -1
- package/dist/engine/llm/validation.js +13 -1
- package/dist/engine/loop/agent-loop.d.ts +23 -1
- package/dist/engine/loop/agent-loop.js +26 -34
- package/dist/engine/loop/types.d.ts +31 -19
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/memory-repo.d.ts +18 -12
- package/dist/engine/session/memory-repo.js +24 -9
- package/dist/engine/session/parent-chain-guard.d.ts +3 -2
- package/dist/engine/session/parent-chain-guard.js +1 -1
- package/dist/engine/session/repo-utils.d.ts +32 -3
- package/dist/engine/session/repo-utils.js +50 -5
- package/dist/index.d.ts +47 -23
- package/dist/index.js +35 -17
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +3 -3
- package/dist/internal/harness.js +2 -2
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.js +2 -2
- package/dist/orchestration/run-workflow-tool.d.ts +8 -6
- package/dist/orchestration/run-workflow-tool.js +10 -6
- package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
- package/dist/orchestration/workflow-types.d.ts +18 -0
- package/dist/orchestration/workflow-types.js +6 -0
- package/dist/orchestration/workflow.d.ts +5 -13
- package/dist/orchestration/workflow.js +57 -49
- 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 +2 -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 +39 -2
- package/dist/prompt-assembly/tool-catalog.js +117 -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/prompts/default.d.ts +14 -14
- package/dist/scenarios/full-body.d.ts +15 -15
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.d.ts +4 -3
- package/dist/stores/file/adoption/adopt.js +27 -33
- package/dist/stores/file/adoption/marker.d.ts +6 -13
- package/dist/stores/file/adoption/marker.js +9 -17
- package/dist/stores/file/checkpoint-store.d.ts +24 -0
- package/dist/stores/file/checkpoint-store.js +45 -7
- package/dist/stores/file/file-history-store.d.ts +20 -19
- package/dist/stores/file/file-history-store.js +157 -141
- package/dist/stores/file/fs-atomic.d.ts +15 -0
- package/dist/stores/file/fs-atomic.js +89 -14
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/index.js +2 -1
- package/dist/stores/file/mailbox-store.d.ts +3 -0
- package/dist/stores/file/mailbox-store.js +3 -1
- package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
- package/dist/stores/file/permission-rule-adopt.js +18 -18
- package/dist/stores/file/permission-rule-store.d.ts +18 -2
- package/dist/stores/file/permission-rule-store.js +31 -18
- package/dist/stores/file/session-policy-store.d.ts +3 -3
- package/dist/stores/file/session-store.d.ts +54 -16
- package/dist/stores/file/session-store.js +114 -85
- package/dist/stores/file/workflow-journal-store.d.ts +10 -4
- package/dist/stores/file/workflow-journal-store.js +28 -13
- package/dist/tools/artifact/artifact-text.d.ts +1 -1
- package/dist/tools/artifact/artifact-tool.js +5 -3
- 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 +3 -3
- package/dist/tools/fs/fs-bash.d.ts +2 -2
- package/dist/tools/fs/fs-bash.js +8 -6
- 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/fs-shared.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
- package/dist/tools/fs/notebook.d.ts +2 -2
- package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
- package/dist/tools/fs/pattern-kill-guard.js +397 -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/read-deny.d.ts +29 -7
- package/dist/tools/fs/read-deny.js +63 -22
- package/dist/tools/fs/removal-targets.d.ts +18 -8
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +16 -6
- 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.js +12 -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-judge.d.ts +4 -0
- package/dist/tools/fs/shell-read-judge.js +5 -2
- 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/loop-tick.d.ts +2 -2
- package/dist/tools/scheduler-tools.js +5 -1
- package/dist/tools/task-list.d.ts +7 -7
- package/dist/tools/task-list.js +5 -1
- package/dist/tools/todo.js +65 -64
- package/dist/tools/web.d.ts +20 -15
- package/dist/tools/web.js +55 -69
- package/dist/tools/worktree.d.ts +3 -3
- package/dist/tools/worktree.js +3 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +5894 -5638
- package/wire-changes/core@7.55.0.json +3318 -0
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
- package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
* must match this InMemory one byte-for-byte — a cross-backend equivalence test is the contract).
|
|
9
9
|
*
|
|
10
10
|
* Safety model:
|
|
11
|
-
* - **tighten-only
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* - **tighten-only below what an operator wrote**: a NORMAL write may not loosen the row's operator part
|
|
12
|
+
* ({@link StoredSessionRules.operatorRules}: what the last operator write set; absent, the whole row) — above it, it
|
|
13
|
+
* may take back what normal writes added (a deny, its own allowlist or allowDirs narrowing). The one `putRules` is
|
|
14
|
+
* the write port and the delete port alike: a rule leaves every gate that reads the row when the row stops holding it.
|
|
15
|
+
* core has NO role system — `operator` is a boolean the caller FREEZES from a verified principal (mirrors
|
|
16
|
+
* `steer.trusted`); core never adjudicates operator-ness, it only honors the flag.
|
|
15
17
|
* - **CAS rev** (optimistic concurrency): a `putRules` with a stale `expectedRev` is rejected, so two replicas
|
|
16
18
|
* can't lose an update (mirrors the checkpoint store's `resolve` OCC).
|
|
17
19
|
* - **one grammar**: the two rule buckets hold rule ENTRIES — the grammar every entry list reads, through its one reader
|
|
@@ -19,8 +21,9 @@
|
|
|
19
21
|
* path rule, a name or host rule. Entries are stored as written; every station that validates, compares, matches or
|
|
20
22
|
* names one reads that reader's answer ({@link judgeSessionRulesWrite}, {@link loosenReasons}, the run-time layer).
|
|
21
23
|
* - **a row keeps its grammar**: the write judge stamps the grammar it read the entries in ({@link SESSION_RULES_GRAMMAR}), and
|
|
22
|
-
* every station reads a row's entries in the grammar the row carries ({@link readSessionRulesShape}) —
|
|
23
|
-
*
|
|
24
|
+
* every station reads a row's entries in the grammar the row carries ({@link readSessionRulesShape}) — an entry keeps the meaning
|
|
25
|
+
* its writer's grammar gave it, one that grammar could not read takes this engine's, and a row whose entries the two grammars
|
|
26
|
+
* read differently is announced ({@link earlierGrammarReads}).
|
|
24
27
|
* - **rules are read as rules or not at all**: rules whose shape cannot be read, or whose toolDeny holds an entry no grammar
|
|
25
28
|
* reads ({@link unreadableDenyEntries}), refuse every call until an operator writes them afresh — never read as fewer.
|
|
26
29
|
* - **NOT A SANDBOX**: a shell command rule reads the command line the call carries (every program run in its connector
|
|
@@ -60,10 +63,33 @@ export type SessionRuleEntryField = {
|
|
|
60
63
|
* `*`, one more name no tool carried, which voided nothing beside it;
|
|
61
64
|
* - 1, the one entry reader taking its tool name from the lenient rule parser (trimmed before a `(`, any character but a
|
|
62
65
|
* blank, a parenthesis or a control / format character);
|
|
63
|
-
* - 2, the rule syntax's tool-name head (`ruleSpellingOf`): a name is read as written, in the characters names are minted in
|
|
64
|
-
*
|
|
66
|
+
* - 2, the rule syntax's tool-name head (`ruleSpellingOf`): a name is read as written, in the characters names are minted in;
|
|
67
|
+
* - 3, the whole-protocol names (`mcp__*`, `mcp__*__*`, see `wholeProtocolOf`) read as a deny rule in `toolDeny` — every tool of the
|
|
68
|
+
* protocol — where grammar 2 read them as an entry that names nothing. An engine of grammar 2 given a row written in grammar 3
|
|
69
|
+
* refuses it ({@link grammarOf}) rather than read the deny as nothing;
|
|
70
|
+
* - 4, the delegation tool's type rules (`Agent(<subagent_type>)`) read as a rule on the agent type the call runs — where grammar 3
|
|
71
|
+
* read them as an entry with no rule form (and its write judge refused one) — and a Bash pattern (`Bash(git * main)`, a star
|
|
72
|
+
* anywhere but the two trailing markers) reads as the `pattern` match form — where grammar 3 had no form for it — so an engine of
|
|
73
|
+
* grammar 3 given a row written in grammar 4 refuses it rather than read an `Agent(…)` or `Bash(<pattern>)` deny as nothing;
|
|
74
|
+
* - 5, a `*` in a tool name is the name grammar's pattern: in `toolDeny` anywhere in the name, over the whole name (`Re*d`, `*` —
|
|
75
|
+
* every tool), where grammar 4 read `*` and a `*` in a protocol peer as entries that name nothing, `Re*d` as an exact name and a
|
|
76
|
+
* name starting with `*` as no rule; in `toolAllow` it grants nothing by itself and the entries beside it keep their reading,
|
|
77
|
+
* where grammars 1–4 voided a list holding it. An engine of grammar 4 given a row written in grammar 5 refuses it rather than
|
|
78
|
+
* read a `*` deny as nothing. In the same revision a host pattern with an empty label (`WebFetch(domain:.evil.test)`) or a `*`
|
|
79
|
+
* the URL parser folds (`*.`) is no rule, where grammar 4 read the exact host it spelled; an earlier row's such entry reads as no rule.
|
|
80
|
+
* A row an earlier grammar wrote keeps the meaning that grammar gave its entries, and an entry that grammar could not read takes
|
|
81
|
+
* this one's ({@link earlierGrammarReads}, over the revisions above as one table); an entry this grammar reads as no rule reads as
|
|
82
|
+
* `earlier_grammar` ({@link compileSessionRuleBucket}).
|
|
83
|
+
*
|
|
84
|
+
* The persisted rule store stamps the same number on each bucket it writes (and the rule-sync wire on each state it sends):
|
|
85
|
+
* a stored rule's text is a `Tool(content)` entry read by the same parser, so every revision of what such a text means is a
|
|
86
|
+
* revision counted here. A revision that touches only the entry list (a tool-name head, a protocol name) moves the persisted
|
|
87
|
+
* stamp too, and an engine before it then refuses a bucket it could have read — the refusing side. The persisted store keeps
|
|
88
|
+
* no earlier reading: its rows are read in this grammar whatever stamp at or below it they carry, so a revision that changes
|
|
89
|
+
* what an existing persisted rule text means owes that store a reading of its earlier stamps, as {@link earlierGrammarReads}
|
|
90
|
+
* is for entries. Every stamp is judged by {@link readRuleGrammarStamp}.
|
|
65
91
|
*/
|
|
66
|
-
export declare const SESSION_RULES_GRAMMAR =
|
|
92
|
+
export declare const SESSION_RULES_GRAMMAR = 5;
|
|
67
93
|
/** {@link SessionPermissionRules} plus the monotonic `rev` the store stamps (the OCC key). */
|
|
68
94
|
export interface StoredSessionRules extends SessionPermissionRules {
|
|
69
95
|
rev: number;
|
|
@@ -75,18 +101,31 @@ export interface StoredSessionRules extends SessionPermissionRules {
|
|
|
75
101
|
/** The rule grammar the row's entries are read in ({@link SESSION_RULES_GRAMMAR}), stamped by the write judge. Absent =
|
|
76
102
|
* a row stored before the stamp: grammar 0. */
|
|
77
103
|
grammar?: number;
|
|
104
|
+
/** The row's OPERATOR PART: the buckets (and their grammar) the last operator write set — the line a non-operator write
|
|
105
|
+
* may not loosen ({@link judgeSessionRulesWrite}). Minted by the write judge alone, and present only once a non-operator
|
|
106
|
+
* write stamped the row (it carries the part it was judged against; over no row, the part of the value it wrote when that
|
|
107
|
+
* value is a stored row — a rev from 1 — else an empty part). ABSENT = the whole row is the operator's: an operator write, and a row stored before
|
|
108
|
+
* the member, read fail-closed. Never enforced itself — the row's buckets are what every gate reads. */
|
|
109
|
+
operatorRules?: SessionPermissionRules & {
|
|
110
|
+
grammar: number;
|
|
111
|
+
};
|
|
78
112
|
}
|
|
79
|
-
/** A rules value as the shape reading hands it on ({@link readSessionRulesShape}): its buckets,
|
|
80
|
-
* are read in — resolved, so a store that serves it on beside its own counters serves the row's grammar with it
|
|
113
|
+
/** A rules value as the shape reading hands it on ({@link readSessionRulesShape}): its buckets, the grammar its entries
|
|
114
|
+
* are read in — resolved, so a store that serves it on beside its own counters serves the row's grammar with it — and the
|
|
115
|
+
* row's operator part when it carries one ({@link StoredSessionRules.operatorRules}). */
|
|
81
116
|
export type SessionRulesInGrammar = SessionPermissionRules & {
|
|
82
117
|
grammar: number;
|
|
118
|
+
operatorRules?: SessionPermissionRules & {
|
|
119
|
+
grammar: number;
|
|
120
|
+
};
|
|
83
121
|
};
|
|
84
122
|
/** Options for {@link SessionPolicyStore.putRules}. */
|
|
85
123
|
export interface PutRulesOptions {
|
|
86
124
|
/** CAS: reject the write if the stored `rev` is not this (optimistic concurrency). Omit to skip the check. */
|
|
87
125
|
expectedRev?: number;
|
|
88
|
-
/** When true, this write MAY loosen the rules (remove a deny / widen an allowlist or allowDirs)
|
|
89
|
-
* (non-operator) write
|
|
126
|
+
/** When true, this write MAY loosen the rules (remove a deny / widen an allowlist or allowDirs), and what it writes is
|
|
127
|
+
* the operator's whole. A NORMAL (non-operator) write may not loosen the row's operator part
|
|
128
|
+
* ({@link StoredSessionRules.operatorRules}). core does NOT verify operator-ness — the caller (service) FREEZES
|
|
90
129
|
* this from a verified, role-checked principal (mirrors `steer.trusted`). */
|
|
91
130
|
operator?: boolean;
|
|
92
131
|
}
|
|
@@ -105,7 +144,7 @@ export interface SessionRuleEntryRefusal extends AllowEntryInertDetail {
|
|
|
105
144
|
reason: AllowEntryInertReason;
|
|
106
145
|
}
|
|
107
146
|
/** Typed error from {@link SessionPolicyStore.putRules}. `conflict` = stale `expectedRev`; `loosen_forbidden`
|
|
108
|
-
* = a non-operator write tried to relax
|
|
147
|
+
* = a non-operator write tried to relax what an operator wrote; `corrupt` = a backend could not read what it stored (a row, or the
|
|
109
148
|
* erase-surviving rev mark of {@link SessionPolicyStore.deleteBySession}) and refuses rather than read it as fewer rules or
|
|
110
149
|
* stamp an unproven rev; `invalid_shape` = the rules value is not an object of buckets, each a list of strings
|
|
111
150
|
* ({@link readSessionRulesShape}); `inert_entry` = a bucket holds an entry the entry reader reads as nothing. `detail` is
|
|
@@ -142,8 +181,9 @@ export interface SessionRulesRecord {
|
|
|
142
181
|
export interface SessionPolicyStore {
|
|
143
182
|
getRules(sessionId: string, principal?: string): Promise<StoredSessionRules | null>;
|
|
144
183
|
/** Write the rules for a key through the one write judge ({@link judgeSessionRulesWrite}): CAS on `expectedRev`, the
|
|
145
|
-
* shape, every entry's reading (operator writes included), then, for a non-operator write
|
|
146
|
-
*
|
|
184
|
+
* shape, every entry's reading (operator writes included), then, for a non-operator write, the check against the row's
|
|
185
|
+
* operator part — each refusal a {@link SessionPolicyError}, and nothing is written. The same call is the delete port: a
|
|
186
|
+
* value without an entry takes it out of every gate that reads the row. */
|
|
147
187
|
putRules(sessionId: string, principal: string | undefined, rules: SessionPermissionRules, opts?: PutRulesOptions): Promise<StoredSessionRules>;
|
|
148
188
|
/**
|
|
149
189
|
* 2c session-sync: every (principal, rules) record for `sessionId` across ALL principals — `getRules`
|
|
@@ -193,13 +233,33 @@ export interface SessionPolicyStore {
|
|
|
193
233
|
* backend should keep `allowDirs` to real directories; a future symlink-aware write-time canonicalize closes it.
|
|
194
234
|
*/
|
|
195
235
|
declare function lexWithin(root: string, p: string): boolean;
|
|
236
|
+
/**
|
|
237
|
+
* THE ONE JUDGE of a rule grammar stamp, whichever store carries it — a session-rules row ({@link readSessionRulesShape}),
|
|
238
|
+
* the persisted rule store's bucket and the rule-sync wire: the grammar the stamped rules are read in, or the fault that
|
|
239
|
+
* makes them unreadable. `absent` is what a missing stamp reads as (each store says what its unstamped rules were written
|
|
240
|
+
* in). A stamp is a whole number no greater than {@link SESSION_RULES_GRAMMAR}: a later grammar is one this engine cannot
|
|
241
|
+
* read the rules in, and reading them in an older one could grant what their writer refused or drop a refusal it cannot
|
|
242
|
+
* name — so they are refused WHOLE (`later`), never read in part. `rules` names the stamped rules in the sentence, `held`
|
|
243
|
+
* what they hold (`entries`, `rows`).
|
|
244
|
+
*/
|
|
245
|
+
export declare function readRuleGrammarStamp(stamp: unknown, absent: number, words: {
|
|
246
|
+
readonly rules: string;
|
|
247
|
+
readonly held: string;
|
|
248
|
+
}): {
|
|
249
|
+
grammar: number;
|
|
250
|
+
} | {
|
|
251
|
+
got: string;
|
|
252
|
+
sentence: string;
|
|
253
|
+
later?: true;
|
|
254
|
+
};
|
|
196
255
|
/**
|
|
197
256
|
* THE ONE SHAPE READING of a rules value — what every station that takes one reads it through: the write (incoming rules),
|
|
198
257
|
* a store's read-back of its own rows, the tighten comparison's prior, the run-time layer's served row. A rules value is an
|
|
199
258
|
* object whose keys are buckets ({@link SessionPermissionRules}); each bucket present is a list of strings (`allowDirs`: of
|
|
200
259
|
* non-blank strings — a directory is no blank). A bucket's TYPE is all this reads: what an entry means is the entry reader's,
|
|
201
260
|
* in the grammar the value is written in ({@link grammarOf}), handed on as `grammar`. The store's counters (`rev`, `gen`) are
|
|
202
|
-
* passed over,
|
|
261
|
+
* passed over, the row's operator part is read as rules of its own and handed on ({@link readOperatorPart}), and a key
|
|
262
|
+
* holding `undefined` holds nothing. Anything else is a fault, named by key and by TYPE, never by value —
|
|
203
263
|
* a bare string is never one rule and never its characters (`"rm"` spread into `["r","m"]`), and a key outside the buckets is
|
|
204
264
|
* never dropped (a dropped deny is a deny nobody enforces).
|
|
205
265
|
*/
|
|
@@ -227,15 +287,17 @@ export declare function normalizeRules(rules: unknown): SessionPermissionRules;
|
|
|
227
287
|
export declare function unreadableDenyEntries(rules: SessionRulesInGrammar, roster?: ReadonlySet<string>): AllowEntryInert[];
|
|
228
288
|
/**
|
|
229
289
|
* THE LIST READING of one rule bucket of a rules value the shape reading read — what the run-time layer enforces, the tighten
|
|
230
|
-
* comparison compares and the write judge refuses on:
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* it out alone.
|
|
290
|
+
* comparison compares and the write judge refuses on: the one entry reader over each entry, in the bucket's direction, against
|
|
291
|
+
* `roster` when given, in the grammar the value is written in ({@link earlierGrammarReads}: an entry keeps the meaning its
|
|
292
|
+
* writer's grammar gave it, and one that grammar could not read takes this engine's). The reading is an entry's — save the one
|
|
293
|
+
* list reading a row keeps: grammars 1–4 voided an allow list holding `*` (in any spelling their voiding test read as `*`, `* (*)`
|
|
294
|
+
* included), so such a row's allow list grants nothing; from grammar 5 a `*` grants nothing by itself and the list beside it is read
|
|
295
|
+
* as written. The entries that read as nothing are listed in order, those an earlier grammar reads so (`earlier_grammar`) last.
|
|
237
296
|
*/
|
|
238
297
|
export declare function compileSessionRuleBucket(rules: SessionRulesInGrammar, field: SessionRuleEntryField, roster?: ReadonlySet<string>): ReturnType<typeof compileAllowList>;
|
|
298
|
+
/** The entries of one bucket a stored row's earlier grammar announces ({@link earlierGrammarReads}: its writer's meaning and this
|
|
299
|
+
* grammar's differ) — what `config.session_rules_earlier_grammar` names, one bucket at a time. */
|
|
300
|
+
export declare function earlierGrammarEntries(rules: SessionRulesInGrammar, field: SessionRuleEntryField): string[];
|
|
239
301
|
/**
|
|
240
302
|
* The advisory for the entries of one bucket a stored row's earlier grammar reads as nothing ({@link compileSessionRuleBucket},
|
|
241
303
|
* `earlier_grammar`; `grammar` = the row's): the session, the bucket, the entries as written, what they do and the way out. An
|
|
@@ -245,9 +307,10 @@ export declare function compileSessionRuleBucket(rules: SessionRulesInGrammar, f
|
|
|
245
307
|
* to make a parenthesized one the rule it now spells, or (`*`, which is no allow rule in any grammar) to leave it out.
|
|
246
308
|
*/
|
|
247
309
|
export declare function earlierGrammarAdvisory(sessionId: string, entries: readonly string[], field: SessionRuleEntryField, grammar: number): string;
|
|
248
|
-
/** The reader's word for one entry an earlier grammar
|
|
249
|
-
*
|
|
250
|
-
|
|
310
|
+
/** The reader's word for one entry an earlier grammar announces: `no_rule` — this engine's rule grammar reads it as no rule;
|
|
311
|
+
* `named_no_tool` — a grammar-0 allow entry the bare-name comparison of its day read as naming no tool; `grammar_revised` — a
|
|
312
|
+
* grammar revision after the row's gave the entry another meaning, and the message names both and which one the rules enforce. */
|
|
313
|
+
export type EarlierGrammarReader = "no_rule" | "named_no_tool" | "grammar_revised";
|
|
251
314
|
/**
|
|
252
315
|
* The notice for the entries of one bucket a stored row's earlier grammar reads as nothing (`config.session_rules_earlier_grammar`,
|
|
253
316
|
* audience `user` — the session's rules are what the person's calls are judged by): the message is {@link earlierGrammarAdvisory}
|
|
@@ -277,14 +340,18 @@ export declare function earlierGrammarAnnouncer(sink: ((entries: readonly string
|
|
|
277
340
|
* the rules to stamp, or a {@link SessionPolicyError}, in this order — `conflict` (a stale `expectedRev` against `prior`'s rev),
|
|
278
341
|
* `invalid_shape` ({@link normalizeRules}), `inert_entry` (an entry that reads as nothing in the grammar the rules are written
|
|
279
342
|
* in; operator writes included — a rule that names nothing guards nothing whoever writes it), then, for a non-operator write
|
|
280
|
-
* over
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
343
|
+
* over a row, `loosen_forbidden` ({@link loosenReasons}) against the row's OPERATOR PART ({@link StoredSessionRules.operatorRules};
|
|
344
|
+
* absent, the whole row) — or `corrupt` when that prior cannot be read as rules, which the comparison never reads as fewer.
|
|
345
|
+
* Over no row there is no rev to compare and no tighten gate, and a judge called with `prior = null` (a host's pre-read of a
|
|
346
|
+
* value's shape and entries) answers only those two content refusals. Below what an operator wrote nothing moves; above it,
|
|
347
|
+
* a non-operator takes back what non-operator writes added. The
|
|
348
|
+
* rules to stamp carry `grammar` = {@link SESSION_RULES_GRAMMAR} — what passed the judge means the same in this engine's
|
|
349
|
+
* grammar — and, from a non-operator write, the operator part it was judged against: over no row, the value's own when it is a
|
|
350
|
+
* stored row handed in ({@link isStoredRow}), else an empty one (an operator write's whole value is the operator's, so it
|
|
351
|
+
* carries none). THIS is the one place both stamps are minted, so every store that stores what the judge
|
|
352
|
+
* returns keeps them. `mountedToolNames` = the store's declaration ({@link SessionPolicyStoreOptions.mountedToolNames}).
|
|
284
353
|
*/
|
|
285
|
-
export declare function judgeSessionRulesWrite(prior: StoredSessionRules | null, rules: unknown, opts: PutRulesOptions | undefined, mountedToolNames?: ReadonlySet<string>):
|
|
286
|
-
grammar: number;
|
|
287
|
-
};
|
|
354
|
+
export declare function judgeSessionRulesWrite(prior: StoredSessionRules | null, rules: unknown, opts: PutRulesOptions | undefined, mountedToolNames?: ReadonlySet<string>): SessionRulesInGrammar;
|
|
288
355
|
/**
|
|
289
356
|
* Pure tighten-only diff: the reasons `next` LOOSENS `prior` (empty ⇒ `next` is a pure tightening or no-op), over the EFFECTIVE
|
|
290
357
|
* entries of each rule bucket — the list as the run-time layer enforces it ({@link effectiveEntries}). Rules whose toolDeny holds
|
|
@@ -321,7 +388,7 @@ export declare function continuesLineage(a: {
|
|
|
321
388
|
}): boolean;
|
|
322
389
|
/**
|
|
323
390
|
* In-process default {@link SessionPolicyStore} (single-replica). A deployment that needs cross-replica
|
|
324
|
-
* durability supplies its own backend with the SAME CAS-rev +
|
|
391
|
+
* durability supplies its own backend with the SAME CAS-rev + write-judge semantics. Single-threaded JS makes
|
|
325
392
|
* the read-check-write trivially atomic here; a durable backend folds it into a CAS WHERE clause.
|
|
326
393
|
*/
|
|
327
394
|
export declare class InMemorySessionPolicyStore implements SessionPolicyStore {
|
|
@@ -4,12 +4,15 @@ import { NAMESPACED_NAME_SHAPES } from "./protocol-table.js";
|
|
|
4
4
|
import { callerToolNameProblem } from "./caller-tool-name.js";
|
|
5
5
|
import { compileAllowList, compiledEntryName, inertEntryPhrase, readRuleEntry, renderListEntry, rootFacingToolNames } from "./allow-entry.js";
|
|
6
6
|
import { valueTypeLabel } from "./tool-name-list.js";
|
|
7
|
-
import { noticeRuleText } from "./permission-rule-model.js";
|
|
7
|
+
import { NAME_RULE_FACES, noticeRuleText } from "./permission-rule-model.js";
|
|
8
|
+
import { parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
9
|
+
import { splitNamespacedName } from "./tool-name-aliases.js";
|
|
8
10
|
const SESSION_RULE_BUCKETS = { toolAllow: "allow", toolDeny: "deny", allowDirs: "dirs" };
|
|
9
11
|
const BUCKETS = Object.keys(SESSION_RULE_BUCKETS);
|
|
10
12
|
const ENTRY_FIELDS = BUCKETS.filter((f) => SESSION_RULE_BUCKETS[f] !== "dirs");
|
|
11
13
|
const STORE_STAMPS = new Set(["rev", "gen", "grammar"]);
|
|
12
|
-
|
|
14
|
+
const OPERATOR_PART = "operatorRules";
|
|
15
|
+
export const SESSION_RULES_GRAMMAR = 5;
|
|
13
16
|
export class SessionPolicyError extends Error {
|
|
14
17
|
code;
|
|
15
18
|
detail;
|
|
@@ -53,18 +56,26 @@ function lexWithin(root, p) {
|
|
|
53
56
|
return true;
|
|
54
57
|
return np === nr || np.startsWith(nr + "/");
|
|
55
58
|
}
|
|
59
|
+
function isStoredRow(value) {
|
|
60
|
+
const rev = value.rev;
|
|
61
|
+
return typeof rev === "number" && Number.isInteger(rev) && rev >= 1;
|
|
62
|
+
}
|
|
56
63
|
function grammarOf(value) {
|
|
57
64
|
const stamp = value.grammar;
|
|
65
|
+
return readRuleGrammarStamp(stamp, stamp === undefined && isStoredRow(value) ? 0 : SESSION_RULES_GRAMMAR, { rules: "session rules", held: "entries" });
|
|
66
|
+
}
|
|
67
|
+
export function readRuleGrammarStamp(stamp, absent, words) {
|
|
58
68
|
if (stamp === undefined)
|
|
59
|
-
return { grammar:
|
|
69
|
+
return { grammar: absent };
|
|
60
70
|
if (typeof stamp !== "number" || !Number.isInteger(stamp) || stamp < 0) {
|
|
61
71
|
const got = typeof stamp === "number" ? "a number that is not a whole number of 0 or more" : valueTypeLabel(stamp);
|
|
62
|
-
return { got, sentence:
|
|
72
|
+
return { got, sentence: `${words.rules} carry a grammar stamp that is ${got} — the stamp is the whole number of the rule grammar the rules were written in (this engine reads grammar ${SESSION_RULES_GRAMMAR})` };
|
|
63
73
|
}
|
|
64
74
|
if (stamp > SESSION_RULES_GRAMMAR) {
|
|
65
75
|
return {
|
|
66
76
|
got: `${stamp}, a grammar newer than this engine's (${SESSION_RULES_GRAMMAR})`,
|
|
67
|
-
sentence:
|
|
77
|
+
sentence: `${words.rules} were written in rule grammar ${stamp}, newer than this engine reads (grammar ${SESSION_RULES_GRAMMAR}) — refusing rather than read their ${words.held} in an older grammar; an engine that reads grammar ${stamp} reads them`,
|
|
78
|
+
later: true,
|
|
68
79
|
};
|
|
69
80
|
}
|
|
70
81
|
return { grammar: stamp };
|
|
@@ -82,6 +93,13 @@ export function readSessionRulesShape(value) {
|
|
|
82
93
|
for (const [key, v] of Object.entries(value)) {
|
|
83
94
|
if (STORE_STAMPS.has(key) || v === undefined)
|
|
84
95
|
continue;
|
|
96
|
+
if (key === OPERATOR_PART) {
|
|
97
|
+
const part = readOperatorPart(v);
|
|
98
|
+
if ("fault" in part)
|
|
99
|
+
return part;
|
|
100
|
+
rules.operatorRules = part.rules;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
85
103
|
if (!Object.hasOwn(SESSION_RULE_BUCKETS, key)) {
|
|
86
104
|
return fault(key, "not a rule bucket", `session rules hold ${JSON.stringify(key)}, which is not a rule bucket — the buckets are ${BUCKETS.join(", ")}, and a shell command rule is a toolDeny / toolAllow entry written Bash(<command>) (Bash(rm:*) matches a command whose first word is rm)`);
|
|
87
105
|
}
|
|
@@ -100,6 +118,20 @@ export function readSessionRulesShape(value) {
|
|
|
100
118
|
}
|
|
101
119
|
return { rules };
|
|
102
120
|
}
|
|
121
|
+
function readOperatorPart(value) {
|
|
122
|
+
const read = readSessionRulesShape(value);
|
|
123
|
+
if ("fault" in read) {
|
|
124
|
+
const field = read.fault.field === "" ? OPERATOR_PART : `${OPERATOR_PART}.${read.fault.field}`;
|
|
125
|
+
return { fault: { field, got: read.fault.got }, sentence: `the session rules' operator part: ${read.sentence}` };
|
|
126
|
+
}
|
|
127
|
+
const { operatorRules: nested, ...part } = read.rules;
|
|
128
|
+
const unstamped = value.grammar === undefined;
|
|
129
|
+
if (unstamped || nested !== undefined) {
|
|
130
|
+
const got = unstamped ? "rules without a grammar stamp" : "an operator part of its own";
|
|
131
|
+
return { fault: { field: OPERATOR_PART, got }, sentence: `session rules carry an operator part holding ${got} — the part is the rules the last operator write set, stamped with their grammar by the write judge` };
|
|
132
|
+
}
|
|
133
|
+
return { rules: part };
|
|
134
|
+
}
|
|
103
135
|
export function normalizeRules(rules) {
|
|
104
136
|
return canonicalRules(shapeOrRefuse(rules));
|
|
105
137
|
}
|
|
@@ -119,42 +151,142 @@ function canonicalRules(read) {
|
|
|
119
151
|
}
|
|
120
152
|
return out;
|
|
121
153
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return false;
|
|
129
|
-
return reading.kind === "row" ? compiledEntryName(reading.compiled) !== entry : reading.reason === "wildcard_all";
|
|
154
|
+
const NAMES_NO_TOOL = "an entry naming no tool, so it refused nothing";
|
|
155
|
+
const NO_RULE_THEN = (direction) => (direction === "allow" ? "no rule, so it admitted nothing" : "no rule, so the rules could not be read and refused every call");
|
|
156
|
+
const NAME_PATTERN_NOW = "a pattern over the whole tool name, every tool it matches";
|
|
157
|
+
function spellsWholeProtocol(name) {
|
|
158
|
+
const split = splitNamespacedName(name);
|
|
159
|
+
return split !== undefined && split.peer === "*" && (split.tool === undefined || split.tool === "*");
|
|
130
160
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
const GRAMMAR_REVISIONS = [
|
|
162
|
+
{
|
|
163
|
+
grammar: 1,
|
|
164
|
+
answer: ({ direction, entry, reading }) => {
|
|
165
|
+
const otherName = reading.kind === "row" ? compiledEntryName(reading.compiled) !== entry : reading.reason === "wildcard_all";
|
|
166
|
+
if (!otherName)
|
|
167
|
+
return undefined;
|
|
168
|
+
if (direction === "allow")
|
|
169
|
+
return { was: "a tool name compared as written, naming no tool", now: "the rule it spells", keep: { kind: "inert", reason: "earlier_grammar" }, reader: "named_no_tool" };
|
|
170
|
+
return reading.kind === "row" ? { was: "a tool name compared as written, naming no tool, so it refused nothing", now: "the rule it spells", reader: "grammar_revised" } : undefined;
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
grammar: 3,
|
|
175
|
+
answer: ({ direction, reading }) => direction === "deny" && reading.kind === "row" && reading.compiled.kind === "covering" && spellsWholeProtocol(reading.compiled.pattern)
|
|
176
|
+
? { was: NAMES_NO_TOOL, now: "a deny of every tool of the protocol", reader: "grammar_revised" }
|
|
177
|
+
: undefined,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
grammar: 4,
|
|
181
|
+
answer: ({ direction, reading }) => {
|
|
182
|
+
if (reading.kind !== "row")
|
|
183
|
+
return undefined;
|
|
184
|
+
const { compiled } = reading;
|
|
185
|
+
if (compiled.kind === "name" && NAME_RULE_FACES[compiled.rule.tool]?.values === "mounted") {
|
|
186
|
+
return { was: direction === "allow" ? "an entry with no rule form, so it admitted nothing" : "an entry with no rule form, so it refused nothing", now: "a rule on the agent type it names", reader: "grammar_revised" };
|
|
187
|
+
}
|
|
188
|
+
return compiled.kind === "command" && compiled.rule.match === "pattern" ? { was: NO_RULE_THEN(direction), now: "the Bash pattern rule it spells", reader: "grammar_revised" } : undefined;
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
grammar: 5,
|
|
193
|
+
answer: ({ row, direction, entry, reading, list }) => {
|
|
194
|
+
if (direction === "allow") {
|
|
195
|
+
if (row >= 1 && list.some(readsAsWildcard))
|
|
196
|
+
return { was: "voided by the `*` its list holds", now: "one entry that grants nothing, the entries beside it read as written", keep: { kind: "inert", reason: "wildcard_all" } };
|
|
197
|
+
const parsed = reading.kind === "inert" ? ruleSpellingOf(entry) : undefined;
|
|
198
|
+
const name = parsed?.ruleContent === undefined ? parsed?.toolName : undefined;
|
|
199
|
+
if (name === undefined || name === "*" || !name.includes("*") || name.startsWith("*") || splitNamespacedName(name) !== undefined)
|
|
200
|
+
return undefined;
|
|
201
|
+
return { was: `the exact tool name ${JSON.stringify(name)}`, now: "no rule (an allow reads a `*` only in a protocol name's tool segment)", keep: { kind: "row", compiled: { kind: "tool", name } }, reader: "grammar_revised" };
|
|
202
|
+
}
|
|
203
|
+
if (reading.kind !== "row" || reading.compiled.kind !== "covering")
|
|
204
|
+
return undefined;
|
|
205
|
+
const { pattern } = reading.compiled;
|
|
206
|
+
const split = splitNamespacedName(pattern);
|
|
207
|
+
if (!pattern.includes("*") || spellsWholeProtocol(pattern) || (split !== undefined && !split.peer.includes("*")))
|
|
208
|
+
return undefined;
|
|
209
|
+
const answer = { now: NAME_PATTERN_NOW, reader: "grammar_revised" };
|
|
210
|
+
if (pattern === "*")
|
|
211
|
+
return { ...answer, was: NAMES_NO_TOOL, keep: { kind: "inert", reason: "wildcard_all" } };
|
|
212
|
+
if (split !== undefined)
|
|
213
|
+
return { ...answer, was: NAMES_NO_TOOL, keep: { kind: "inert", reason: "namespace_wildcard" } };
|
|
214
|
+
if (pattern.startsWith("*"))
|
|
215
|
+
return { ...answer, was: NO_RULE_THEN(direction) };
|
|
216
|
+
return { ...answer, was: `the exact tool name ${JSON.stringify(pattern)}, so it refused only a tool of that name`, keep: { kind: "row", compiled: { kind: "tool", name: pattern } } };
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
];
|
|
220
|
+
function earlierGrammarReads(row, direction, entry, reading, list) {
|
|
221
|
+
if (row >= SESSION_RULES_GRAMMAR)
|
|
222
|
+
return { reading };
|
|
223
|
+
let first;
|
|
224
|
+
let last;
|
|
225
|
+
let kept;
|
|
226
|
+
for (const revision of GRAMMAR_REVISIONS) {
|
|
227
|
+
if (revision.grammar <= row)
|
|
228
|
+
continue;
|
|
229
|
+
const answer = revision.answer({ row, direction, entry, reading, list });
|
|
230
|
+
if (answer === undefined)
|
|
231
|
+
continue;
|
|
232
|
+
first ??= answer;
|
|
233
|
+
last = answer;
|
|
234
|
+
if (answer.keep !== undefined) {
|
|
235
|
+
kept = answer.keep;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const read = kept ?? reading;
|
|
240
|
+
if (read.kind === "inert" && read.reason === "grammar")
|
|
241
|
+
return { reading: { kind: "inert", reason: "earlier_grammar" }, reader: "no_rule" };
|
|
242
|
+
if (first === undefined || last === undefined)
|
|
243
|
+
return { reading: read };
|
|
244
|
+
const reader = first.reader === "named_no_tool" ? first.reader : last.reader;
|
|
245
|
+
if (reader === undefined)
|
|
246
|
+
return { reading: read };
|
|
247
|
+
return { reading: read, reader, ...(reader === "grammar_revised" ? { revised: { was: first.was, now: last.now, stands: kept !== undefined } } : {}) };
|
|
134
248
|
}
|
|
135
249
|
const NO_RULE_REASONS = new Set(["grammar", "earlier_grammar"]);
|
|
136
250
|
export function unreadableDenyEntries(rules, roster) {
|
|
137
251
|
return compileSessionRuleBucket(rules, "toolDeny", roster).inert.filter((i) => NO_RULE_REASONS.has(i.reason));
|
|
138
252
|
}
|
|
139
|
-
function readsAsWildcard(entry) {
|
|
140
|
-
return compileAllowList([entry], "allow").inert.some((i) => i.reason === "wildcard_all");
|
|
141
|
-
}
|
|
142
253
|
const STAR_IS_NO_ALLOW_RULE = "it is no allow rule in any grammar and a write holding it is refused";
|
|
143
254
|
function starWayOut(onlyStars, others, left) {
|
|
144
255
|
return onlyStars
|
|
145
256
|
? `"*" is no allow rule in any grammar (a write holding it is refused); to drop it, write the session's rules afresh without it ${REWRITE_THROUGH}; ${left}`
|
|
146
257
|
: `${others}, leaving "*" out — ${STAR_IS_NO_ALLOW_RULE}; ${left}`;
|
|
147
258
|
}
|
|
148
|
-
|
|
259
|
+
function readsAsWildcard(entry) {
|
|
260
|
+
return typeof entry === "string" && entry === entry.trim() && parsePermissionRule(entry).toolName === "*";
|
|
261
|
+
}
|
|
262
|
+
function entryBucketDirection(field) {
|
|
149
263
|
const direction = SESSION_RULE_BUCKETS[field];
|
|
264
|
+
if (direction === "allow" || direction === "deny")
|
|
265
|
+
return direction;
|
|
266
|
+
throw new SessionPolicyError("invalid_shape", `${JSON.stringify(field)} is no rule-entry bucket of the session rules — the entry buckets are ${ENTRY_FIELDS.join(" and ")}`);
|
|
267
|
+
}
|
|
268
|
+
function bucketReadings(rules, field, roster) {
|
|
269
|
+
const direction = entryBucketDirection(field);
|
|
150
270
|
const entries = rules[field] ?? [];
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
271
|
+
return entries.map((entry) => ({ entry, ...earlierGrammarReads(rules.grammar, direction, entry, readRuleEntry(entry, direction, roster), entries) }));
|
|
272
|
+
}
|
|
273
|
+
export function compileSessionRuleBucket(rules, field, roster) {
|
|
274
|
+
const rows = [];
|
|
275
|
+
const inert = [];
|
|
276
|
+
const earlier = [];
|
|
277
|
+
for (const { entry, reading } of bucketReadings(rules, field, roster)) {
|
|
278
|
+
if (reading.kind === "row")
|
|
279
|
+
rows.push({ entry, compiled: reading.compiled });
|
|
280
|
+
else {
|
|
281
|
+
const { kind: _kind, ...why } = reading;
|
|
282
|
+
void _kind;
|
|
283
|
+
(why.reason === "earlier_grammar" ? earlier : inert).push({ entry, ...why });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return { rows, inert: [...inert, ...earlier] };
|
|
287
|
+
}
|
|
288
|
+
export function earlierGrammarEntries(rules, field) {
|
|
289
|
+
return bucketReadings(rules, field).flatMap((r) => (r.reader === undefined ? [] : [r.entry]));
|
|
158
290
|
}
|
|
159
291
|
const ADVISORY_ENTRIES_SHOWN = 5;
|
|
160
292
|
function shownEntries(entries, render) {
|
|
@@ -163,14 +295,33 @@ function shownEntries(entries, render) {
|
|
|
163
295
|
}
|
|
164
296
|
const REWRITE_THROUGH = `through this engine (an operator write of a new value without the stored row's rev; the write stamps grammar ${SESSION_RULES_GRAMMAR})`;
|
|
165
297
|
export function earlierGrammarAdvisory(sessionId, entries, field, grammar) {
|
|
166
|
-
const read = earlierGrammarReadings(entries, field);
|
|
298
|
+
const read = earlierGrammarReadings(entries, field, grammar);
|
|
167
299
|
const noRule = read.filter((r) => r.reader === "no_rule").map((r) => r.entry);
|
|
168
300
|
const namedNoTool = read.filter((r) => r.reader === "named_no_tool").map((r) => r.entry);
|
|
169
|
-
const
|
|
301
|
+
const revised = read.flatMap((r) => (r.revised === undefined ? [] : [{ entry: r.entry, ...r.revised }]));
|
|
302
|
+
const sentences = [
|
|
303
|
+
...(namedNoTool.length > 0 ? [namedNoToolInGrammar0(namedNoTool)] : []),
|
|
304
|
+
...(noRule.length > 0 ? [noRuleInThisGrammar(noRule, field, grammar)] : []),
|
|
305
|
+
...(revised.length > 0 ? [revisedSinceGrammar(revised, field, grammar)] : []),
|
|
306
|
+
];
|
|
170
307
|
return `session permission rules of session ${JSON.stringify(sessionId)}: ${sentences.join(" ")}`;
|
|
171
308
|
}
|
|
172
|
-
function earlierGrammarReadings(entries, field) {
|
|
173
|
-
|
|
309
|
+
function earlierGrammarReadings(entries, field, grammar) {
|
|
310
|
+
const direction = entryBucketDirection(field);
|
|
311
|
+
return entries.map((entry) => {
|
|
312
|
+
const read = earlierGrammarReads(grammar, direction, entry, readRuleEntry(entry, direction), entries);
|
|
313
|
+
return { entry, reader: read.reader ?? "no_rule", ...(read.revised !== undefined ? { revised: read.revised } : {}) };
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function revisedSinceGrammar(entries, field, grammar) {
|
|
317
|
+
const one = entries.length === 1;
|
|
318
|
+
const said = entries
|
|
319
|
+
.slice(0, ADVISORY_ENTRIES_SHOWN)
|
|
320
|
+
.map((e) => `${renderListEntry(e.entry)} meant ${e.was} there; this engine's rule grammar (${SESSION_RULES_GRAMMAR}) reads it as ${e.now}, and ${e.stands ? "the stored meaning stands" : "this grammar's reading applies"}`)
|
|
321
|
+
.join("; ");
|
|
322
|
+
const rest = entries.length > ADVISORY_ENTRIES_SHOWN ? `; and ${entries.length - ADVISORY_ENTRIES_SHOWN} more` : "";
|
|
323
|
+
return (`${field} ${one ? "holds an entry" : "holds entries"} stored in rule grammar ${grammar}${grammar === 0 ? " (before the rule grammar stamp)" : ""} whose meaning a later grammar revised — ${said}${rest}. ` +
|
|
324
|
+
`To give ${one ? "it" : "them"} this grammar's reading, write the session's rules afresh ${REWRITE_THROUGH}; left as stored, ${one ? "it reads" : "they read"} as said.`);
|
|
174
325
|
}
|
|
175
326
|
export function earlierGrammarNotice(input) {
|
|
176
327
|
const { rulesSessionId, sessionId, entries, field, grammar } = input;
|
|
@@ -180,7 +331,7 @@ export function earlierGrammarNotice(input) {
|
|
|
180
331
|
detail: {
|
|
181
332
|
bucket: field,
|
|
182
333
|
storedGrammar: grammar,
|
|
183
|
-
entries: earlierGrammarReadings(entries, field).map((r) => ({ entry: noticeRuleText(r.entry), reader: r.reader })),
|
|
334
|
+
entries: earlierGrammarReadings(entries, field, grammar).map((r) => ({ entry: noticeRuleText(r.entry), reader: r.reader })),
|
|
184
335
|
rewrite: { by: "operator_write_without_rev", stampsGrammar: SESSION_RULES_GRAMMAR },
|
|
185
336
|
rulesSessionId,
|
|
186
337
|
sessionId,
|
|
@@ -215,8 +366,9 @@ function noRuleInThisGrammar(entries, field, grammar) {
|
|
|
215
366
|
export function earlierGrammarRefusalClause(entries, grammar) {
|
|
216
367
|
if (entries.length === 0)
|
|
217
368
|
return "";
|
|
218
|
-
const
|
|
219
|
-
const
|
|
369
|
+
const read = earlierGrammarReadings(entries, "toolAllow", grammar);
|
|
370
|
+
const noRule = read.filter((r) => r.reader === "no_rule").length;
|
|
371
|
+
const namedNoTool = read.filter((r) => r.reader !== "no_rule").map((r) => r.entry);
|
|
220
372
|
const stars = namedNoTool.filter(readsAsWildcard).length;
|
|
221
373
|
const others = namedNoTool.length - stars;
|
|
222
374
|
const named = [...(stars > 0 ? ['"*"'] : []), ...(others > 0 ? [`${others} parenthesized ${others === 1 ? "entry" : "entries"}`] : [])];
|
|
@@ -246,15 +398,13 @@ function effectiveEntries(rules, field, mountedToolNames) {
|
|
|
246
398
|
function assertEntriesRead(rules, mountedToolNames) {
|
|
247
399
|
const known = rootFacingToolNames(mountedToolNames);
|
|
248
400
|
for (const field of ENTRY_FIELDS) {
|
|
249
|
-
for (const entry of rules
|
|
250
|
-
const reading = readRuleEntry(entry, SESSION_RULE_BUCKETS[field], known);
|
|
251
|
-
const read = earlierGrammarReads(rules.grammar, field, entry, reading) ? { kind: "inert", reason: "earlier_grammar" } : reading;
|
|
401
|
+
for (const { entry, reading: read, reader } of bucketReadings(rules, field, known)) {
|
|
252
402
|
if (read.kind === "row")
|
|
253
403
|
continue;
|
|
254
404
|
const { kind: _kind, ...why } = read;
|
|
255
405
|
void _kind;
|
|
256
406
|
const way = why.reason === "earlier_grammar"
|
|
257
|
-
?
|
|
407
|
+
? reader === "no_rule"
|
|
258
408
|
? ` These rules are written in grammar ${rules.grammar} (a stored row), and this engine's grammar (${SESSION_RULES_GRAMMAR}) reads this entry as no rule (grammar) — ` +
|
|
259
409
|
(field === "toolAllow" && readsAsWildcard(entry) ? `leave the entry out: it spells "*", and ${STAR_IS_NO_ALLOW_RULE}.` : "leave the entry out, or spell the tool's name as a rule spells one.")
|
|
260
410
|
: ` These rules are written in grammar ${rules.grammar} (a stored row from before the grammar stamp), in which this entry names no tool.` +
|
|
@@ -284,17 +434,29 @@ export function judgeSessionRulesWrite(prior, rules, opts, mountedToolNames = NO
|
|
|
284
434
|
const read = shapeOrRefuse(rules);
|
|
285
435
|
const clean = canonicalRules(read);
|
|
286
436
|
assertEntriesRead(read, mountedToolNames);
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
437
|
+
if (opts?.operator === true)
|
|
438
|
+
return { ...clean, grammar: SESSION_RULES_GRAMMAR };
|
|
439
|
+
if (prior === null) {
|
|
440
|
+
return { ...clean, grammar: SESSION_RULES_GRAMMAR, operatorRules: isStoredRow(rules) ? operatorPartOf(read) : { grammar: SESSION_RULES_GRAMMAR } };
|
|
441
|
+
}
|
|
442
|
+
const operatorRules = operatorPartOf(readStoredOrRefuse(prior));
|
|
443
|
+
const loosens = loosenReasons(operatorRules, clean, mountedToolNames);
|
|
444
|
+
if (loosens.length > 0) {
|
|
445
|
+
throw new SessionPolicyError("loosen_forbidden", `a non-operator session-rule write may not loosen what an operator wrote; refused: ${loosens.join("; ")}`);
|
|
446
|
+
}
|
|
447
|
+
return { ...clean, grammar: SESSION_RULES_GRAMMAR, operatorRules };
|
|
448
|
+
}
|
|
449
|
+
function operatorPartOf(read) {
|
|
450
|
+
const { operatorRules, ...whole } = read;
|
|
451
|
+
const part = operatorRules ?? whole;
|
|
452
|
+
return { ...canonicalRules(part), grammar: part.grammar };
|
|
453
|
+
}
|
|
454
|
+
function readStoredOrRefuse(prior) {
|
|
455
|
+
const stored = readSessionRulesShape(prior);
|
|
456
|
+
if ("fault" in stored) {
|
|
457
|
+
throw new SessionPolicyError("corrupt", `the stored session rules cannot be read as rules (${stored.sentence}) — refusing to judge a non-operator write against them as fewer rules; an operator write replaces them`);
|
|
296
458
|
}
|
|
297
|
-
return
|
|
459
|
+
return stored.rules;
|
|
298
460
|
}
|
|
299
461
|
export function loosenReasons(priorValue, nextValue, mountedToolNames = NO_DECLARED_TOOLS) {
|
|
300
462
|
const shapeOf = (side, value) => {
|