@sema-agent/server 7.132.0 → 7.134.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/MIGRATION.md +353 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +301 -64
- package/deploy/sema-up/README.md +35 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
- package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +19 -2
- package/deploy/sema-up/chart/templates/server.yaml +19 -2
- package/deploy/sema-up/chart/values-full-single.yaml +5 -1
- package/deploy/sema-up/chart/values.yaml +34 -0
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +32 -14
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +83 -23
- package/dist/approval-card.js +45 -15
- package/dist/approval-content-kind.d.ts +5 -2
- package/dist/approval-content-kind.js +16 -3
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval-gate-currency.d.ts +72 -0
- package/dist/approval-gate-currency.js +94 -0
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +55 -17
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/coordinators.d.ts +6 -1
- package/dist/boot/coordinators.js +6 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.d.ts +2 -0
- package/dist/boot/leader.js +4 -1
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/read-deny-anchor-audit.js +2 -2
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.d.ts +18 -5
- package/dist/boot/runner-deps.js +10 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +6 -3
- package/dist/boot/stage-06-runners.js +20 -4
- package/dist/boot/stage-07-capability-layer.d.ts +4 -1
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +4 -1
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +5 -1
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +5 -1
- package/dist/boot/stage-10-http-server.js +6 -6
- package/dist/boot/stores.d.ts +8 -0
- package/dist/boot/stores.js +10 -14
- package/dist/boot/web-admin.d.ts +10 -0
- package/dist/boot/web-admin.js +162 -65
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -1
- package/dist/caller-text-echo.d.ts +11 -6
- package/dist/caller-text-echo.js +10 -12
- package/dist/canonical-json.d.ts +2 -41
- package/dist/canonical-json.js +2 -13
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +29 -6
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +36 -4
- package/dist/capability-facts.js +30 -4
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
- package/dist/checkpoint-ctx-seal-m28.js +19 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +44 -0
- package/dist/field-conflict.js +21 -0
- package/dist/file-history-disclosure.d.ts +34 -5
- package/dist/file-history-disclosure.js +2 -2
- package/dist/fleet/fleet-bus.d.ts +84 -6
- package/dist/fleet/fleet-bus.js +42 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +111 -60
- package/dist/http/approval-sweeps.js +58 -19
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +173 -18
- package/dist/http/checkpoint-ctx.js +171 -12
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +13 -7
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +37 -12
- package/dist/http/idempotency.d.ts +2 -2
- package/dist/http/idempotency.js +2 -2
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +78 -27
- package/dist/http/principal-gate.js +64 -14
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +12 -0
- package/dist/http/refusal-body.js +11 -0
- package/dist/http/request-guards.d.ts +16 -32
- package/dist/http/request-guards.js +31 -30
- package/dist/http/resume-ctx-read.d.ts +50 -6
- package/dist/http/resume-ctx-read.js +33 -7
- package/dist/http/resume-legs.d.ts +5 -5
- package/dist/http/resume-legs.js +163 -91
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -37
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.js +91 -56
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +6 -2
- package/dist/http/routes/fleet.js +4 -4
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +9 -22
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +63 -115
- package/dist/http/routes/session-sync.d.ts +3 -2
- package/dist/http/routes/session-sync.js +53 -48
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions-list.js +3 -4
- package/dist/http/routes/sessions.js +33 -43
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +71 -30
- package/dist/http/routes/trace-usage.js +7 -9
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/run-declared-families.d.ts +16 -0
- package/dist/http/run-declared-families.js +12 -0
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +23 -18
- package/dist/http/server.js +20 -15
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +4 -3
- package/dist/http/submit-ctx.js +23 -6
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +17 -10
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/leader/wire.d.ts +4 -0
- package/dist/leader/wire.js +8 -7
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/memory-origin-fence.js +2 -2
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-compat.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +22 -25
- package/dist/observability/prompt-manifest.js +54 -50
- package/dist/observability/tool-trace.js +9 -10
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +119 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +43 -11
- package/dist/parked-decide.js +100 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/permission-rule-vocab.d.ts +1 -23
- package/dist/permission-rule-vocab.js +0 -13
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
- package/dist/plugins/approval-payload-fingerprint.js +1 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +4 -1
- package/dist/plugins/caching-session-store.js +7 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +36 -1
- package/dist/plugins/checkpoint-store-sql.js +65 -3
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +15 -2
- package/dist/plugins/local-checkpoint-store.js +32 -1
- package/dist/plugins/local-session-store.d.ts +13 -10
- package/dist/plugins/local-session-store.js +23 -14
- package/dist/plugins/local-session-window.d.ts +45 -0
- package/dist/plugins/local-session-window.js +38 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +121 -5
- package/dist/plugins/one-time-migrations.js +332 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-file.js +10 -6
- package/dist/plugins/permission-rule-store-sql.js +8 -8
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +18 -5
- package/dist/plugins/pg-session-storage.js +68 -23
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-device.d.ts +14 -7
- package/dist/plugins/remote-env-device.js +23 -15
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-ownership.d.ts +11 -0
- package/dist/plugins/session-ownership.js +11 -0
- package/dist/plugins/session-placement.d.ts +12 -14
- package/dist/plugins/session-placement.js +2 -15
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +25 -5
- package/dist/plugins/tidb-session-store.js +67 -21
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-tool-axes.d.ts +12 -0
- package/dist/request-tool-axes.js +20 -0
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +37 -6
- package/dist/runs.d.ts +12 -10
- package/dist/runs.js +25 -6
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/sealed-key.d.ts +32 -0
- package/dist/sealed-key.js +55 -1
- package/dist/security.d.ts +95 -15
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +31 -7
- package/dist/session-error-wire.js +9 -2
- package/dist/session-sync-kernel.d.ts +37 -10
- package/dist/session-sync-kernel.js +10 -0
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-a2a.js +4 -3
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +5 -5
- package/dist/task-mcp.js +27 -74
- package/dist/task-settings.d.ts +93 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +451 -136
- package/dist/tool-approval.js +733 -256
- package/dist/tool-rule-names.d.ts +6 -0
- package/dist/trace/core-keyset-guard.d.ts +108 -25
- package/dist/trace/exit-seat.d.ts +40 -0
- package/dist/trace/exit-seat.js +130 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/project.d.ts +98 -13
- package/dist/trace/project.js +57 -32
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +57 -0
- package/dist/trace/redact.js +962 -168
- package/dist/trace/self-minted-wire.d.ts +349 -1
- package/dist/trace/self-minted-wire.js +118 -1
- package/dist/trace/wire-projection-faces.d.ts +304 -2
- package/dist/trace/wire-projection-faces.js +160 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.js +6 -8
- package/dist/web-admin-client/types.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -2
- package/scripts/drain-check.mysql.sql +20 -2
- package/scripts/drain-check.pg.sql +20 -2
- package/dist/mcp-tool-faces.d.ts +0 -69
- package/dist/mcp-tool-faces.js +0 -106
|
@@ -4,7 +4,7 @@ import { sameExecutionRecord } from "@sema-agent/core";
|
|
|
4
4
|
import { DECIDED_REPLAY_SCAN_CAP, approvalPayloadFingerprint } from "../../plugins/checkpoint-store-sql.js";
|
|
5
5
|
import { APPROVAL_GATE_KINDS, carriesDeploymentListQuestion, standingAnswerDurablyRecordable } from "../../tool-approval.js";
|
|
6
6
|
import { isParkedRunStatus } from "../../plugins/store-contracts.js";
|
|
7
|
-
import { principalFrom, decodeCheckpointScope, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../../security.js";
|
|
7
|
+
import { principalFrom, decodeCheckpointScope, ownerOfCheckpointScope, CHECKPOINT_PUBLIC_SCOPE, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../../security.js";
|
|
8
8
|
import { editedPlanBinding, isWellFormedUnicode, verifyDirectDoorProof } from "../../principal-jwt.js";
|
|
9
9
|
import { MAX_APPROVAL_REASON_CHARS, projectQuestionAnswer, questionAnswerFromProjection } from "../../approval-hmac.js";
|
|
10
10
|
import { PLAN_APPROVE_PERMISSION_MODES_AFTER, isPlanApprovePermissionModeAfter, planReviewDecisionExitsPlan, storedBodyPermissionMode } from "../../task-settings.js";
|
|
@@ -14,22 +14,26 @@ import { redactRiskDescriptor } from "../../observability/run-terminal.js";
|
|
|
14
14
|
import { buildRunName } from "../../fleet/fleet-bus.js";
|
|
15
15
|
import { sleep } from "../sse-log.js";
|
|
16
16
|
import { bindSseLifecycle } from "../sse-lifecycle.js";
|
|
17
|
-
import { sendJson, sendError, sseHeaders, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "../send.js";
|
|
18
|
-
import { gatedPrincipal, explicitOperatorOk,
|
|
17
|
+
import { sendJson, sendError, sseHeaders, logRequestError, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "../send.js";
|
|
18
|
+
import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal, sessionCallerOf } from "../principal-gate.js";
|
|
19
|
+
import { readOwnedRun, readOwnedSession } from "../owner-access.js";
|
|
19
20
|
import { governanceOriginOf } from "../../runtime-governance.js";
|
|
20
21
|
import { deploymentListAsks } from "../../approval.js";
|
|
21
22
|
import { callGrantBindingOf, questionGrantBindingOf } from "../../standing-answer-grant.js";
|
|
22
23
|
import { sendResumeOutcome } from "../route-ctx.js";
|
|
23
24
|
import { assertNever } from "../route-ctx.js";
|
|
24
25
|
import * as facts from "../../capability-facts.js";
|
|
25
|
-
import { readResumeCtx } from "../resume-ctx-read.js";
|
|
26
|
+
import { KEEP_SEALED, readResumeCtx } from "../resume-ctx-read.js";
|
|
27
|
+
import { StoreCorruptError } from "../../plugins/sql-json-column.js";
|
|
26
28
|
import { recordFailOpen } from "../../observability/fail-open.js";
|
|
29
|
+
import { durableRowIdentity } from "../../checkpoint-identity.js";
|
|
27
30
|
import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "../../request-key-closure.js";
|
|
31
|
+
import { fieldConflictFacts } from "../../field-conflict.js";
|
|
28
32
|
const DECIDE_BODY_DECLARED_KEYS = [
|
|
29
|
-
"answer", "boundCallId", "boundInputHash", "checkpointToken", "decidedBy", "decision", "reason", "remember", "updatedInput",
|
|
33
|
+
"answer", "boundCallId", "boundInputHash", "checkpointToken", "decidedBy", "decision", "feedback", "reason", "remember", "updatedInput",
|
|
30
34
|
];
|
|
31
35
|
const DECIDE_PROOF_COVERED_KEYS = ["answer", "boundCallId", "boundInputHash", "decision", "reason"];
|
|
32
|
-
const DECIDE_NOT_IN_PROOF_KEYS = ["checkpointToken", "decidedBy", "remember", "updatedInput"];
|
|
36
|
+
const DECIDE_NOT_IN_PROOF_KEYS = ["checkpointToken", "decidedBy", "feedback", "remember", "updatedInput"];
|
|
33
37
|
const PLAN_REVIEW_BODY_DECLARED_KEYS = [
|
|
34
38
|
"boundCallId", "decidedBy", "decision", "editedPlan", "permissionModeAfter", "reason",
|
|
35
39
|
];
|
|
@@ -268,20 +272,32 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
268
272
|
}
|
|
269
273
|
const cs = park.checkpointStore;
|
|
270
274
|
const principal = gatedPrincipal(req, deps.config);
|
|
271
|
-
const operator =
|
|
275
|
+
const operator = explicitOperatorOk(principal, deps.config);
|
|
276
|
+
const ownScope = principal ?? CHECKPOINT_PUBLIC_SCOPE;
|
|
272
277
|
if (match.decl.id === "approvals-stream") {
|
|
273
278
|
const scope = operator
|
|
274
279
|
? (new URLSearchParams(match.search).get("owner") ?? undefined)
|
|
275
|
-
:
|
|
280
|
+
: ownScope;
|
|
276
281
|
await streamApprovals(req, res, cs, deps.toolApproval, scope, deps.config);
|
|
277
282
|
return;
|
|
278
283
|
}
|
|
279
284
|
if (match.decl.id === "approvals-list") {
|
|
280
285
|
const scope = operator
|
|
281
286
|
? (new URLSearchParams(match.search).get("owner") ?? undefined)
|
|
282
|
-
:
|
|
287
|
+
: ownScope;
|
|
288
|
+
let durableRows;
|
|
289
|
+
try {
|
|
290
|
+
durableRows = await cs.listPending(scope);
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
if (!isApprovalsReadCorrupt(err))
|
|
294
|
+
throw err;
|
|
295
|
+
logRequestError(deps.logger, req, err);
|
|
296
|
+
sendError(res, 500, "approvals.read_corrupt", "a stored approval row cannot be read - retrying this request will fail the same way until an operator repairs or removes the row");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
283
299
|
sendJson(res, 200, {
|
|
284
|
-
pending:
|
|
300
|
+
pending: durableRows.map((r) => projectPendingForWire(r, deps.config)),
|
|
285
301
|
serverNowMs: Date.now(),
|
|
286
302
|
...(deps.toolApproval ? { livePending: deps.toolApproval.listLivePending(scope) } : {}),
|
|
287
303
|
...(deps.approvalAskAudit ? { crashConverged: deps.approvalAskAudit.listCrashConverged(scope) } : {}),
|
|
@@ -300,17 +316,13 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
300
316
|
sendError(res, 400, "request.path_malformed", "malformed id (invalid percent-encoding)");
|
|
301
317
|
return;
|
|
302
318
|
}
|
|
303
|
-
|
|
304
|
-
const isExplicitOperator = explicitOperatorOk(principal, operators);
|
|
305
|
-
if (!isExplicitOperator) {
|
|
319
|
+
if (!explicitOperatorOk(principal, deps.config)) {
|
|
306
320
|
const owned = facts.sessionOwnership(deps);
|
|
307
321
|
if (!owned.available) {
|
|
308
322
|
sendError(res, 501, "capability.session_store_required", "approval exemptions require a session-store backend");
|
|
309
323
|
return;
|
|
310
324
|
}
|
|
311
|
-
|
|
312
|
-
const owner = await ownerOf(exSessionId);
|
|
313
|
-
if (owner === undefined || (owner !== null && owner !== principal)) {
|
|
325
|
+
if ((await readOwnedSession(deps, owned.sessionStorage, sessionCallerOf(req, deps), exSessionId, "owner")) === undefined) {
|
|
314
326
|
sendError(res, 404, "not_found.session", "not found");
|
|
315
327
|
return;
|
|
316
328
|
}
|
|
@@ -329,22 +341,28 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
329
341
|
return;
|
|
330
342
|
}
|
|
331
343
|
const revoked = await deps.approvalExemptionStore.revoke(exSessionId, exToolName);
|
|
332
|
-
|
|
344
|
+
if (revoked)
|
|
345
|
+
sendJson(res, 200, { revoked: true });
|
|
346
|
+
else
|
|
347
|
+
sendError(res, 404, "not_found.exemption", "not found");
|
|
333
348
|
return;
|
|
334
349
|
}
|
|
335
350
|
}
|
|
336
351
|
if (match.decl.id === "assistant-inbox") {
|
|
337
352
|
const ownerParam = new URLSearchParams(match.search).get("owner") || undefined;
|
|
338
|
-
const scope = operator && ownerParam ? ownerParam :
|
|
353
|
+
const scope = operator && ownerParam ? ownerParam : ownScope;
|
|
339
354
|
const summaries = await cs.listByScope(scope);
|
|
340
355
|
const inbox = (await Promise.all(summaries.map(async (s) => {
|
|
341
|
-
const ctxRead = await readResumeCtx(cs.getCtx(s.sessionId));
|
|
356
|
+
const ctxRead = await readResumeCtx(cs.getCtx(s.sessionId), KEEP_SEALED);
|
|
342
357
|
if (ctxRead.kind === "corrupt")
|
|
343
358
|
recordFailOpen("server.assistant-inbox.objective-ctx-corrupt", ctxRead.where);
|
|
344
|
-
const
|
|
359
|
+
const storedBody = ctxRead.kind === "ok" ? ctxRead.ctx.body : undefined;
|
|
360
|
+
const storedObjective = typeof storedBody === "object" && storedBody !== null ? storedBody.objective : undefined;
|
|
361
|
+
const objective = typeof storedObjective === "string" ? storedObjective : null;
|
|
345
362
|
const input = s.toolInput != null ? redactedPreview(s.toolInput) : null;
|
|
346
363
|
return {
|
|
347
364
|
sessionId: s.sessionId,
|
|
365
|
+
...durableRowIdentity("assistant-inbox", s.checkpointId, s.token),
|
|
348
366
|
scope: s.scope,
|
|
349
367
|
createdAt: s.createdAt,
|
|
350
368
|
...(s.gateKind !== undefined ? { gateKind: s.gateKind } : {}),
|
|
@@ -364,13 +382,14 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
364
382
|
objective,
|
|
365
383
|
input,
|
|
366
384
|
};
|
|
367
|
-
})))
|
|
385
|
+
})))
|
|
386
|
+
.sort((a, b) => (b.severity ?? 0) - (a.severity ?? 0) || (a.createdAt ?? 0) - (b.createdAt ?? 0));
|
|
368
387
|
sendJson(res, 200, { inbox });
|
|
369
388
|
return;
|
|
370
389
|
}
|
|
371
390
|
if (match.decl.id === "assistant-tasks") {
|
|
372
391
|
const ownerParam = new URLSearchParams(match.search).get("owner") || undefined;
|
|
373
|
-
const scope = operator && ownerParam ? ownerParam :
|
|
392
|
+
const scope = operator && ownerParam ? ownerParam : ownScope;
|
|
374
393
|
const ledger = facts.durableRuns(deps);
|
|
375
394
|
if (!ledger.available) {
|
|
376
395
|
sendJson(res, 200, { tasks: [] });
|
|
@@ -379,7 +398,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
379
398
|
const runStore = ledger.runStore;
|
|
380
399
|
const summaries = await cs.listByScope(scope);
|
|
381
400
|
const byGate = new Map(summaries.map((s) => [s.sessionId, s]));
|
|
382
|
-
const runs = await runStore.listRuns({ owner: scope, limit: 100 });
|
|
401
|
+
const runs = await runStore.listRuns({ owner: ownerOfCheckpointScope(scope), limit: 100 });
|
|
383
402
|
const tasks = runs
|
|
384
403
|
.filter((r) => r.status === "running" || isParkedRunStatus(r.status))
|
|
385
404
|
.map((r) => {
|
|
@@ -416,17 +435,11 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
416
435
|
return;
|
|
417
436
|
}
|
|
418
437
|
const taskId = match.params.taskId;
|
|
419
|
-
const run = await runStore
|
|
438
|
+
const run = await readOwnedRun(deps.config, runStore, principal, taskId, "owner_or_operator");
|
|
420
439
|
if (!run) {
|
|
421
440
|
sendError(res, 404, "not_found.run", "task not found");
|
|
422
441
|
return;
|
|
423
442
|
}
|
|
424
|
-
const operators = deps.config.operatorPrincipals;
|
|
425
|
-
const explicitOperator = explicitOperatorOk(principal, operators);
|
|
426
|
-
if (!explicitOperator && run.owner !== null && run.owner !== principal) {
|
|
427
|
-
sendError(res, 404, "not_found.run", "task not found");
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
443
|
if (run.status === "running") {
|
|
431
444
|
const ownedHere = run.instanceId != null && run.instanceId === deps.instanceId;
|
|
432
445
|
if (ownedHere && !preemptableRuns.has(taskId)) {
|
|
@@ -482,8 +495,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
482
495
|
sendError(res, 404, "not_found.run", "task not found");
|
|
483
496
|
return;
|
|
484
497
|
}
|
|
485
|
-
const
|
|
486
|
-
const explicitOperator = explicitOperatorOk(principal, operators);
|
|
498
|
+
const explicitOperator = explicitOperatorOk(principal, deps.config);
|
|
487
499
|
if (!explicitOperator && run.owner !== null && run.owner !== principal) {
|
|
488
500
|
sendError(res, 404, "not_found.run", "task not found");
|
|
489
501
|
return;
|
|
@@ -520,7 +532,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
520
532
|
}
|
|
521
533
|
}
|
|
522
534
|
if (decision === "edit" && (typeof body.editedPlan !== "string" || body.editedPlan.length === 0)) {
|
|
523
|
-
sendError(res, 400, "request.field_conflict", "decision 'edit' requires a non-empty editedPlan (the operator's revised plan)");
|
|
535
|
+
sendError(res, 400, "request.field_conflict", "decision 'edit' requires a non-empty editedPlan (the operator's revised plan)", fieldConflictFacts("plan_edit", ["decision", "editedPlan"]));
|
|
524
536
|
return;
|
|
525
537
|
}
|
|
526
538
|
const decidedByReading = readDecidedBy(body.decidedBy, deps.config.directDoorActive);
|
|
@@ -543,7 +555,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
543
555
|
return;
|
|
544
556
|
}
|
|
545
557
|
if (decision !== "edit" && body.editedPlan !== undefined) {
|
|
546
|
-
sendError(res, 400, "request.field_conflict", `editedPlan is only valid with decision 'edit' (got '${decision}')
|
|
558
|
+
sendError(res, 400, "request.field_conflict", `editedPlan is only valid with decision 'edit' (got '${decision}')`, fieldConflictFacts("plan_edit", ["editedPlan", "decision"]));
|
|
547
559
|
return;
|
|
548
560
|
}
|
|
549
561
|
if (body.permissionModeAfter !== undefined && !isPlanApprovePermissionModeAfter(body.permissionModeAfter)) {
|
|
@@ -551,7 +563,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
551
563
|
return;
|
|
552
564
|
}
|
|
553
565
|
if (!planReviewDecisionExitsPlan(decision) && body.permissionModeAfter !== undefined) {
|
|
554
|
-
sendError(res, 400, "request.field_conflict", `permissionModeAfter is only valid with a decision that carries the plan out ('approve' or 'edit'; got '${decision}')
|
|
566
|
+
sendError(res, 400, "request.field_conflict", `permissionModeAfter is only valid with a decision that carries the plan out ('approve' or 'edit'; got '${decision}')`, fieldConflictFacts("plan_mode_after", ["permissionModeAfter", "decision"]));
|
|
555
567
|
return;
|
|
556
568
|
}
|
|
557
569
|
if (body.reason !== undefined && typeof body.reason !== "string") {
|
|
@@ -572,7 +584,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
572
584
|
return;
|
|
573
585
|
}
|
|
574
586
|
if (!deps.config.directDoorActive) {
|
|
575
|
-
sendError(res, 400, "request.field_conflict", "boundCallId (the plan_review nonce) is only valid on a direct-door worker — a BFF worker carries no decision proof to bind it to");
|
|
587
|
+
sendError(res, 400, "request.field_conflict", "boundCallId (the plan_review nonce) is only valid on a direct-door worker — a BFF worker carries no decision proof to bind it to", fieldConflictFacts("bound_call_door", ["boundCallId"]));
|
|
576
588
|
return;
|
|
577
589
|
}
|
|
578
590
|
}
|
|
@@ -611,8 +623,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
611
623
|
deciderPrincipal = proof.principal;
|
|
612
624
|
singleUse = proof.singleUse === undefined ? undefined : { proof: proof.singleUse, store };
|
|
613
625
|
}
|
|
614
|
-
const
|
|
615
|
-
const explicitOperator = explicitOperatorOk(deciderPrincipal, operators);
|
|
626
|
+
const explicitOperator = explicitOperatorOk(deciderPrincipal, deps.config);
|
|
616
627
|
if (!explicitOperator && run.owner !== null && run.owner !== deciderPrincipal) {
|
|
617
628
|
deps.logger?.info?.("decide_404", { reason: "owner-mismatch", taskId, principalPresent: principal !== undefined });
|
|
618
629
|
sendError(res, 404, "not_found.run", "task not found");
|
|
@@ -626,7 +637,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
626
637
|
if (body.permissionModeAfter !== undefined) {
|
|
627
638
|
const storedCtx = plan.prepared.ctx;
|
|
628
639
|
if (storedCtx.body !== undefined && storedBodyPermissionMode(storedCtx.body) !== "plan") {
|
|
629
|
-
sendError(res, 400, "request.field_conflict", "permissionModeAfter does not apply to this task: it was not started in plan mode (its stored permission mode is not \"plan\"), so approving the plan returns it to the mode it was in before planning");
|
|
640
|
+
sendError(res, 400, "request.field_conflict", "permissionModeAfter does not apply to this task: it was not started in plan mode (its stored permission mode is not \"plan\"), so approving the plan returns it to the mode it was in before planning", fieldConflictFacts("plan_mode_after", ["permissionModeAfter"]));
|
|
630
641
|
return;
|
|
631
642
|
}
|
|
632
643
|
}
|
|
@@ -657,7 +668,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
657
668
|
const body = (await readJson(req));
|
|
658
669
|
const decision = body?.decision === "approve" ? "approve" : body?.decision === "deny" ? "deny" : undefined;
|
|
659
670
|
if (!decision) {
|
|
660
|
-
sendError(res, 400, "request.body_shape", "body must be { decision: 'approve' | 'deny', reason?, answer?, checkpointToken?, boundCallId?, boundInputHash?, updatedInput?, remember?, decidedBy? }", retiredDecisionKeyFacts(body)?.extra);
|
|
671
|
+
sendError(res, 400, "request.body_shape", "body must be { decision: 'approve' | 'deny', reason?, answer?, checkpointToken?, boundCallId?, boundInputHash?, updatedInput?, remember?, decidedBy?, feedback? }", retiredDecisionKeyFacts(body)?.extra);
|
|
661
672
|
return;
|
|
662
673
|
}
|
|
663
674
|
{
|
|
@@ -683,7 +694,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
683
694
|
return;
|
|
684
695
|
}
|
|
685
696
|
if (decision !== "approve") {
|
|
686
|
-
sendError(res, 400, "request.field_conflict", "remember requires decision 'approve'");
|
|
697
|
+
sendError(res, 400, "request.field_conflict", "remember requires decision 'approve'", fieldConflictFacts("remember_decision", ["remember", "decision"]));
|
|
687
698
|
return;
|
|
688
699
|
}
|
|
689
700
|
if (deps.config.directDoorActive) {
|
|
@@ -721,6 +732,10 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
721
732
|
return;
|
|
722
733
|
}
|
|
723
734
|
}
|
|
735
|
+
if (body.feedback !== undefined && typeof body.feedback !== "string") {
|
|
736
|
+
sendError(res, 400, "request.field_invalid", "feedback must be a string (the words the approving person wrote on the card; omit the key when there are none)");
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
724
739
|
if (deps.config.directDoorActive && body.updatedInput !== undefined) {
|
|
725
740
|
sendError(res, 400, "updated_input_not_in_proof", "updatedInput is not supported on a direct-door worker (not covered by the decision proof)");
|
|
726
741
|
return;
|
|
@@ -729,6 +744,10 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
729
744
|
sendError(res, 400, "checkpoint_token_not_in_proof", "checkpointToken is not supported on a direct-door worker (not covered by the decision proof); bind the decision with boundCallId and boundInputHash instead");
|
|
730
745
|
return;
|
|
731
746
|
}
|
|
747
|
+
if (deps.config.directDoorActive && body.feedback !== undefined) {
|
|
748
|
+
sendError(res, 400, "feedback_not_in_proof", "feedback is not supported on a direct-door worker (not covered by the decision proof)");
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
732
751
|
const decidedByReading = readDecidedBy(body.decidedBy, deps.config.directDoorActive);
|
|
733
752
|
switch (decidedByReading.kind) {
|
|
734
753
|
case "not_in_proof":
|
|
@@ -745,11 +764,20 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
745
764
|
}
|
|
746
765
|
}
|
|
747
766
|
const decidedBy = decidedByReading.decidedBy;
|
|
767
|
+
if (body.feedback !== undefined && decision !== "approve") {
|
|
768
|
+
sendError(res, 400, "request.field_conflict", "feedback is only valid with decision 'approve' — the words of a denial are its reason", fieldConflictFacts("approval_feedback", ["feedback", "decision"]));
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (body.feedback !== undefined && decidedBy !== "person") {
|
|
772
|
+
sendError(res, 400, "request.field_conflict", "feedback is only valid on a person's decision — the agent reads it as the user's own words, which a policy decision cannot carry", fieldConflictFacts("approval_feedback", ["feedback", "decidedBy"]));
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
748
775
|
const binding = {
|
|
749
776
|
checkpointToken: body.checkpointToken,
|
|
750
777
|
boundCallId: body.boundCallId,
|
|
751
778
|
boundInputHash: body.boundInputHash,
|
|
752
779
|
updatedInput: body.updatedInput,
|
|
780
|
+
...(typeof body.feedback === "string" ? { feedback: body.feedback } : {}),
|
|
753
781
|
};
|
|
754
782
|
let deciderPrincipal = principal;
|
|
755
783
|
if (deps.config.directDoorActive) {
|
|
@@ -770,8 +798,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
770
798
|
}
|
|
771
799
|
deciderPrincipal = proof.principal;
|
|
772
800
|
}
|
|
773
|
-
const
|
|
774
|
-
const explicitOperator = explicitOperatorOk(deciderPrincipal, operators);
|
|
801
|
+
const explicitOperator = explicitOperatorOk(deciderPrincipal, deps.config);
|
|
775
802
|
if (!explicitOperator) {
|
|
776
803
|
const cpScope = await cs
|
|
777
804
|
.peekPendingScope(sessionId, { gateKinds: APPROVAL_GATE_KINDS })
|
|
@@ -814,6 +841,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
814
841
|
...(decision === "approve" && binding.updatedInput !== undefined ? { updatedInput: binding.updatedInput } : {}),
|
|
815
842
|
...(answer !== undefined ? { answer } : {}),
|
|
816
843
|
...((r) => (r !== undefined ? { reason: r } : {}))(decisionReasonOf(body)),
|
|
844
|
+
...(binding.feedback !== undefined ? { feedback: binding.feedback } : {}),
|
|
817
845
|
},
|
|
818
846
|
deciderPrincipal,
|
|
819
847
|
explicitOperator,
|
|
@@ -830,6 +858,9 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
830
858
|
return assertNever(match.decl.id);
|
|
831
859
|
}
|
|
832
860
|
const APPROVALS_STREAM_POLL_MS = 3000;
|
|
861
|
+
function isApprovalsReadCorrupt(err) {
|
|
862
|
+
return err instanceof StoreCorruptError;
|
|
863
|
+
}
|
|
833
864
|
function redactPendingDisclosures(row) {
|
|
834
865
|
const rd = row.riskDescriptor;
|
|
835
866
|
if (rd === null || rd === undefined)
|
|
@@ -895,23 +926,27 @@ export async function streamApprovals(req, res, cs, live, scope, governance, pol
|
|
|
895
926
|
});
|
|
896
927
|
let first = true;
|
|
897
928
|
while (!closed) {
|
|
898
|
-
let
|
|
899
|
-
let livePending;
|
|
929
|
+
let snapshot;
|
|
900
930
|
try {
|
|
901
|
-
pending = (await cs.listPending(scope)).map((r) => projectPendingForWire(r, governance));
|
|
902
|
-
|
|
931
|
+
const pending = (await cs.listPending(scope)).map((r) => projectPendingForWire(r, governance));
|
|
932
|
+
snapshot = { pending, livePending: live ? live.listLivePending(scope) : [] };
|
|
903
933
|
}
|
|
904
|
-
catch {
|
|
934
|
+
catch (err) {
|
|
935
|
+
if (isApprovalsReadCorrupt(err)) {
|
|
936
|
+
if (!res.writableEnded)
|
|
937
|
+
res.write(`event: error\ndata: ${JSON.stringify({ type: "error", errorCode: "approvals.read_corrupt", message: "a stored approval row cannot be read - this stream is closing, and reconnecting will fail the same way until an operator repairs or removes the row" })}\n\n`);
|
|
938
|
+
break;
|
|
939
|
+
}
|
|
905
940
|
if (!res.writableEnded)
|
|
906
|
-
res.write(`event:
|
|
907
|
-
await sleep(pollMs);
|
|
908
|
-
continue;
|
|
941
|
+
res.write(`event: error\ndata: ${JSON.stringify({ type: "error", errorCode: "approvals.read_unavailable", message: "the approvals queue could not be read - this stream stays open and retries on its next poll; until a read succeeds, silence here does not mean nothing is pending" })}\n\n`);
|
|
909
942
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
943
|
+
if (snapshot !== undefined) {
|
|
944
|
+
durableLane.tick(snapshot.pending);
|
|
945
|
+
liveLane.tick(snapshot.livePending);
|
|
946
|
+
if (first) {
|
|
947
|
+
res.write(`event: synced\ndata: ${JSON.stringify({ type: "synced", count: snapshot.pending.length })}\n\n`);
|
|
948
|
+
first = false;
|
|
949
|
+
}
|
|
915
950
|
}
|
|
916
951
|
if (Date.now() - start > SSE_MAX_STREAM_MS) {
|
|
917
952
|
res.write(`event: error\ndata: ${JSON.stringify({ type: "error", errorCode: "STREAM_MAX_DURATION", message: "approvals stream reached its 15-minute cap — reconnect to continue" })}\n\n`);
|
|
@@ -7,6 +7,7 @@ import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal } from "../pri
|
|
|
7
7
|
import {} from "../route-ctx.js";
|
|
8
8
|
import { assertNever, SESSION_NOT_FOUND_MESSAGE } from "../route-ctx.js";
|
|
9
9
|
import * as facts from "../../capability-facts.js";
|
|
10
|
+
import { sessionOwnerCellOf } from "../../security.js";
|
|
10
11
|
const LIST_LIMIT = 500;
|
|
11
12
|
export const DESCRIPTION_MAX = 500;
|
|
12
13
|
const ROW_KEY_DISPOSITION = {
|
|
@@ -67,8 +68,8 @@ export async function handleBackground(req, res, match, ctx) {
|
|
|
67
68
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
71
|
+
const operator = explicitOperatorOk(principal, deps.config);
|
|
72
|
+
if (!operator && !ctx.helpers.sessionOwnerOk(req, res, await sessionOwnerCellOf(owned.sessionStorage, sessionId, owner)))
|
|
72
73
|
return;
|
|
73
74
|
const scope = owner ?? "default";
|
|
74
75
|
switch (id) {
|
|
@@ -2,6 +2,8 @@ import { PERMISSION_MODES, USER_ATTACHMENT_SEAT, expandTiers, reasoningEffortLev
|
|
|
2
2
|
import { modelImageInput, modelReasoningDecl, isAtMentionable, selectableCatalog } from "../../model-select.js";
|
|
3
3
|
import { buildDroppedEntriesWire } from "../../web-admin-client/read-warnings.js";
|
|
4
4
|
import { buildCandidateRejectedWire } from "../../web-admin-client/candidate-gate.js";
|
|
5
|
+
import { buildModelPlaneFace } from "../../model-plane-face.js";
|
|
6
|
+
import { isRosterGateArmed } from "../../config.js";
|
|
5
7
|
import { modelKeyPoisonOf, resolveModelApiKey } from "../../key-resolver.js";
|
|
6
8
|
import { projectSealedKeyCapability } from "../../sealed-key.js";
|
|
7
9
|
import { cwdHonored, deviceCwdHonored } from "../../task-cwd.js";
|
|
@@ -10,7 +12,7 @@ import { leaderEntryRefusal, leaderRunEntry } from "../../leader/run-entry.js";
|
|
|
10
12
|
import { autonomyKeepsOpenWriteFace, autonomyModeFloor } from "../../runtime-governance.js";
|
|
11
13
|
import { DEVICE_PROTOCOL_VERSION, DEVICE_WS_PATH } from "../../device-ws-protocol.js";
|
|
12
14
|
import { a2aInjectionHonored } from "../../task-a2a.js";
|
|
13
|
-
import { buildEmptyMcpProbeFace, buildMcpInjectionRefusal, buildMcpProbeCacheKey, buildMcpProbeInflightRefusal, buildMcpProbeRateKey, buildMcpProbeRateRefusal, createMcpProbeLocal, buildMcpProbeDeclarationRefusal, buildMcpProbeIncompleteRefusal, McpProbeIncomplete, MCP_PROBE_HTTP_STATUS, MCP_PROBE_MAX_INFLIGHT, MCP_PROBE_VERDICT_TIMEOUT_MS, createMcpProbeWalk, readMcpProbeBody, } from "../../capabilities/mcp-probe.js";
|
|
15
|
+
import { buildEmptyMcpProbeFace, buildMcpInjectionRefusal, buildMcpProbeCacheKey, buildMcpProbeInflightRefusal, buildMcpProbeRateKey, buildMcpProbeRateRefusal, createMcpProbeLocal, buildMcpProbeDeclarationRefusal, buildMcpProbeIncompleteRefusal, McpProbeIncomplete, McpProbeMisaligned, MCP_PROBE_HTTP_STATUS, MCP_PROBE_MAX_INFLIGHT, MCP_PROBE_VERDICT_TIMEOUT_MS, createMcpProbeWalk, readMcpProbeBody, } from "../../capabilities/mcp-probe.js";
|
|
14
16
|
import { mcpForScenario } from "../../web-admin-client/facade.js";
|
|
15
17
|
import { sendScenarioNotFound } from "../scenario-read-face.js";
|
|
16
18
|
import { sendJson, sendError } from "../send.js";
|
|
@@ -21,6 +23,7 @@ import { projectWriteProtectionCapability } from "../../write-protection.js";
|
|
|
21
23
|
import { projectStoreCapability } from "../../store-posture.js";
|
|
22
24
|
import { projectWebSearchCapability } from "../../plugins/web-search.js";
|
|
23
25
|
import { projectExecutionLaneCapability } from "../../capabilities/execution-lane.js";
|
|
26
|
+
import { MCP_ASSERTION_HEADER_SENT } from "../../mcp-assertion-header.js";
|
|
24
27
|
import { gateCompositeMembers } from "../../capabilities/composite-members.js";
|
|
25
28
|
import { projectApprovalsStreamLiveCapability } from "../../capabilities/approvals-push.js";
|
|
26
29
|
import { workflowModelAllowlistFor } from "../../task-workflow.js";
|
|
@@ -29,6 +32,7 @@ import * as facts from "../../capability-facts.js";
|
|
|
29
32
|
import { judgeAutoModeArming } from "../../auto-mode-face.js";
|
|
30
33
|
import { coercePermissionModeStrict, PERMISSION_MODE_WORDS, taskHooksHonored } from "../../task-settings.js";
|
|
31
34
|
import { gatedPrincipal, sendPrincipalRefusal } from "../principal-gate.js";
|
|
35
|
+
import { callerTrust } from "../caller-trust.js";
|
|
32
36
|
function routePairingOf(deps, name, m) {
|
|
33
37
|
if (modelKeyPoisonOf(name, deps.config.modelApiKeyEnv ?? {}, process.env, deps.config.modelApiKeys ?? {}) !== undefined)
|
|
34
38
|
return "unknown";
|
|
@@ -72,12 +76,14 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
72
76
|
if (autoModeFault !== undefined)
|
|
73
77
|
deps.logger?.warn("auto_mode_face_resolver_fault", { fault: autoModeFault });
|
|
74
78
|
const rulesLaneForCaller = facts.ruleLaneForCaller(deps, gatedPrincipal(req, deps.config)).available;
|
|
79
|
+
const streamApprovalFact = facts.streamApproval(deps);
|
|
75
80
|
sendJson(res, 200, gateCompositeMembers({
|
|
76
81
|
...deps.capabilities,
|
|
77
82
|
...facts.engineCapabilityBits(),
|
|
78
83
|
asyncRuns: facts.durableRuns(deps).available,
|
|
79
84
|
artifacts: facts.durableRuns(deps).available,
|
|
80
85
|
approvals: facts.checkpointPark(deps).available,
|
|
86
|
+
approvalReadRootGrant: facts.readRootGrant(deps).available,
|
|
81
87
|
sessions: facts.sessionAuditView(deps).available,
|
|
82
88
|
deviceExecutor: facts.deviceLane(deps).available
|
|
83
89
|
? { enabled: true, protocolVersion: DEVICE_PROTOCOL_VERSION, maxInflightPerDevice: deps.config.remoteExec?.provider === "device" ? (deps.config.remoteExec.maxInflightPerDevice ?? 4) : 4, wsPath: DEVICE_WS_PATH, management: facts.deviceManagement(deps).available }
|
|
@@ -100,6 +106,7 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
100
106
|
mcpReconnect: facts.mcpReconnect(deps).available,
|
|
101
107
|
background: { listFace: facts.sessionOwnership(deps).available, exitFaces: facts.sessionOwnership(deps).available },
|
|
102
108
|
sharedMemory: facts.sharedMemoryRead(deps).available,
|
|
109
|
+
principalInboxDelivery: facts.principalInboxDelivery(deps).available,
|
|
103
110
|
adoption: facts.adoption(deps).available,
|
|
104
111
|
memoryBundle: facts.memoryBundle(deps).available,
|
|
105
112
|
memoryCompliance: facts.memoryCompliance(deps).available,
|
|
@@ -124,8 +131,8 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
124
131
|
scratchpadDir: true,
|
|
125
132
|
subagentSteer: facts.subagentSteer(deps).available,
|
|
126
133
|
subagentResume: facts.subagentSteer(deps).available,
|
|
127
|
-
taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: cwdHonored(deps.config) || deviceCwdHonored(deps.config), hooks: taskHooksHonored(deps.config) },
|
|
128
|
-
settings: { permissions: { allowGrant: true, allowLayer: true } },
|
|
134
|
+
taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: cwdHonored(deps.config) || deviceCwdHonored(deps.config), hooks: taskHooksHonored(deps.config), pluginHooks: taskHooksHonored(deps.config), managedHookGroups: taskHooksHonored(deps.config), tightenOnlySeats: true, approvalFrameFamilies: true },
|
|
135
|
+
settings: { permissions: { allowGrant: true, allowLayer: true, callerTrust: callerTrust(req, deps.config).trust } },
|
|
129
136
|
permissionModeAuto: {
|
|
130
137
|
accepted: true,
|
|
131
138
|
classifierSeat: deps.autoModeFace?.seatMounted === true,
|
|
@@ -160,11 +167,13 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
160
167
|
sessionInit: true,
|
|
161
168
|
mcp: true,
|
|
162
169
|
mcpProbe: true,
|
|
170
|
+
mcpAssertionHeaderSent: MCP_ASSERTION_HEADER_SENT,
|
|
163
171
|
mcpElicitation: facts.elicitation(deps).available,
|
|
164
172
|
askUserQuestion: facts.askUserQuestion(deps).available,
|
|
165
173
|
toolApproval: facts.toolApproval(deps).available,
|
|
166
174
|
approvalsStreamLive: projectApprovalsStreamLiveCapability(deps),
|
|
167
|
-
streamApproval:
|
|
175
|
+
streamApproval: streamApprovalFact.available,
|
|
176
|
+
approvalFrameFamilies: [...facts.approvalFrameFamilies(streamApprovalFact)],
|
|
168
177
|
approvalDecisionNote: true,
|
|
169
178
|
approvalDecidedBy: true,
|
|
170
179
|
permissionModes: [...PERMISSION_MODES],
|
|
@@ -273,6 +282,11 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
273
282
|
defaultModel: { id: deps.config.model.id, ...(defaultName ? { name: defaultName } : {}) },
|
|
274
283
|
droppedEntries: buildDroppedEntriesWire(deps.config.droppedCatalogEntries),
|
|
275
284
|
...(candidateRejection !== undefined ? { candidateRejected: buildCandidateRejectedWire(candidateRejection) } : {}),
|
|
285
|
+
modelPlane: buildModelPlaneFace(deps.config, {
|
|
286
|
+
envTableIsPlaceholder: isRosterGateArmed(deps.config.webAdmin),
|
|
287
|
+
candidateRejection,
|
|
288
|
+
modelRefusals: deps.modelRefusalsState?.(),
|
|
289
|
+
}),
|
|
276
290
|
});
|
|
277
291
|
return;
|
|
278
292
|
}
|
|
@@ -330,6 +344,8 @@ async function answerMcpProbe(res, ctx, answer, outcome, declaredBy) {
|
|
|
330
344
|
sendMcpProbeRefusal(res, ctx, buildMcpProbeIncompleteRefusal(err.boundMs), "failed", Math.ceil(err.boundMs / 1000));
|
|
331
345
|
return;
|
|
332
346
|
}
|
|
347
|
+
if (err instanceof McpProbeMisaligned)
|
|
348
|
+
throw err;
|
|
333
349
|
if (declaredBy === "caller") {
|
|
334
350
|
sendMcpProbeRefusal(res, ctx, buildMcpProbeDeclarationRefusal(), "failed");
|
|
335
351
|
return;
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* 门序 = operator 面口径:身份 → 能力(事实 `configCatalog`,501)→ 授权 → 应答;billable=false,
|
|
10
10
|
* 刻意不吃 drain / roster-pending 两道 503(排障读面在停机窗里恰恰要打得通)。
|
|
11
11
|
*
|
|
12
|
-
* 🔴 鉴权 = `explicitOperatorOk`(
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* 🔴 鉴权 = `explicitOperatorOk`(「谁是 operator」的唯一读法:空名单 = 谁都不是)—— 设计稿 §0.5 点名禁「空名单 = 人人都是」的 fail-open 读法
|
|
13
|
+
* (S-1050 起整只删):本面是部署事实外泄口(env 在场性 / 后端形态 / 限额值)。单用户形只在部署方显式声明 `OPERATOR_SINGLE_USER=true`
|
|
14
|
+
* (每个调用方都是运维)时对调用方开。
|
|
15
15
|
*
|
|
16
16
|
* 🔴 旋钮 `CONFIG_CATALOG_ENABLED=false` / operator 名单空 ⇒ 501(事实 `configCatalog`,与能力位同一只函数):
|
|
17
17
|
* 旋钮关 = `feature.config_catalog_disabled`(合规部署不想让部署事实上 wire 的表态;「去开旋钮」由码与句承担),
|
|
@@ -29,7 +29,7 @@ export async function handleConfigCatalog(req, res, match, ctx) {
|
|
|
29
29
|
return assertNever(fact.why);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
if (!explicitOperatorOk(principal, deps.config
|
|
32
|
+
if (!explicitOperatorOk(principal, deps.config)) {
|
|
33
33
|
sendError(res, 403, "auth.operator_only", OPERATOR_ONLY_MESSAGE);
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
@@ -47,14 +47,7 @@ function bodyKeyIssue(body, accepted) {
|
|
|
47
47
|
return `unknown key(s) in body: ${extra.join(", ")} — this endpoint accepts ${accepted.length === 0 ? "no body keys" : accepted.slice().sort().join(", ")} (a silently dropped key is a declaration that never existed)`;
|
|
48
48
|
}
|
|
49
49
|
async function readClosedBody(req, res, readJson, accepted) {
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
body = await readJson(req);
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
50
|
+
const body = await readJson(req);
|
|
58
51
|
if (typeof body !== "object" || body === null || Array.isArray(body)) {
|
|
59
52
|
sendError(res, 400, "request.body_shape", "body must be a JSON object");
|
|
60
53
|
return null;
|
|
@@ -151,7 +144,7 @@ export async function handleDevices(req, res, match, ctx) {
|
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
146
|
const { store, hub, enrollment, runStore } = lane;
|
|
154
|
-
const operator = explicitOperatorOk(principal, deps.config
|
|
147
|
+
const operator = explicitOperatorOk(principal, deps.config);
|
|
155
148
|
const domain = deviceOwnerDomainOf(req, deps.config);
|
|
156
149
|
if (match.decl.id === "devices-list") {
|
|
157
150
|
if (!operator && domain === undefined) {
|
|
@@ -277,14 +270,7 @@ export async function handleDevices(req, res, match, ctx) {
|
|
|
277
270
|
sendDeviceNotFound(res);
|
|
278
271
|
return;
|
|
279
272
|
}
|
|
280
|
-
|
|
281
|
-
try {
|
|
282
|
-
body = (await readJson(req));
|
|
283
|
-
}
|
|
284
|
-
catch {
|
|
285
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
273
|
+
const body = (await readJson(req));
|
|
288
274
|
if (typeof body !== "object" || body === null || typeof body.toDeviceId !== "string" || body.expectedRev === undefined) {
|
|
289
275
|
sendError(res, 400, "request.body_shape", "body must be { toDeviceId: string, expectedRev: number } — expectedRev is the binding rev read from GET /v1/devices/sessions/{rootSessionId} (explicit prior state; two concurrent operators must not silently stomp each other)");
|
|
290
276
|
return;
|
|
@@ -43,8 +43,8 @@ export interface ServerWiringGateInput {
|
|
|
43
43
|
streamApprovalEnabled: boolean;
|
|
44
44
|
/** 谓词自己的入参类型(结构形,不 import store 依赖树)—— 取型而非重述,两处不可能漂。 */
|
|
45
45
|
backend: StreamApprovalGateInput["backend"];
|
|
46
|
-
/**
|
|
47
|
-
checkpointStore:
|
|
46
|
+
/** 谓词自己的入参类型(只收店的形,工厂方法过不了 tsc)—— 取型而非重述,与 `backend` 同理;在场性即事实,本面不读实例的内容。 */
|
|
47
|
+
checkpointStore: StreamApprovalGateInput["checkpointStore"];
|
|
48
48
|
durableApproval: boolean;
|
|
49
49
|
/** S-178:三个 posture 旋钮的**来源**,取自 config 上与值同处写的那一格(不在这里重判)。 */
|
|
50
50
|
durableApprovalSource: PostureSource;
|
|
@@ -68,7 +68,7 @@ export interface StaticWiringAudit {
|
|
|
68
68
|
export interface StaticWiringFacts {
|
|
69
69
|
/** core `describeStaticWiring(deps, specTemplate)` 的产物。 */
|
|
70
70
|
manifest: WiringManifest;
|
|
71
|
-
/** 我方喂给 `resolveStreamApprovalGate` 的 `
|
|
71
|
+
/** 我方喂给 `resolveStreamApprovalGate` 的 `checkpointStore` 实参的在场性(= checkpoint 店在场 ∧ DURABLE_APPROVAL)。 */
|
|
72
72
|
parkFacility: boolean;
|
|
73
73
|
/** store backend 的种类;`undefined` = env-only worker(无 backend)。 */
|
|
74
74
|
backendKind: "mysql" | "pg" | "local" | undefined;
|
|
@@ -12,27 +12,31 @@ export function buildServerWiringGates(input) {
|
|
|
12
12
|
toolApprovalEnabled: input.toolApprovalEnabled,
|
|
13
13
|
streamApprovalEnabled: input.streamApprovalEnabled,
|
|
14
14
|
backend: input.backend,
|
|
15
|
-
|
|
15
|
+
checkpointStore: input.checkpointStore,
|
|
16
16
|
});
|
|
17
17
|
const noCenterArm = (knob) => `this knob has no web-admin arm on this deployment — it is set by ${knob} on this machine, or derived from the deployment posture`;
|
|
18
|
+
const noLaneArm = (knob) => `this knob has no execution-lane default — ${knob} does not depend on which execution lane this deployment runs`;
|
|
18
19
|
return {
|
|
19
20
|
streamApproval: gate.active ? "active" : gate.reason,
|
|
20
21
|
durableApproval: buildPostureKnobReading(input.durableApproval, {
|
|
21
22
|
knob: "DURABLE_APPROVAL",
|
|
22
23
|
source: input.durableApprovalSource,
|
|
23
24
|
centerMeaning: noCenterArm("DURABLE_APPROVAL"),
|
|
25
|
+
laneMeaning: noLaneArm("DURABLE_APPROVAL"),
|
|
24
26
|
postureMeaning: "derived from the single-user turnkey posture (REQUIRE_PRINCIPAL is not set) composed with a durable store being present: park/resume and the /v1/approvals routes are on by default — set DURABLE_APPROVAL=false to pin them off",
|
|
25
27
|
}),
|
|
26
28
|
streamAskWindowMs: buildPostureKnobReading(input.streamAskWindowMs, {
|
|
27
29
|
knob: "STREAM_ASK_WINDOW_MS",
|
|
28
30
|
source: input.streamAskWindowMsSource,
|
|
29
31
|
centerMeaning: noCenterArm("STREAM_ASK_WINDOW_MS"),
|
|
32
|
+
laneMeaning: noLaneArm("STREAM_ASK_WINDOW_MS"),
|
|
30
33
|
postureMeaning: "derived from the single-user turnkey posture (REQUIRE_PRINCIPAL is not set): an approval card waits 24h instead of 5 minutes, so stepping away does not settle the run unattended — set STREAM_ASK_WINDOW_MS to pin your own window",
|
|
31
34
|
}),
|
|
32
35
|
sessionAutoTitle: buildPostureKnobReading(input.sessionAutoTitle, {
|
|
33
36
|
knob: "SESSION_AUTO_TITLE",
|
|
34
37
|
source: input.sessionAutoTitleSource,
|
|
35
38
|
centerMeaning: noCenterArm("SESSION_AUTO_TITLE"),
|
|
39
|
+
laneMeaning: noLaneArm("SESSION_AUTO_TITLE"),
|
|
36
40
|
postureMeaning: "this knob has no posture arm — its default is the same on every deployment shape",
|
|
37
41
|
}),
|
|
38
42
|
checkpointStore: input.checkpointStore !== undefined,
|
|
@@ -93,7 +97,7 @@ export async function handleDiagnostics(req, res, match, ctx) {
|
|
|
93
97
|
return;
|
|
94
98
|
}
|
|
95
99
|
const principal = gatedPrincipal(req, deps.config);
|
|
96
|
-
if (!explicitOperatorOk(principal, deps.config
|
|
100
|
+
if (!explicitOperatorOk(principal, deps.config)) {
|
|
97
101
|
sendError(res, 403, "auth.operator_only", "wiring diagnostics are operator-only on a multi-tenant worker");
|
|
98
102
|
return;
|
|
99
103
|
}
|