@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
package/dist/http/routes/runs.js
CHANGED
|
@@ -5,7 +5,7 @@ import { uuidv7, mintCheckpointToken, CheckpointError, policyCannotAnswer, valid
|
|
|
5
5
|
import { isTerminalRunStatus, isParkedRunStatus, runProvenElsewhere } from "../../plugins/store-contracts.js";
|
|
6
6
|
import { LIVE_RUN_GATE_KINDS, TERMINAL_PARK_GATE_KINDS } from "../../plugins/checkpoint-store-sql.js";
|
|
7
7
|
import { redactSecrets } from "../../trace/redact.js";
|
|
8
|
-
import {
|
|
8
|
+
import { isUuidV7, encodeCheckpointScope } from "../../security.js";
|
|
9
9
|
import { redactSteerIn, STEER_IN_MAX_CHARS, STEER_IN_MAX_REQUEST_CHARS } from "../../orchestration/workflow-agent-steer.js";
|
|
10
10
|
import { defaultSubagentTailBus } from "../../fleet/subagent-tail-bus.js";
|
|
11
11
|
import { idemCallerOf, idemKeyOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
|
|
@@ -13,11 +13,12 @@ import { streamSseLog } from "../sse-log.js";
|
|
|
13
13
|
import { bindSseLifecycle } from "../sse-lifecycle.js";
|
|
14
14
|
import { buildApprovalPreamble, buildApprovalPreambleSseFrames, readClosedWordSeat, storedCardDemandsAPerson } from "../../approval-card.js";
|
|
15
15
|
import { heldAskOf, liveSettledBy, readDecidedBy, retiredDecisionKeyFacts, DECIDED_BY_NOT_IN_PROOF, DECIDED_BY_OUTSIDE_CLOSED_SET, POLICY_CANNOT_ALLOW_PERSON_ASK } from "../../host-decision.js";
|
|
16
|
-
import { ASK_DECISION_CONSUMER_ABSENT, outcomeOfDecidedRow, resolveStreamApprovalGate } from "../../tool-approval.js";
|
|
17
|
-
import {
|
|
16
|
+
import { ASK_DECISION_CONSUMER_ABSENT, approvalPreambleReplays, outcomeOfDecidedRow, resolveStreamApprovalGate } from "../../tool-approval.js";
|
|
17
|
+
import { readRunDeclaredFamilies } from "../run-declared-families.js";
|
|
18
|
+
import { MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt } from "../../approval-ask-machine.js";
|
|
18
19
|
import { causeOfAskRow } from "../../approval-deny-reasons.js";
|
|
19
20
|
import { normalizeRunEventType, screenedStoredEventData } from "../../trace/project.js";
|
|
20
|
-
import { sendJson, sendError, sendHttpError, sseHeaders } from "../send.js";
|
|
21
|
+
import { invalidJsonError, sendJson, sendError, sendHttpError, sseHeaders } from "../send.js";
|
|
21
22
|
import { mintCancelledResult } from "../../run-cancel-context.js";
|
|
22
23
|
import { acceptedInputKindOf } from "../../user-input-ledger.js";
|
|
23
24
|
import { INJECTION_TIERS } from "../../trace/injection-tier.js";
|
|
@@ -35,6 +36,7 @@ import { storedBodyReplayAnswer, storedBodyReplayLogFields } from "../checkpoint
|
|
|
35
36
|
import { serviceVersion } from "../../service-version.js";
|
|
36
37
|
import { storedBodyReplayRefusal } from "../stored-body-replay.js";
|
|
37
38
|
import { steerBodyKeyIssue } from "../../request-key-closure.js";
|
|
39
|
+
import { fieldConflictFacts } from "../../field-conflict.js";
|
|
38
40
|
const STEER_PRIORITY_WORDS = INJECTION_TIERS.map((tier) => `'${tier}'`);
|
|
39
41
|
const STEER_PRIORITY_UNION = STEER_PRIORITY_WORDS.join(" | ");
|
|
40
42
|
const STEER_PRIORITY_CHOICES = STEER_PRIORITY_WORDS.length <= 2 ? STEER_PRIORITY_WORDS.join(" or ") : `${STEER_PRIORITY_WORDS.slice(0, -1).join(", ")}, or ${STEER_PRIORITY_WORDS[STEER_PRIORITY_WORDS.length - 1]}`;
|
|
@@ -81,7 +83,7 @@ async function subagentReadGate(req, res, ctx, runId, search) {
|
|
|
81
83
|
sendPrincipalRefusal(res, req, deps.config);
|
|
82
84
|
return null;
|
|
83
85
|
}
|
|
84
|
-
const trusted = explicitOperatorOk(principal, deps.config
|
|
86
|
+
const trusted = explicitOperatorOk(principal, deps.config);
|
|
85
87
|
const run = await deps.runStore.getRun(runId);
|
|
86
88
|
if (!run) {
|
|
87
89
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
@@ -108,17 +110,26 @@ function sendHandleMiss(res, run, thisInstanceId) {
|
|
|
108
110
|
}
|
|
109
111
|
return false;
|
|
110
112
|
}
|
|
111
|
-
async function streamRunEvents(req, res, deps, runStore, taskId, staleMs) {
|
|
113
|
+
async function streamRunEvents(req, res, deps, runStore, taskId, sessionId, staleMs) {
|
|
112
114
|
await streamSseLog(req, res, {
|
|
113
115
|
preamble: async (signal) => {
|
|
114
116
|
const gate = resolveStreamApprovalGate({
|
|
115
117
|
toolApprovalEnabled: Boolean(deps.toolApproval),
|
|
116
118
|
streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
|
|
117
119
|
backend: deps.backend,
|
|
118
|
-
|
|
120
|
+
checkpointStore: deps.checkpointStore,
|
|
119
121
|
});
|
|
120
122
|
if (!gate.active)
|
|
121
123
|
return [];
|
|
124
|
+
const declaredFamilies = await readRunDeclaredFamilies(gate.checkpointStore, sessionId, (where) => deps.logger?.warn?.("approval_preamble_declaration_unreadable", { taskId, where, face: "run.events" }));
|
|
125
|
+
if (!approvalPreambleReplays({
|
|
126
|
+
streamApprovalOn: gate.active,
|
|
127
|
+
windowMs: deps.config.streamApproval?.windowMs,
|
|
128
|
+
windowMarginMs: deps.config.streamAskWindowMarginMs,
|
|
129
|
+
declaredFamilies,
|
|
130
|
+
})) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
122
133
|
const store = gate.askStore;
|
|
123
134
|
const rows = await store.listPendingByTask(taskId, signal);
|
|
124
135
|
const { frames, skipped, dropped } = buildApprovalPreamble(rows, Date.now(), deps.config.streamApproval.replayMax);
|
|
@@ -254,7 +265,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
254
265
|
if (!runSessionAcceptOk(req, res, run, match.decl.id === "run-events" ? "run.events" : "run.poll"))
|
|
255
266
|
return;
|
|
256
267
|
if (match.decl.id === "run-events") {
|
|
257
|
-
await streamRunEvents(req, res, deps, runStore, taskId, deps.config.runStaleSec * 1000);
|
|
268
|
+
await streamRunEvents(req, res, deps, runStore, taskId, run.sessionId, deps.config.runStaleSec * 1000);
|
|
258
269
|
}
|
|
259
270
|
else {
|
|
260
271
|
sendJson(res, 200, await readRunFace(deps, runStore, run));
|
|
@@ -399,18 +410,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
399
410
|
return;
|
|
400
411
|
}
|
|
401
412
|
const taskId = match.params.taskId;
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
body = ((await readJson(req)) ?? {});
|
|
405
|
-
}
|
|
406
|
-
catch (e) {
|
|
407
|
-
if (e instanceof HttpError) {
|
|
408
|
-
sendHttpError(res, e);
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
413
|
+
const body = ((await readJson(req)) ?? {});
|
|
414
414
|
if (typeof body.text !== "string" || body.text.length === 0) {
|
|
415
415
|
sendError(res, 400, "request.body_shape", `body must be { text: string (non-empty), mode?: 'all' | 'one-at-a-time', priority?: ${STEER_PRIORITY_UNION} }`);
|
|
416
416
|
return;
|
|
@@ -435,7 +435,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
435
435
|
const steerIdemRaw = headerStr(req.headers["idempotency-key"]);
|
|
436
436
|
const steerInputId = steerIdemRaw ? `idem-${idemKeyOf(steerIdemRaw, idemCallerOf(req, ctx), "run").slice(0, 32)}` : undefined;
|
|
437
437
|
const messageId = steerInputId ?? uuidv7();
|
|
438
|
-
const trusted = explicitOperatorOk(principal, deps.config
|
|
438
|
+
const trusted = explicitOperatorOk(principal, deps.config);
|
|
439
439
|
const steerInput = () => ({
|
|
440
440
|
text,
|
|
441
441
|
trusted,
|
|
@@ -623,11 +623,15 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
623
623
|
const leafId = await Promise.resolve(deps.sessionStorage.getLeafId(run.sessionId)).catch(() => undefined);
|
|
624
624
|
if (leafId === undefined || leafId === null)
|
|
625
625
|
return;
|
|
626
|
-
const resumeRead = await readResumeCtx(cs.getCtx(run.sessionId));
|
|
626
|
+
const resumeRead = await readResumeCtx(cs.getCtx(run.sessionId), { sessionId: run.sessionId, opener: deps.checkpointCtxSealing });
|
|
627
627
|
if (resumeRead.kind === "corrupt") {
|
|
628
628
|
mintResult.corruptCtxWhere = resumeRead.where;
|
|
629
629
|
return;
|
|
630
630
|
}
|
|
631
|
+
if (resumeRead.kind === "unsealable") {
|
|
632
|
+
mintResult.unsealableCtx = resumeRead;
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
631
635
|
if (resumeRead.kind === "absent") {
|
|
632
636
|
mintResult.noResumeCtx = true;
|
|
633
637
|
return;
|
|
@@ -651,10 +655,13 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
651
655
|
createdAt: Date.now(),
|
|
652
656
|
sourceTaskId: taskId,
|
|
653
657
|
});
|
|
654
|
-
const stillRead = await readResumeCtx(cs.getCtx(run.sessionId));
|
|
655
|
-
if (stillRead.kind === "corrupt") {
|
|
656
|
-
await withdrawWakeCard(wakeToken, cpScope, "resume_context_corrupt");
|
|
657
|
-
|
|
658
|
+
const stillRead = await readResumeCtx(cs.getCtx(run.sessionId), { sessionId: run.sessionId, opener: deps.checkpointCtxSealing });
|
|
659
|
+
if (stillRead.kind === "corrupt" || stillRead.kind === "unsealable") {
|
|
660
|
+
await withdrawWakeCard(wakeToken, cpScope, stillRead.kind === "corrupt" ? "resume_context_corrupt" : "resume_context_unsealable");
|
|
661
|
+
if (stillRead.kind === "corrupt")
|
|
662
|
+
mintResult.corruptCtxWhere = stillRead.where;
|
|
663
|
+
else
|
|
664
|
+
mintResult.unsealableCtx = stillRead;
|
|
658
665
|
return;
|
|
659
666
|
}
|
|
660
667
|
if (stillRead.kind !== "ok") {
|
|
@@ -691,6 +698,10 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
691
698
|
sendError(res, 500, "corrupt", "run already ended and this session's stored resume context cannot be read — nothing was queued. Ask whoever operates this deployment to repair or remove the row named in `where` before steering this session again.", { where: mintResult.corruptCtxWhere });
|
|
692
699
|
return;
|
|
693
700
|
}
|
|
701
|
+
if (mintResult.unsealableCtx !== undefined) {
|
|
702
|
+
sendError(res, 409, "conflict.checkpoint_ctx_unsealable", "run already ended and this session's stored resume context holds credentials this server cannot unseal (reason says why) — nothing was queued, because POST /v1/sessions/:id/wake could not resume it; restore the sealed-key directory that sealed them, restart this server (it reads its keys only at startup) and steer again, or submit a new task instead", { field: mintResult.unsealableCtx.field, reason: mintResult.unsealableCtx.reason });
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
694
705
|
if (mintResult.unservable !== undefined) {
|
|
695
706
|
deps.logger?.warn?.("steer_wake_park_refused_stored_body", { taskId, sessionId: run.sessionId, ...storedBodyReplayLogFields(mintResult.unservable) });
|
|
696
707
|
const { status, body: { error, errorCode, ...rest } } = storedBodyReplayAnswer(mintResult.unservable, serviceVersion(), false);
|
|
@@ -724,18 +735,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
724
735
|
return;
|
|
725
736
|
}
|
|
726
737
|
const taskId = match.params.taskId;
|
|
727
|
-
|
|
728
|
-
try {
|
|
729
|
-
interruptRaw = await readJson(req);
|
|
730
|
-
}
|
|
731
|
-
catch (e) {
|
|
732
|
-
if (e instanceof HttpError) {
|
|
733
|
-
sendHttpError(res, e);
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
737
|
-
return;
|
|
738
|
-
}
|
|
738
|
+
const interruptRaw = await readJson(req);
|
|
739
739
|
const interruptNormalized = interruptRaw === null || interruptRaw === undefined ? {} : interruptRaw;
|
|
740
740
|
if (typeof interruptNormalized !== "object" || Array.isArray(interruptNormalized)) {
|
|
741
741
|
sendError(res, 400, "request.body_shape", "body must be {} (bare halt: cut the in-flight turn and stop the run at this boundary) or { text: string (non-empty) } (cut + steer: the text reaches the model after the cut)");
|
|
@@ -759,7 +759,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
759
759
|
const interruptIdemRaw = headerStr(req.headers["idempotency-key"]);
|
|
760
760
|
const interruptInputId = interruptIdemRaw ? `idem-${idemKeyOf(interruptIdemRaw, idemCallerOf(req, ctx), "run").slice(0, 32)}` : uuidv7();
|
|
761
761
|
const interruptMessageId = interruptInputId;
|
|
762
|
-
const trusted = explicitOperatorOk(principal, deps.config
|
|
762
|
+
const trusted = explicitOperatorOk(principal, deps.config);
|
|
763
763
|
if (!interruptBare) {
|
|
764
764
|
try {
|
|
765
765
|
validatePendingSteer({ text, trusted, inputId: interruptInputId });
|
|
@@ -877,28 +877,17 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
877
877
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
878
878
|
return;
|
|
879
879
|
}
|
|
880
|
-
const operator = explicitOperatorOk(principal, deps.config
|
|
880
|
+
const operator = explicitOperatorOk(principal, deps.config);
|
|
881
881
|
if (!operator && !runOwnerOk(req, res, run.owner))
|
|
882
882
|
return;
|
|
883
883
|
if (!runSessionAcceptOk(req, res, run, "run.compact"))
|
|
884
884
|
return;
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (parsed === null || typeof parsed !== "object") {
|
|
889
|
-
sendError(res, 400, "request.invalid_json", "body must be a JSON object when present");
|
|
890
|
-
return;
|
|
891
|
-
}
|
|
892
|
-
compactBody = parsed;
|
|
893
|
-
}
|
|
894
|
-
catch (e) {
|
|
895
|
-
if (e instanceof HttpError) {
|
|
896
|
-
sendHttpError(res, e);
|
|
897
|
-
return;
|
|
898
|
-
}
|
|
899
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
885
|
+
const parsed = await readJson(req);
|
|
886
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
887
|
+
sendHttpError(res, invalidJsonError("not_object"));
|
|
900
888
|
return;
|
|
901
889
|
}
|
|
890
|
+
const compactBody = parsed;
|
|
902
891
|
if (compactBody.instructions !== undefined && (typeof compactBody.instructions !== "string" || compactBody.instructions.length === 0 || [...compactBody.instructions].length > 2_048)) {
|
|
903
892
|
sendError(res, 400, "request.field_invalid", "instructions must be a non-empty string of at most 2048 characters (code points) when present — the engine caps compaction instructions there");
|
|
904
893
|
return;
|
|
@@ -938,18 +927,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
938
927
|
return;
|
|
939
928
|
}
|
|
940
929
|
const taskId = match.params.taskId;
|
|
941
|
-
|
|
942
|
-
try {
|
|
943
|
-
body = ((await readJson(req)) ?? {});
|
|
944
|
-
}
|
|
945
|
-
catch (e) {
|
|
946
|
-
if (e instanceof HttpError) {
|
|
947
|
-
sendHttpError(res, e);
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
930
|
+
const body = ((await readJson(req)) ?? {});
|
|
953
931
|
if (typeof body.toolCallId !== "string" || body.toolCallId.length === 0 || body.toolCallId.length > 256) {
|
|
954
932
|
sendError(res, 400, "request.body_shape", "body must be { toolCallId: string (non-empty, ≤256 chars) }");
|
|
955
933
|
return;
|
|
@@ -959,7 +937,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
959
937
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
960
938
|
return;
|
|
961
939
|
}
|
|
962
|
-
const operator = explicitOperatorOk(principal, deps.config
|
|
940
|
+
const operator = explicitOperatorOk(principal, deps.config);
|
|
963
941
|
if (!operator && !runOwnerOk(req, res, run.owner))
|
|
964
942
|
return;
|
|
965
943
|
if (!runSessionAcceptOk(req, res, run, "run.detach"))
|
|
@@ -1164,18 +1142,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1164
1142
|
sendError(res, 400, "request.path_malformed", "malformed subagent path (invalid percent-encoding)");
|
|
1165
1143
|
return;
|
|
1166
1144
|
}
|
|
1167
|
-
|
|
1168
|
-
try {
|
|
1169
|
-
body = ((await readJson(req)) ?? {});
|
|
1170
|
-
}
|
|
1171
|
-
catch (e) {
|
|
1172
|
-
if (e instanceof HttpError) {
|
|
1173
|
-
sendHttpError(res, e);
|
|
1174
|
-
return;
|
|
1175
|
-
}
|
|
1176
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
1177
|
-
return;
|
|
1178
|
-
}
|
|
1145
|
+
const body = ((await readJson(req)) ?? {});
|
|
1179
1146
|
if (typeof body.content !== "string" || body.content.length === 0) {
|
|
1180
1147
|
sendError(res, 400, "request.body_shape", "body must be { content: string (non-empty) }");
|
|
1181
1148
|
return;
|
|
@@ -1191,7 +1158,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1191
1158
|
sendError(res, 413, "steer.content_too_large", `content exceeds ${STEER_IN_MAX_REQUEST_CHARS} characters (got ${body.content.length}); note only the first ${STEER_IN_MAX_CHARS} are delivered anyway`);
|
|
1192
1159
|
return;
|
|
1193
1160
|
}
|
|
1194
|
-
const trusted = explicitOperatorOk(principal, deps.config
|
|
1161
|
+
const trusted = explicitOperatorOk(principal, deps.config);
|
|
1195
1162
|
const run = await runStore.getRun(runId);
|
|
1196
1163
|
if (!run) {
|
|
1197
1164
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
@@ -1274,14 +1241,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1274
1241
|
return;
|
|
1275
1242
|
}
|
|
1276
1243
|
const id = match.params.id;
|
|
1277
|
-
|
|
1278
|
-
try {
|
|
1279
|
-
body = await readJson(req);
|
|
1280
|
-
}
|
|
1281
|
-
catch {
|
|
1282
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
1283
|
-
return;
|
|
1284
|
-
}
|
|
1244
|
+
const body = await readJson(req);
|
|
1285
1245
|
const { status, body: respBody } = elicitFact.coordinator.respond(id, principal, body);
|
|
1286
1246
|
sendJson(res, status, respBody);
|
|
1287
1247
|
return;
|
|
@@ -1300,19 +1260,12 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1300
1260
|
return;
|
|
1301
1261
|
}
|
|
1302
1262
|
const id = match.params.id;
|
|
1303
|
-
|
|
1304
|
-
try {
|
|
1305
|
-
body = await readJson(req);
|
|
1306
|
-
}
|
|
1307
|
-
catch {
|
|
1308
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
1309
|
-
return;
|
|
1310
|
-
}
|
|
1263
|
+
const body = await readJson(req);
|
|
1311
1264
|
const { status, body: respBody } = questionFact.coordinator.respond(id, principal, body);
|
|
1312
1265
|
sendJson(res, status, respBody);
|
|
1313
1266
|
return;
|
|
1314
1267
|
}
|
|
1315
|
-
if (match.decl.id === "tool-approval-respond") {
|
|
1268
|
+
if (match.decl.id === "tool-approval-respond" || match.decl.id === "tool-approval-read") {
|
|
1316
1269
|
if (rateLimited(req, res))
|
|
1317
1270
|
return;
|
|
1318
1271
|
const approvalFact = facts.toolApproval(deps);
|
|
@@ -1326,15 +1279,13 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1326
1279
|
return;
|
|
1327
1280
|
}
|
|
1328
1281
|
const id = match.params.id;
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
}
|
|
1333
|
-
catch {
|
|
1334
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
1282
|
+
if (match.decl.id === "tool-approval-read") {
|
|
1283
|
+
const { status, body: respBody } = await approvalFact.coordinator.readApproval(id, principal);
|
|
1284
|
+
sendJson(res, status, respBody);
|
|
1335
1285
|
return;
|
|
1336
1286
|
}
|
|
1337
|
-
const
|
|
1287
|
+
const body = await readJson(req);
|
|
1288
|
+
const { status, body: respBody } = await approvalFact.coordinator.respond(id, principal, body, req, { readRootGrantAccepted: facts.readRootGrant(deps).available });
|
|
1338
1289
|
const retryAfterSec = respBody.retryAfterSec;
|
|
1339
1290
|
if (typeof retryAfterSec === "number" && Number.isFinite(retryAfterSec) && retryAfterSec >= 0) {
|
|
1340
1291
|
res.setHeader("retry-after", String(Math.ceil(retryAfterSec)));
|
|
@@ -1356,14 +1307,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1356
1307
|
sendPrincipalRefusal(res, req, deps.config);
|
|
1357
1308
|
return;
|
|
1358
1309
|
}
|
|
1359
|
-
|
|
1360
|
-
try {
|
|
1361
|
-
rawBody = await readJson(req);
|
|
1362
|
-
}
|
|
1363
|
-
catch {
|
|
1364
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
1365
|
-
return;
|
|
1366
|
-
}
|
|
1310
|
+
const rawBody = await readJson(req);
|
|
1367
1311
|
const parsedBody = AskDecisionBodySchema.safeParse(rawBody);
|
|
1368
1312
|
if (!parsedBody.success) {
|
|
1369
1313
|
const retired = retiredDecisionKeyFacts(rawBody);
|
|
@@ -1401,7 +1345,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1401
1345
|
return;
|
|
1402
1346
|
}
|
|
1403
1347
|
const ownerOk = row0.owner === null || (principal !== undefined && row0.owner === principal);
|
|
1404
|
-
const operatorOk = explicitOperatorOk(principal, deps.config
|
|
1348
|
+
const operatorOk = explicitOperatorOk(principal, deps.config);
|
|
1405
1349
|
if (!ownerOk && !operatorOk) {
|
|
1406
1350
|
askNotFound();
|
|
1407
1351
|
return;
|
|
@@ -1440,6 +1384,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1440
1384
|
return true;
|
|
1441
1385
|
};
|
|
1442
1386
|
const decisionNoteEcho = (row) => (row.decisionNote === null ? {} : { decisionNote: row.decisionNote });
|
|
1387
|
+
const noteReceipt = (row) => noteRecordedReceipt(body.note, noteLandedOnRow(body.note, row.decisionNote));
|
|
1443
1388
|
const replayDecided = (row) => {
|
|
1444
1389
|
const storedActor = projectDecisionActor(row.decisionActor);
|
|
1445
1390
|
sendJson(res, 200, {
|
|
@@ -1449,6 +1394,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1449
1394
|
decidedAtMs: row.decidedAtMs,
|
|
1450
1395
|
...(storedActor ? { actor: storedActor } : {}),
|
|
1451
1396
|
...decisionNoteEcho(row),
|
|
1397
|
+
...noteReceipt(row),
|
|
1452
1398
|
});
|
|
1453
1399
|
};
|
|
1454
1400
|
const sendTerminal = (row) => {
|
|
@@ -1519,7 +1465,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1519
1465
|
return;
|
|
1520
1466
|
}
|
|
1521
1467
|
if (body.decision === "approve" && policyCannotAnswer(heldAskOf(storedCardDemandsAPerson(row0.cardJson)), decidedBy)) {
|
|
1522
|
-
sendError(res, 400, "request.field_conflict", POLICY_CANNOT_ALLOW_PERSON_ASK);
|
|
1468
|
+
sendError(res, 400, "request.field_conflict", POLICY_CANNOT_ALLOW_PERSON_ASK, fieldConflictFacts("policy_person_ask", ["decidedBy", "decision"]));
|
|
1523
1469
|
return;
|
|
1524
1470
|
}
|
|
1525
1471
|
let outcome;
|
|
@@ -1606,6 +1552,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
|
|
|
1606
1552
|
...(forwarded ? { updatedInputForwarded: true } : {}),
|
|
1607
1553
|
...(settled === 0 ? { consumerState: ASK_DECISION_CONSUMER_ABSENT } : {}),
|
|
1608
1554
|
...decisionNoteEcho(outcome.row),
|
|
1555
|
+
...noteReceipt(outcome.row),
|
|
1609
1556
|
});
|
|
1610
1557
|
return;
|
|
1611
1558
|
}
|
|
@@ -1675,6 +1622,7 @@ export const RUN_VERBS_ROUTES = [
|
|
|
1675
1622
|
{ id: "elicitation-respond", pattern: /^\/v1\/elicitations\/(?<id>[^/]+)\/respond$/, label: "/v1/elicitations/:id/respond", methods: ["POST"] },
|
|
1676
1623
|
{ id: "question-respond", pattern: /^\/v1\/questions\/(?<id>[^/]+)\/respond$/, label: "/v1/questions/:id/respond", methods: ["POST"] },
|
|
1677
1624
|
{ id: "tool-approval-respond", pattern: /^\/v1\/tool-approvals\/(?<id>[^/]+)\/respond$/, label: "/v1/tool-approvals/:id/respond", methods: ["POST"] },
|
|
1625
|
+
{ id: "tool-approval-read", pattern: /^\/v1\/tool-approvals\/(?<id>[^/]+)$/, label: "/v1/tool-approvals/:id", methods: ["GET"] },
|
|
1678
1626
|
{ id: "task-ask-decision", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/asks\/(?<askId>[^/]+)\/decision$/, label: "/v1/tasks/:id/asks/:askId/decision", methods: ["POST"] },
|
|
1679
1627
|
];
|
|
1680
1628
|
//# sourceMappingURL=runs.js.map
|
|
@@ -34,8 +34,9 @@ export type PendingStaging = {
|
|
|
34
34
|
declaredEntryIds: string[];
|
|
35
35
|
/** The principal that opened this staging — a different caller may not drive it (404, no oracle). */
|
|
36
36
|
openedBy: string | null;
|
|
37
|
-
/**
|
|
38
|
-
|
|
37
|
+
/** The owner cell the gate judged when it opened this staging (`ownerOf` reading: `undefined` = no such session) — the commit lands only on
|
|
38
|
+
* this same cell (`StagedCommitOptions.expectedOwner`, `session-sync-kernel.ts`); `owner` above (the re-stamped importing principal) is derived from it for a fleet caller. */
|
|
39
|
+
expectedOwner: string | null | undefined;
|
|
39
40
|
};
|
|
40
41
|
/** 单域独占状态 + 它的两个操作。每个 server 实例一份。 */
|
|
41
42
|
export interface SessionSyncLocal {
|
|
@@ -5,11 +5,10 @@ import { StringDecoder } from "node:string_decoder";
|
|
|
5
5
|
import { exportSessionManifest, fileHistoryImportFace, replayFileHistory, replayPolicyRecords, wipeSessionAttendants } from "../../session-sync.js";
|
|
6
6
|
import * as facts from "../../capability-facts.js";
|
|
7
7
|
import { classifySyncRelationshipByIds, SyncConflictError } from "../../session-sync-kernel.js";
|
|
8
|
-
import { isUuidShape } from "../../security.js";
|
|
9
|
-
import {
|
|
10
|
-
import { sendJson, sendError, sendSessionError, sendSessionPolicyError, msg } from "../send.js";
|
|
8
|
+
import { isUuidShape, legacyUnownedSessionOk, sessionOwnerCellOf } from "../../security.js";
|
|
9
|
+
import { sendJson, sendError, sendSessionError, sendSessionPolicyError, logRequestError, msg } from "../send.js";
|
|
11
10
|
import { buildDisplaySafeUrl } from "../../trace/redact.js";
|
|
12
|
-
import { gatedPrincipal, explicitOperatorOk, sendUnauthorized } from "../principal-gate.js";
|
|
11
|
+
import { fleetViewOf, gatedPrincipal, explicitOperatorOk, sendUnauthorized, sessionCallerOf } from "../principal-gate.js";
|
|
13
12
|
const SYNC_BLOB_MAX_BYTES = 64 * 1024 * 1024;
|
|
14
13
|
const SYNC_NDJSON_LINE_MAX_BYTES = 8 * 1024 * 1024;
|
|
15
14
|
const SYNC_IMPORT_BATCH = 500;
|
|
@@ -35,7 +34,7 @@ export function createSessionSyncLocal() {
|
|
|
35
34
|
}
|
|
36
35
|
export async function handleSessionSync(req, res, match, ctx) {
|
|
37
36
|
const { deps } = ctx;
|
|
38
|
-
const { readJson, readRawBody, safeDecode,
|
|
37
|
+
const { readJson, readRawBody, safeDecode, rateLimited } = ctx.helpers;
|
|
39
38
|
const { pendingStagings, importLeases, touchImportLease, cleanupStaging } = ctx.local.sessionSync;
|
|
40
39
|
{
|
|
41
40
|
{
|
|
@@ -45,7 +44,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
45
44
|
return;
|
|
46
45
|
}
|
|
47
46
|
const { backend, sessionStorage, historyStore } = sync;
|
|
48
|
-
const scope =
|
|
47
|
+
const scope = fleetViewOf(req, deps, "write");
|
|
49
48
|
if (!scope.fleetWide && scope.gateOwner === null) {
|
|
50
49
|
sendUnauthorized(res, "identity");
|
|
51
50
|
return;
|
|
@@ -55,23 +54,25 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
55
54
|
sendError(res, 400, "request.id_invalid", "invalid session id (must be a canonical uuid)");
|
|
56
55
|
return;
|
|
57
56
|
}
|
|
58
|
-
const
|
|
57
|
+
const judgeSessionGate = async () => {
|
|
58
|
+
const face = await sessionStorage.sessionFaceOf(sessionId);
|
|
59
|
+
const mayTouch = face !== undefined && (scope.fleetWide || face.owner === scope.gateOwner || legacyUnownedSessionOk(deps.config.requirePrincipal, sessionCallerOf(req, deps), await sessionOwnerCellOf(sessionStorage, sessionId, face.owner)));
|
|
60
|
+
return { face, mayPull: mayTouch, mayPush: face === undefined || mayTouch };
|
|
61
|
+
};
|
|
62
|
+
const gate = await judgeSessionGate();
|
|
63
|
+
const gateFace = gate.face;
|
|
59
64
|
const owner = gateFace === undefined ? undefined : gateFace.owner;
|
|
60
|
-
const
|
|
65
|
+
const sendSessionAbsent = () => sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
61
66
|
const pullGateOk = () => {
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
if (!ownsOrFleet(owner)) {
|
|
67
|
-
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
67
|
+
if (!gate.mayPull) {
|
|
68
|
+
sendSessionAbsent();
|
|
68
69
|
return false;
|
|
69
70
|
}
|
|
70
71
|
return true;
|
|
71
72
|
};
|
|
72
73
|
const pushGateOk = () => {
|
|
73
|
-
if (
|
|
74
|
-
|
|
74
|
+
if (!gate.mayPush) {
|
|
75
|
+
sendSessionAbsent();
|
|
75
76
|
return false;
|
|
76
77
|
}
|
|
77
78
|
return true;
|
|
@@ -94,7 +95,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
94
95
|
throw e;
|
|
95
96
|
}
|
|
96
97
|
if (out === null) {
|
|
97
|
-
|
|
98
|
+
sendSessionAbsent();
|
|
98
99
|
return;
|
|
99
100
|
}
|
|
100
101
|
sendJson(res, 200, { manifest: out.manifest });
|
|
@@ -115,7 +116,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
115
116
|
}
|
|
116
117
|
const it = await sessionStorage.exportEntriesStream(sessionId, afterSeq === undefined ? undefined : { afterSeq });
|
|
117
118
|
if (it === null) {
|
|
118
|
-
|
|
119
|
+
sendSessionAbsent();
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
121
122
|
res.writeHead(200, { "content-type": "application/x-ndjson", "transfer-encoding": "chunked" });
|
|
@@ -187,17 +188,16 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
187
188
|
}
|
|
188
189
|
const fs = blobs.historyStore;
|
|
189
190
|
const body = await readRawBody(req, SYNC_BLOB_MAX_BYTES);
|
|
190
|
-
const sqlCap = deps.snapshotBlobSqlCap?.();
|
|
191
|
-
if (sqlCap !== undefined && body.byteLength > sqlCap.capBytes) {
|
|
192
|
-
sendError(res, 413, "blob_too_large_for_sql", sqlBlobCapRefusalText(body.byteLength, sqlCap), { wallSource: sqlCap.source });
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
191
|
if (createHash("sha256").update(body).digest("hex") !== hash) {
|
|
196
192
|
sendError(res, 400, "request.hash_mismatch", "blob hash mismatch");
|
|
197
193
|
return;
|
|
198
194
|
}
|
|
199
195
|
const put = await fs.putBlob(hash, new Uint8Array(body));
|
|
200
196
|
if (!put.ok) {
|
|
197
|
+
if (put.error.code === "blob_too_large_for_sql") {
|
|
198
|
+
sendError(res, 413, "blob_too_large_for_sql", put.error.message, { wallSource: put.error.wallSource });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
201
|
sendError(res, 502, put.error.code, "blob store write failed");
|
|
202
202
|
return;
|
|
203
203
|
}
|
|
@@ -216,14 +216,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
216
216
|
}
|
|
217
217
|
}).catch(() => { });
|
|
218
218
|
}
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
body = (await readJson(req));
|
|
222
|
-
}
|
|
223
|
-
catch {
|
|
224
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
219
|
+
const body = (await readJson(req));
|
|
227
220
|
if (!Array.isArray(body.entryIds) || !body.entryIds.every((x) => typeof x === "string")) {
|
|
228
221
|
sendError(res, 400, "request.field_invalid", "entryIds must be an array of strings");
|
|
229
222
|
return;
|
|
@@ -314,7 +307,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
314
307
|
return;
|
|
315
308
|
}
|
|
316
309
|
}
|
|
317
|
-
const opOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config
|
|
310
|
+
const opOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
|
|
318
311
|
if (deps.sessionPolicyStore) {
|
|
319
312
|
try {
|
|
320
313
|
await replayPolicyRecords(deps.sessionPolicyStore, sessionId, policy, opOk);
|
|
@@ -389,14 +382,14 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
389
382
|
}
|
|
390
383
|
}
|
|
391
384
|
const importingPrincipal = scope.fleetWide ? (owner ?? null) : scope.gateOwner;
|
|
392
|
-
const operatorOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config
|
|
385
|
+
const operatorOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
|
|
393
386
|
const token = randomBytes(8).toString("hex");
|
|
394
387
|
const handle = sessionStorage.beginImportStaging(sessionId, token);
|
|
395
388
|
const stagingId = handle.stagingId;
|
|
396
389
|
importLeases.set(sessionId, { at: Date.now(), stagingId });
|
|
397
390
|
pendingStagings.set(stagingId, {
|
|
398
391
|
handle, realSessionId: sessionId, owner: importingPrincipal, ...(resolution ? { resolution } : {}), operatorOk,
|
|
399
|
-
fileHistory, policy, anchors, row, declaredEntryIds: entryIds, openedBy: scope.gateOwner,
|
|
392
|
+
fileHistory, policy, anchors, row, declaredEntryIds: entryIds, openedBy: scope.gateOwner, expectedOwner: owner,
|
|
400
393
|
});
|
|
401
394
|
sendJson(res, 200, { stagingId, relation: relA.relation });
|
|
402
395
|
return;
|
|
@@ -412,7 +405,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
412
405
|
sendError(res, 404, "not_found.staging", "staging not found");
|
|
413
406
|
return;
|
|
414
407
|
}
|
|
415
|
-
if (!
|
|
408
|
+
if (!scope.fleetWide && pending.openedBy !== scope.gateOwner) {
|
|
416
409
|
sendError(res, 404, "not_found.staging", "staging not found");
|
|
417
410
|
return;
|
|
418
411
|
}
|
|
@@ -494,7 +487,23 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
494
487
|
return;
|
|
495
488
|
throw e;
|
|
496
489
|
}
|
|
497
|
-
|
|
490
|
+
let mayPushAtCommit;
|
|
491
|
+
let activeAtCommit;
|
|
492
|
+
try {
|
|
493
|
+
mayPushAtCommit = (await judgeSessionGate()).mayPush;
|
|
494
|
+
activeAtCommit = mayPushAtCommit ? await deps.runStore?.getActiveTaskId(sessionId) : undefined;
|
|
495
|
+
}
|
|
496
|
+
catch (e) {
|
|
497
|
+
await pending.handle.abort().catch(() => undefined);
|
|
498
|
+
cleanupStaging(stagingId);
|
|
499
|
+
throw e;
|
|
500
|
+
}
|
|
501
|
+
if (!mayPushAtCommit) {
|
|
502
|
+
await pending.handle.abort().catch(() => undefined);
|
|
503
|
+
cleanupStaging(stagingId);
|
|
504
|
+
sendSessionAbsent();
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
498
507
|
if (activeAtCommit) {
|
|
499
508
|
await pending.handle.abort().catch(() => undefined);
|
|
500
509
|
cleanupStaging(stagingId);
|
|
@@ -502,7 +511,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
502
511
|
return;
|
|
503
512
|
}
|
|
504
513
|
try {
|
|
505
|
-
const committed = await pending.handle.commit(pending.owner, pending.resolution ? { resolution: pending.resolution } :
|
|
514
|
+
const committed = await pending.handle.commit(pending.owner, { expectedOwner: pending.expectedOwner, ...(pending.resolution ? { resolution: pending.resolution } : {}) });
|
|
506
515
|
if (pending.resolution === "overwrite-dst" && (committed.relation === "fork" || committed.relation === "stale")) {
|
|
507
516
|
await wipeSessionAttendants({ fileHistoryStore: historyStore, sessionPolicyStore: deps.sessionPolicyStore, resumeAnchorStore: deps.resumeAnchorStore }, sessionId);
|
|
508
517
|
}
|
|
@@ -532,15 +541,18 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
532
541
|
sendJson(res, 200, { relation: committed.relation });
|
|
533
542
|
}
|
|
534
543
|
catch (e) {
|
|
544
|
+
await pending.handle.abort().catch(() => undefined);
|
|
545
|
+
cleanupStaging(stagingId);
|
|
535
546
|
if (e instanceof SyncConflictError) {
|
|
536
|
-
await pending.handle.abort().catch(() => undefined);
|
|
537
|
-
cleanupStaging(stagingId);
|
|
538
547
|
sendError(res, 409, "conflict", "sync conflict", { relation: e.relation });
|
|
539
548
|
return;
|
|
540
549
|
}
|
|
541
|
-
cleanupStaging(stagingId);
|
|
542
550
|
if (sendSessionPolicyError(res, e))
|
|
543
551
|
return;
|
|
552
|
+
if (sendSessionError(res, e, "import")) {
|
|
553
|
+
logRequestError(deps.logger, req, e);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
544
556
|
throw e;
|
|
545
557
|
}
|
|
546
558
|
return;
|
|
@@ -548,14 +560,7 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
548
560
|
if (match.decl.id === "session-sync-plan") {
|
|
549
561
|
if (!pushGateOk())
|
|
550
562
|
return;
|
|
551
|
-
|
|
552
|
-
try {
|
|
553
|
-
body = (await readJson(req));
|
|
554
|
-
}
|
|
555
|
-
catch {
|
|
556
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
563
|
+
const body = (await readJson(req));
|
|
559
564
|
if (!Array.isArray(body.entryIds) || !body.entryIds.every((x) => typeof x === "string")) {
|
|
560
565
|
sendError(res, 400, "request.field_invalid", "entryIds must be an array of strings");
|
|
561
566
|
return;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* [ref] A9 域模块 —— 会话列表 / 发件链接列表。
|
|
3
3
|
*
|
|
4
4
|
* 路由:`GET /v1/sessions`(CC /resume picker,keyset 分页)、`GET /v1/sendfile-links`。
|
|
5
|
-
* owner-scope 与 trace 列表同一权威模型(
|
|
5
|
+
* owner-scope 与 trace 列表同一权威模型(`fleetViewOf` 读档:service 凭据不报主体 / 只读 trace 凭据 / dev-open = fleet-wide;带验过的主体 = 钉住那位主体)。本域零可变状态。
|
|
6
6
|
*/
|
|
7
7
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
8
8
|
import { type SessionListItem } from "../../security.js";
|