@sema-agent/server 7.149.0 → 7.151.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 +307 -9
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +92 -40
- package/deploy/sema-up/README.md +7 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +1 -0
- package/deploy/sema-up/kube-up.sh +1 -1
- package/deploy/sema-up/lib/flagshape.sh +1 -1
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-machine.d.ts +1 -1
- package/dist/approval-card.d.ts +3 -3
- package/dist/approval-gate-currency.d.ts +2 -2
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +2 -2
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +2 -3
- package/dist/bind-host.js +2 -4
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +8 -14
- package/dist/boot/execution-env.js +54 -17
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/reapers.d.ts +5 -0
- package/dist/boot/reapers.js +12 -1
- package/dist/boot/resolve-spec.d.ts +7 -8
- package/dist/boot/resolve-spec.js +80 -35
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.d.ts +9 -2
- package/dist/boot/runner-deps.js +3 -3
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +28 -24
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +7 -4
- package/dist/boot/stage-06-runners.js +16 -8
- package/dist/boot/stage-07-capability-layer.d.ts +7 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +7 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +11 -5
- package/dist/boot/stage-09-leader.js +12 -3
- package/dist/boot/stage-10-http-server.d.ts +44 -6
- package/dist/boot/stage-10-http-server.js +12 -10
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/boot/web-admin.js +3 -1
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capability-facts.d.ts +84 -66
- package/dist/capability-facts.js +58 -41
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +15 -12
- package/dist/config-invariants.d.ts +2 -1
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +22 -15
- package/dist/config.d.ts +51 -2
- package/dist/config.js +35 -24
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +66 -29
- package/dist/device-ws-protocol.d.ts +79 -12
- package/dist/device-ws-protocol.js +64 -26
- package/dist/engine-identity.d.ts +23 -5
- package/dist/engine-identity.js +13 -0
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/execution-env-refusal.d.ts +23 -0
- package/dist/execution-env-refusal.js +5 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +3 -3
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/hook-runner.js +2 -2
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +19 -4
- package/dist/http/approval-sweeps.js +7 -6
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +20 -63
- package/dist/http/checkpoint-ctx.js +2 -24
- package/dist/http/claim-heartbeat.d.ts +4 -4
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/dispatch.d.ts +2 -1
- package/dist/http/dispatch.js +36 -29
- package/dist/http/durable-run-leg.js +17 -17
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +2 -0
- package/dist/http/owner-access.d.ts +264 -20
- package/dist/http/owner-access.js +215 -5
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.js +38 -1
- package/dist/http/resume-legs.d.ts +2 -1
- package/dist/http/resume-legs.js +273 -89
- package/dist/http/route-ctx.d.ts +41 -19
- package/dist/http/route-table.d.ts +1 -1
- package/dist/http/routes/a2a-serve.js +15 -14
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +12 -12
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.js +10 -6
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/projects.d.ts +4 -2
- package/dist/http/routes/projects.js +7 -6
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +125 -66
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +4 -3
- package/dist/http/routes/session-sync.js +174 -83
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +26 -48
- package/dist/http/routes/tasks.js +38 -23
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +28 -30
- package/dist/http/server.js +7 -3
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +1 -2
- package/dist/http/submit-ctx.js +8 -6
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +19 -6
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +4 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +0 -1
- package/dist/leader/endpoint.js +9 -8
- package/dist/leader/leader.d.ts +2 -1
- package/dist/leg-facts.d.ts +19 -5
- package/dist/leg-facts.js +3 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-scope.d.ts +5 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +12 -8
- package/dist/observability/fail-open.js +12 -8
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/owner-faces.d.ts +28 -4
- package/dist/owner-faces.js +2 -0
- package/dist/parked-decide.d.ts +104 -53
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/permission-mode-admission.d.ts +41 -5
- package/dist/permission-mode-admission.js +29 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
- package/dist/plugins/approval-ask-store-memory.js +28 -9
- package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
- package/dist/plugins/approval-ask-store-sql.js +34 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-checkpoint-store.d.ts +4 -1
- package/dist/plugins/local-checkpoint-store.js +3 -0
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +80 -61
- package/dist/plugins/one-time-migrations.js +241 -104
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +28 -1
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +8 -3
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +44 -17
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +114 -14
- package/dist/plugins/remote-env-e2b.d.ts +18 -7
- package/dist/plugins/remote-env-e2b.js +53 -40
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +18 -1
- package/dist/plugins/remote-env-host.js +48 -47
- package/dist/plugins/remote-env-k8s.d.ts +41 -39
- package/dist/plugins/remote-env-k8s.js +56 -32
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +37 -43
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +64 -62
- package/dist/plugins/remote-shell.d.ts +101 -2
- package/dist/plugins/remote-shell.js +221 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +22 -3
- package/dist/plugins/run-store-sql.js +33 -9
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
- package/dist/plugins/schema-consistency.d.ts +9 -5
- package/dist/plugins/schema-consistency.js +48 -18
- package/dist/plugins/schema-drift-sentence.js +1 -1
- package/dist/plugins/send-file-ledger.js +3 -0
- package/dist/plugins/serving-requirement.d.ts +68 -0
- package/dist/plugins/serving-requirement.js +60 -0
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +48 -3
- package/dist/plugins/stop-then-start-sentence.js +48 -0
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +40 -13
- package/dist/plugins/store-backend.js +169 -27
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +29 -2
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.js +9 -0
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +6 -1
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +64 -0
- package/dist/project-context.js +66 -0
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-cancel-card.d.ts +1 -1
- package/dist/run-cancel-card.js +2 -1
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +37 -8
- package/dist/runs.js +53 -12
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +31 -33
- package/dist/security.js +41 -7
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-agent.d.ts +1 -10
- package/dist/session-agent.js +0 -6
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +28 -4
- package/dist/session-incarnation.js +14 -2
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +4 -98
- package/dist/session-sync.js +4 -74
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
- package/dist/stores-sql/checkpoint-store-sql.js +106 -18
- package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
- package/dist/stores-sql/file-history-store-sql.js +108 -70
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +2 -10
- package/dist/stores-sql/retention-store-sql.js +2 -10
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +6 -5
- package/dist/task-settings.d.ts +19 -5
- package/dist/task-settings.js +13 -7
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +147 -12
- package/dist/tool-approval.js +206 -109
- package/dist/trace/engine-notice-wire.d.ts +14 -0
- package/dist/trace/engine-notice-wire.js +18 -1
- package/dist/trace/project.d.ts +4 -3
- package/dist/trace/project.js +3 -2
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/self-minted-wire.d.ts +422 -26
- package/dist/trace/self-minted-wire.js +149 -23
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
- package/package.json +3 -3
- package/wire-changes/server@7.150.0.json +335 -0
- package/wire-changes/server@7.151.0.json +762 -0
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
package/dist/runs.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ import type { RunAcceptance } from "./run-acceptance.js";
|
|
|
17
17
|
import type { SessionWorkspaceRecorder } from "./session-workspace.js";
|
|
18
18
|
import type { VerifyRoundsSpec } from "./http/verify-rounds.js";
|
|
19
19
|
import { type ParkLedgerEventType } from "./trace/ledger-events.js";
|
|
20
|
+
import type { LandedAttendantSeat } from "./plugins/landed-attendants.js";
|
|
21
|
+
import type { DelegationRootWitness } from "./delegated-session-owner.js";
|
|
22
|
+
import type { SessionFace } from "./session-incarnation.js";
|
|
20
23
|
import type { UserInputLedger } from "./user-input-ledger.js";
|
|
21
24
|
/**
|
|
22
25
|
* stoppedBy (core 1.252): a service cancel is a USER stop — mark the run's still-running background
|
|
@@ -27,8 +30,8 @@ import type { UserInputLedger } from "./user-input-ledger.js";
|
|
|
27
30
|
* cross-replica flag poll). Advisory only — the cancel itself must never fail on attribution.
|
|
28
31
|
*
|
|
29
32
|
* Access = TASK-scoped children ONLY: owner = the parent taskId (on a RESUME leg: the sessionId — core's
|
|
30
|
-
* canonical taskId there), scope =
|
|
31
|
-
*
|
|
33
|
+
* canonical taskId there), scope = the engine-identity cell `engineScopeOfOwner(subject)` (core registers
|
|
34
|
+
* children under its task scope, so an anonymous run's children live in scope "default" and an access
|
|
32
35
|
* WITHOUT scope matched nothing). Session-scoped children are DELIBERATELY not marked: a cancelled parent
|
|
33
36
|
* does NOT take them down (CC Backgrounded semantics — core's teardown reaps with skipSessionScoped), so
|
|
34
37
|
* pre-marking them "user" would misattribute a stop that isn't happening.
|
|
@@ -201,10 +204,36 @@ export type ResumeAnchorLeg = "stream" | "sync" | "bg" | "resume";
|
|
|
201
204
|
* 到期只放手不取消:那次写照常在飞,迟到落定的锚照样可用(迟到的失败被吞,不重复计数)。
|
|
202
205
|
* 用户面的读数仍只有一处:会话视图用户消息行的 `taskId?`(present-iff 锚在)与 `resumeAt` 的 404 `resume_at.unknown_event`。
|
|
203
206
|
*/
|
|
204
|
-
export declare function settleResumeAnchor(write: () => Promise<void>, where: {
|
|
207
|
+
export declare function settleResumeAnchor(write: (held: () => boolean) => Promise<void>, where: {
|
|
205
208
|
readonly leg: ResumeAnchorLeg;
|
|
206
209
|
readonly kind: "prompt" | "turn";
|
|
207
210
|
}): Promise<void>;
|
|
211
|
+
/** 一条运行腿的两只回退锚写口(缺席 = 这条腿没有那一种锚:没有落定席位 / 没有提示手柄 / 没有叶子读)。 */
|
|
212
|
+
export interface RunAnchorWriter {
|
|
213
|
+
/** 用户提示锚:键 = 这条 run 的 id(客户端手里的回退手柄),值 = 那条用户提交的条目 id。 */
|
|
214
|
+
readonly prompt?: (entryId: string, held: () => boolean) => Promise<void>;
|
|
215
|
+
/** 助手文本锚:键 = 这一轮第一个 text 帧的 eventId,值 = 此刻会话的叶子。 */
|
|
216
|
+
readonly turn?: (eventId: string, held: () => boolean) => Promise<void>;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* **运行腿回退锚的唯一写法**(后台腿 / 同步腿 / 流式腿 / 续跑腿同一只):锚只经落定席位的 `putAnchors` 落(`plugins/landed-attendants.ts`:段首锁会话根行判住客),
|
|
220
|
+
* 住客 = **这条 run 自己的那一位** —— 受理时见证到的(`LegFacts.sessionWitness`,带化身);见证里还没有化身(这条腿新建了会话)⇒ 第一笔锚之前读一次头钉住。
|
|
221
|
+
* 钉住发生在腿还在等这一笔的期限之内(`held()`:腿被这一笔挡着 ⇒ run 在跑、认领在手 ⇒ 会话删不掉),到期之后才完成的钉住不发写;已发出的写到期只放手不取消
|
|
222
|
+
* (`settleResumeAnchor`),但它绑着钉住的那一位 —— run 收场、会话被删、同 id 被别人重建之后才落的那一笔落不进新住客,也落不进空闲 id(段判「不是那一位」⇒ 零写,
|
|
223
|
+
* 记一次同一只 fail-open,`reason=error`)。没有席位 ⇒ 两只都缺席(这台部署不存锚)。
|
|
224
|
+
*/
|
|
225
|
+
export declare function createRunAnchorWriter(args: {
|
|
226
|
+
readonly seat: Pick<LandedAttendantSeat, "putAnchors"> | undefined;
|
|
227
|
+
readonly sessionId: string;
|
|
228
|
+
readonly owner: string | null;
|
|
229
|
+
/** 用户提示锚的键(这条 run 的 id);缺 ⇒ 不写提示锚(没有手柄 / 续跑腿接着别的腿的 run)。 */
|
|
230
|
+
readonly promptKey: string | undefined;
|
|
231
|
+
readonly witness: DelegationRootWitness | undefined;
|
|
232
|
+
/** 头读投成的住客(属主存取器的 `sessionOccupantReadOf`);缺 ⇒ 见证里没有化身时钉不住 ⇒ 不写。 */
|
|
233
|
+
readonly occupantOf: ((sessionId: string) => Promise<SessionFace | undefined>) | undefined;
|
|
234
|
+
/** 会话此刻的叶子(属主存取器的 `sessionFactsReadOf` 投影);缺 ⇒ 不写助手文本锚。 */
|
|
235
|
+
readonly leafOf: ((sessionId: string) => Promise<string | null | undefined>) | undefined;
|
|
236
|
+
}): RunAnchorWriter;
|
|
208
237
|
export declare class TurnAnchorCapture {
|
|
209
238
|
private readonly capture;
|
|
210
239
|
/** 这只捕获器在哪条腿上(写失败的 fail-open 探针行带它)。 */
|
|
@@ -227,7 +256,7 @@ export declare class TurnAnchorCapture {
|
|
|
227
256
|
private turnHadTool;
|
|
228
257
|
/** 用户提交是不是开场提示的唯一读法({@link createPromptCommitReader};开场窗 + 闩 —— 开场提示之后打断标记 / steer 不改锚;附件帧不是提问)。 */
|
|
229
258
|
private readonly promptCommit;
|
|
230
|
-
constructor(capture: ((eventId: string) => Promise<void>) | undefined,
|
|
259
|
+
constructor(capture: ((eventId: string, held: () => boolean) => Promise<void>) | undefined,
|
|
231
260
|
/** 这只捕获器在哪条腿上(写失败的 fail-open 探针行带它)。 */
|
|
232
261
|
leg: Exclude<ResumeAnchorLeg, "stream">,
|
|
233
262
|
/** R8 (CC-parity rewind): capture a USER-message anchor straight from the
|
|
@@ -242,7 +271,7 @@ export declare class TurnAnchorCapture {
|
|
|
242
271
|
* user-role commit in the same run — the interruption marker, a steer — never moves it. The capture instance is per
|
|
243
272
|
* run: a leg that CONTINUES an existing run (same taskId) wires no `captureUser` (its opening prompt was anchored
|
|
244
273
|
* by the first leg). */
|
|
245
|
-
captureUser?: ((entryId: string) => Promise<void>) | undefined);
|
|
274
|
+
captureUser?: ((entryId: string, held: () => boolean) => Promise<void>) | undefined);
|
|
246
275
|
/** A `human_input` arrived — the objective's declared attachments open the frame window of {@link createPromptCommitReader} (another applied input inside the window voids it). */
|
|
247
276
|
onHumanInput(ev: {
|
|
248
277
|
readonly type: string;
|
|
@@ -359,7 +388,7 @@ cascade?: CascadeConfig, instrumentDegenerate?: (result: TaskResult) => void, pl
|
|
|
359
388
|
elicitOwner?: string | null,
|
|
360
389
|
/** E18 resume-at: capture the turn's (firstTextEventId → leaf entryId) anchor at each turn_end. Built by the caller
|
|
361
390
|
* closing over {sessionId, owner, the session store's head read (`headOf(id)?.leafId`), resumeAnchorStore}; undefined ⇒ no anchor store wired. */
|
|
362
|
-
captureTurnAnchor?: (eventId: string) => Promise<void>,
|
|
391
|
+
captureTurnAnchor?: (eventId: string, held: () => boolean) => Promise<void>,
|
|
363
392
|
/** MF-Fleet (shell-host contract): the run-scoped fleet-row publisher. `onStart` adds the live row; `onEvent` accrues
|
|
364
393
|
* tokens (turn_end) + subagent child rows (task_progress); `onTerminal` flips/removes it. Fired for ALL legs
|
|
365
394
|
* (verify/cascade/plain-stream) so a background run TRANSITIONS its `GET /v1/fleet/stream` row exactly like the
|
|
@@ -367,7 +396,7 @@ captureTurnAnchor?: (eventId: string) => Promise<void>,
|
|
|
367
396
|
fleetPublisher?: FleetRunPublisher,
|
|
368
397
|
/** R8 (CC-parity rewind): capture a USER-message anchor (keyed by this run's taskId) from `message_committed{role:"user"}`
|
|
369
398
|
* — the CC "rewind to the prompt" target. undefined ⇒ no anchor store wired. */
|
|
370
|
-
captureUserMessageAnchor?: (entryId: string) => Promise<void>,
|
|
399
|
+
captureUserMessageAnchor?: (entryId: string, held: () => boolean) => Promise<void>,
|
|
371
400
|
/** §4④ : AskUserQuestion LIVE coordinator — establishes a per-run onQuestion ALS context (like `elicitation`)
|
|
372
401
|
* so an AskUserQuestion tool call routes to this run's stream + owner-gated respond. undefined ⇒ headless default. */
|
|
373
402
|
question?: QuestionCoordinator,
|
|
@@ -457,7 +486,7 @@ workspaceRecorder?: SessionWorkspaceRecorder,
|
|
|
457
486
|
*/
|
|
458
487
|
runSkills?: readonly RunSkillEntry[],
|
|
459
488
|
/**
|
|
460
|
-
*
|
|
489
|
+
* 这条腿跑在的工作目录(部署事实 `LegFacts.sessionBindings.cwd`)。只在两条组合腿(verify / cascade)上经 `compositionLegRoot` 交给引擎 ——
|
|
461
490
|
* 梯子的级 / 验证器腿跑在引擎现铸的会话里,工厂按会话读不到它;普通流形跑在根会话上,工厂自己读得到。缺席 = 没登记 ⇒ 每一条腿照旧落临时目录。
|
|
462
491
|
*/
|
|
463
492
|
registeredCwd?: string): Promise<void>;
|
package/dist/runs.js
CHANGED
|
@@ -9,9 +9,8 @@ import { TOOL_DECLARATION_HTTP_STATUS } from "./tool-declaration-http-status.js"
|
|
|
9
9
|
import { isSessionErrorCode, sessionErrorHttp } from "./session-error-wire.js";
|
|
10
10
|
import { redactErrorMessage } from "./observability/run-terminal.js";
|
|
11
11
|
import { withSubject } from "./observability/principal-context.js";
|
|
12
|
-
import { partsOf } from "./owner-brands.js";
|
|
13
12
|
import { recoveredSubject } from "./owner-faces.js";
|
|
14
|
-
import {
|
|
13
|
+
import { engineScopeOfOwner } from "./engine-identity.js";
|
|
15
14
|
import { withModelReachScope } from "./model-reach-scope.js";
|
|
16
15
|
import { createInstructionSelectionLeg } from "./instruction-selection.js";
|
|
17
16
|
import { redactSecrets } from "./trace/redact.js";
|
|
@@ -62,11 +61,10 @@ export async function taskHandleStop(registry, handle, access, agentStore) {
|
|
|
62
61
|
return registry.stopTask(handle, access);
|
|
63
62
|
}
|
|
64
63
|
export function markChildrenStoppedByUserOnAbort(signal, taskId, subject) {
|
|
65
|
-
const
|
|
66
|
-
const principal = taskSpecIdentityOf(recovered === undefined ? undefined : partsOf(recovered)).principal;
|
|
64
|
+
const scope = engineScopeOfOwner(subject);
|
|
67
65
|
const mark = () => {
|
|
68
66
|
try {
|
|
69
|
-
defaultTaskRegistry.markStopSourceForOwner({ owner: taskId, scope
|
|
67
|
+
defaultTaskRegistry.markStopSourceForOwner({ owner: taskId, scope }, "user", { skipSessionScoped: true });
|
|
70
68
|
}
|
|
71
69
|
catch {
|
|
72
70
|
}
|
|
@@ -79,6 +77,10 @@ export function markChildrenStoppedByUserOnAbort(signal, taskId, subject) {
|
|
|
79
77
|
}
|
|
80
78
|
const EXECUTION_ENV_REFUSAL_HTTP_STATUS = {
|
|
81
79
|
"env.home_unconfirmed": 409,
|
|
80
|
+
"env.snapshot_bucket_missing": 409,
|
|
81
|
+
"env.occupant_missing": 409,
|
|
82
|
+
"env.sandbox_refused": 409,
|
|
83
|
+
"env.host_key_rejected": 409,
|
|
82
84
|
};
|
|
83
85
|
const PREPARE_REFUSAL_HTTP_STATUS = {
|
|
84
86
|
"resume.session_not_found": 404,
|
|
@@ -234,13 +236,52 @@ export function createPromptCommitReader() {
|
|
|
234
236
|
};
|
|
235
237
|
}
|
|
236
238
|
export async function settleResumeAnchor(write, where) {
|
|
239
|
+
let open = true;
|
|
237
240
|
try {
|
|
238
|
-
await withinIoDeadline(write);
|
|
241
|
+
await withinIoDeadline(() => write(() => open));
|
|
239
242
|
}
|
|
240
243
|
catch (err) {
|
|
241
244
|
const why = err instanceof IoDeadlineExceeded ? `reason=timeout boundMs=${BASELINE_IO_DEADLINE_MS}` : `reason=error error=${err instanceof Error ? err.message : String(err)}`;
|
|
242
245
|
recordFailOpen("server.resume-anchor.capture-failed", `leg=${where.leg} kind=${where.kind} ${why}`);
|
|
243
246
|
}
|
|
247
|
+
finally {
|
|
248
|
+
open = false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export function createRunAnchorWriter(args) {
|
|
252
|
+
const { seat, sessionId, owner, promptKey, witness, occupantOf, leafOf } = args;
|
|
253
|
+
if (seat === undefined)
|
|
254
|
+
return {};
|
|
255
|
+
let pinned = witness !== undefined && witness.incarnation !== null ? { owner: witness.owner, incarnation: witness.incarnation } : undefined;
|
|
256
|
+
const pin = async () => (pinned ??= await occupantOf?.(sessionId));
|
|
257
|
+
const put = async (landed, eventId, entryId) => {
|
|
258
|
+
const out = await seat.putAnchors(sessionId, landed, [{ eventId, entryId }], owner);
|
|
259
|
+
if (!out.landed)
|
|
260
|
+
throw new Error("the session's occupant is no longer this run's — the anchor was not written");
|
|
261
|
+
};
|
|
262
|
+
return {
|
|
263
|
+
...(promptKey !== undefined
|
|
264
|
+
? {
|
|
265
|
+
prompt: async (entryId, held) => {
|
|
266
|
+
const landed = await pin();
|
|
267
|
+
if (landed !== undefined && held())
|
|
268
|
+
await put(landed, promptKey, entryId);
|
|
269
|
+
},
|
|
270
|
+
}
|
|
271
|
+
: {}),
|
|
272
|
+
...(leafOf !== undefined
|
|
273
|
+
? {
|
|
274
|
+
turn: async (eventId, held) => {
|
|
275
|
+
const landed = await pin();
|
|
276
|
+
if (landed === undefined || !held())
|
|
277
|
+
return;
|
|
278
|
+
const leaf = await leafOf(sessionId);
|
|
279
|
+
if (leaf)
|
|
280
|
+
await put(landed, eventId, leaf);
|
|
281
|
+
},
|
|
282
|
+
}
|
|
283
|
+
: {}),
|
|
284
|
+
};
|
|
244
285
|
}
|
|
245
286
|
export class TurnAnchorCapture {
|
|
246
287
|
capture;
|
|
@@ -262,7 +303,7 @@ export class TurnAnchorCapture {
|
|
|
262
303
|
const prompt = this.promptCommit(committed);
|
|
263
304
|
const captureUser = this.captureUser;
|
|
264
305
|
if (prompt !== undefined && captureUser)
|
|
265
|
-
await settleResumeAnchor(() => captureUser(prompt), { leg: this.leg, kind: "prompt" });
|
|
306
|
+
await settleResumeAnchor((held) => captureUser(prompt, held), { leg: this.leg, kind: "prompt" });
|
|
266
307
|
}
|
|
267
308
|
onText(eventId) {
|
|
268
309
|
if (this.firstTextEventId === undefined) {
|
|
@@ -278,7 +319,7 @@ export class TurnAnchorCapture {
|
|
|
278
319
|
const capture = this.capture;
|
|
279
320
|
const handle = this.firstTextEventId;
|
|
280
321
|
if (handle && !this.turnHadTool && capture)
|
|
281
|
-
await settleResumeAnchor(() => capture(handle), { leg: this.leg, kind: "turn" });
|
|
322
|
+
await settleResumeAnchor((held) => capture(handle, held), { leg: this.leg, kind: "turn" });
|
|
282
323
|
this.firstTextEventId = undefined;
|
|
283
324
|
this.turnHadTool = false;
|
|
284
325
|
}
|
|
@@ -388,6 +429,7 @@ export async function runInBackground(runner, spec, runStore, taskId, parkCommit
|
|
|
388
429
|
await sink.appendParked(word, grafted);
|
|
389
430
|
const sealed = sealResultForExit(grafted);
|
|
390
431
|
reached = { kind: word, result: sealed };
|
|
432
|
+
await acceptance?.settle(sealed);
|
|
391
433
|
const committed = await commitParkRow({
|
|
392
434
|
runStore, taskId, word, result: sealed, card: { token, sessionId: spec.sessionId }, cards: checkpointCards, leg: "bg",
|
|
393
435
|
legId: parkCommit.legId, staleWindowMs: parkCommit.runStaleSec === undefined ? undefined : parkCommit.runStaleSec * 1000,
|
|
@@ -396,7 +438,6 @@ export async function runInBackground(runner, spec, runStore, taskId, parkCommit
|
|
|
396
438
|
reached = undefined;
|
|
397
439
|
settledAsCancel = committed.row?.errorCode === CANCELLED_CODE;
|
|
398
440
|
}
|
|
399
|
-
acceptance?.settle(sealed);
|
|
400
441
|
};
|
|
401
442
|
const settleLegResult = async (engineResult) => {
|
|
402
443
|
const result = atHostBoundary(engineResult);
|
|
@@ -410,10 +451,10 @@ export async function runInBackground(runner, spec, runStore, taskId, parkCommit
|
|
|
410
451
|
const safe = await withModelUsage(sealResultForExit(settled));
|
|
411
452
|
await sink.appendDone(safe);
|
|
412
453
|
reached = { kind: "done", result: safe };
|
|
454
|
+
await acceptance?.settle(safe);
|
|
413
455
|
const plane = outwardPlane(safe.terminal);
|
|
414
456
|
await runStore.setTerminal(taskId, plane.status, safe, plane.errorMessage ?? null);
|
|
415
457
|
await releaseKeyIfZeroWorkRefusal(runStore, taskId, safe);
|
|
416
|
-
acceptance?.settle(safe);
|
|
417
458
|
};
|
|
418
459
|
const instructionLeg = createInstructionSelectionLeg();
|
|
419
460
|
const sink = createLedgerSink({ appendEvent: (seq, type, data) => runStore.appendEvent(taskId, seq, type, data), persistThinking, notifiedKeys, onActivity: (kind, statusData) => recordTurnActivity(taskId, kind, statusData), legSections: () => ({ instructions: instructionLeg.segment(), skills: runSkills }), usage: { modelUsage, taskId } });
|
|
@@ -609,12 +650,12 @@ export async function runInBackground(runner, spec, runStore, taskId, parkCommit
|
|
|
609
650
|
if (reached?.kind === "done") {
|
|
610
651
|
const plane = outwardPlane(reached.result.terminal);
|
|
611
652
|
settledAsCancel = failureCodeOf(reached.result.terminal) === CANCELLED_CODE;
|
|
653
|
+
await acceptance?.settle(reached.result);
|
|
612
654
|
await runStore.setTerminal(taskId, plane.status, reached.result, plane.errorMessage ?? null);
|
|
613
655
|
await releaseKeyIfZeroWorkRefusal(runStore, taskId, reached.result);
|
|
614
|
-
acceptance?.settle(reached.result);
|
|
615
656
|
}
|
|
616
657
|
else if (reached !== undefined) {
|
|
617
|
-
acceptance?.settle(reached.result);
|
|
658
|
+
await acceptance?.settle(reached.result);
|
|
618
659
|
}
|
|
619
660
|
else if (thrownCancelCause === undefined && observedDone !== undefined && heldParkOf(atHostBoundary(observedDone)) !== undefined) {
|
|
620
661
|
recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=park-held ${message}`);
|
|
@@ -92,8 +92,9 @@ export declare function compileCommandPolicyLayers(rules: CommandRule[] | undefi
|
|
|
92
92
|
* `plan` 是有出口的**生命周期词**(`plan_review` 把计划带出 plan),不是围栏:它是**提交入口的模式词地板**({@link autonomyModeFloor}),
|
|
93
93
|
* 盖在每一个 spec 出生点一次(词 = {@link entryPermissionMode} 的 `effective`):受理门盖进存储的提交体(`task-settings.ts` `stampEntryPermissionMode`)、run-local 盖在它自建的 spec 上、
|
|
94
94
|
* leader run 盖在它出生时的入口体上(`leader/run-entry.ts`;入口词是 `plan` 的 leader run 进不了那条车道 —— worker 会话没有计划审阅通道 ⇒ 受理口响亮拒)。此后一条 run 的模式词
|
|
95
|
-
* 只有存储体一个源,写者是每一个出生点(新的持久化写都经 `http/checkpoint-ctx.ts` `buildCheckpointCtx`)
|
|
96
|
-
*
|
|
95
|
+
* 只有存储体一个源,写者是每一个出生点(新的持久化写都经 `http/checkpoint-ctx.ts` `buildCheckpointCtx`)、`plan_review` 写回与续跑口(停驻 run 的存储体被重放之前过一次**现**地板、
|
|
96
|
+
* 钳过的随 CAS 赢点写回;`permission-mode-admission.ts` `stampReplayEntryMode`,地板的出口词 —— `plan_review` 批准写下的词 —— 原样读)。按段折一个模式词 = 第二个源:
|
|
97
|
+
* 被批准的计划会在下一次挂起→续跑被拉回 plan;续跑口不是按段折 —— 它与提交口同一只入口一步,写的是同一个源,且不碰出口词。收紧入参的型上因此没有 `permissionMode`(`governance-overrides.ts`)。(上一个发布版本里本档不碰模式词,按段折的是只读手 +
|
|
97
98
|
* 写面 `roots`、与 `read-only` 同形 —— 运维 plan 那时根本不进 plan 模式,见下一段。)
|
|
98
99
|
*
|
|
99
100
|
* 🔴 **为什么 `plan` 不再与 `read-only` 同形**:修前两档同映「只读手 + roots」,外加 `resolve-spec.ts` 见只读手就剥委派工具 —— 于是 `plan` 有三套
|
|
@@ -145,8 +146,8 @@ export interface EntryPermissionMode<W extends PermissionMode | undefined = Perm
|
|
|
145
146
|
* 无人值守腿(`unattended-permission-mode.ts` `withUnattendedLeg`:`default` 钳在 spec 的词之下);
|
|
146
147
|
* · 「这个词会变成什么」的读者 —— 能力面写面开不开({@link autonomyKeepsOpenWriteFace}:bypass 声明过地板)、能力面 auto 读面
|
|
147
148
|
* (`auto-mode-face.ts` `judgeAutoModeArming`:意图过地板;`clamped` 且不是 auto ⇒ 未武装原因 `operator_floor`)、
|
|
148
|
-
*
|
|
149
|
-
* `test/entry-permission-mode.test.ts` 按语法树钉:core 钳在 `src/`
|
|
149
|
+
* 受理判官的入口一步(`permission-mode-admission.ts` `entryStep`:提交口盖章、在飞切档口、续跑口 —— 停驻 run 的存储体被重放之前过**现**地板 —— 三口同经这一处)。
|
|
150
|
+
* `test/entry-permission-mode.test.ts` 按语法树钉:core 钳在 `src/` 只此一处调用,本函数七处调用点各一次。
|
|
150
151
|
*/
|
|
151
152
|
export declare function entryPermissionMode<W extends PermissionMode | undefined>(word: W, floor: PermissionMode | undefined): EntryPermissionMode<W>;
|
|
152
153
|
/**
|
package/dist/security.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IncomingMessage } from "node:http";
|
|
2
|
+
import type { EntriesStreamOptions } from "./session-sync-kernel.js";
|
|
2
3
|
import { type SessionHead, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
3
4
|
import type { ServiceConfig } from "./config-types.js";
|
|
4
5
|
import type { Logger } from "./observability/logger.js";
|
|
@@ -9,6 +10,8 @@ import type { TaskRequestBody } from "./http/wire-types.js";
|
|
|
9
10
|
import type { StagingHandle } from "./session-sync-kernel.js";
|
|
10
11
|
import type { SessionDeletionFace } from "./session-deletion.js";
|
|
11
12
|
import { type SessionBirth } from "./session-incarnation.js";
|
|
13
|
+
import { type IdleSession, type IdleSessionCursor, type SessionKind, type SessionKindReading } from "./session-kind.js";
|
|
14
|
+
import type { SessionListQuery } from "./plugins/store-contracts.js";
|
|
12
15
|
import type { ClientSessionRowWrite, ReplaySessionRowWrite, ReplaySessionRowWriteOutcome, SessionRowAnswer, SessionRowPatch, SessionRowWriteOutcome } from "./session-row.js";
|
|
13
16
|
import type { ExecutionPlacementSeat } from "./execution-placement.js";
|
|
14
17
|
import type { SessionUnreadable } from "./session-error-wire.js";
|
|
@@ -56,6 +59,10 @@ export interface SessionListItem {
|
|
|
56
59
|
* by a fork after lineage was recorded (an older fork is not backfilled: its source is unknown). OMIT-when-absent, never `null`. Additive key, passed
|
|
57
60
|
* through unprojected (`sessions-list.ts`). Same name and meaning as `SessionSummary.forkedFrom` in `plugins/store-contracts.ts`. */
|
|
58
61
|
forkedFrom?: string;
|
|
62
|
+
/** The session's kind (`session-kind.ts`): present-iff the session was created by a submission that declared `sessionKind`; a top-level session
|
|
63
|
+
* never carries it (OMIT-when-absent, never `null`). The default list view lists only top-level sessions; `?sessionKind=<word>` lists that kind.
|
|
64
|
+
* Additive key, passed through unprojected (`sessions-list.ts`). Same name and meaning as `SessionSummary.sessionKind` in `plugins/store-contracts.ts`. */
|
|
65
|
+
sessionKind?: SessionKind;
|
|
59
66
|
}
|
|
60
67
|
/**
|
|
61
68
|
* 会话店的行格写原语(规则与判序:`session-row.ts` 头注「写原语」)—— 按入口分两只重载:客户端写(PATCH)的结局闭集四员;行重放(2c 导入落定后的那一笔)
|
|
@@ -74,7 +81,7 @@ export interface SessionRowCellsWriter {
|
|
|
74
81
|
* 🔴 2026-08-01 复审逮到:守卫原本是**逐条路由白名单**(`PUT …/policy`、`POST …/sync/import`),
|
|
75
82
|
* 而 `DELETE /v1/sessions/:id`(删整条会话)不在其中 —— 同一风险形、爆炸半径**更大**,却没门。
|
|
76
83
|
*
|
|
77
|
-
* 风险形逐字同源(守卫自己的注释)
|
|
84
|
+
* 风险形逐字同源(守卫自己的注释):「请求没带凭据门认的凭据 + 未开 `ALLOW_UNAUTHED_WRITES`」这一形下
|
|
78
85
|
* fleet 写档(面表 fleet 列的 `dev_open` 格,`owner-faces.ts` 的 `listFilterOf`)判 fleet-wide ⇒ 集群内**任意**不报主体的调用方可对**任意** session 动手(报了主体的调用方只动得到那位主体的,`principal-gate.ts` 的 `actsForDeployment`)。
|
|
79
86
|
* policy 腿担心的是「forged principal 能 tighten/DoS 一个会话的工具」;DELETE 直接把会话删掉。
|
|
80
87
|
*
|
|
@@ -104,6 +111,10 @@ export type SessionOwnerCell = {
|
|
|
104
111
|
export declare function claimCallerOf(subject: Subject | undefined, config: DeploymentShapeInput<"principal">): Caller;
|
|
105
112
|
/** 提交挂接「没有这只会话」那一答的句子(requireExisting 缺行与认领面看不见同一句;投影 `attach_absent`)。 */
|
|
106
113
|
export declare const ATTACH_ABSENT_MESSAGE = "requireExistingSession: session does not exist (resume.session_not_found)";
|
|
114
|
+
/** 带种类的提交撞上一只种类不同的既有会话的 409(律 `session-kind.ts`):体上机读位 `sessionKind` = 行上的词(顶层行缺席)。句子不回显请求的词以外的任何行事实。 */
|
|
115
|
+
export declare const SESSION_KIND_MISMATCH_MESSAGE = "this session already exists with a different session kind \u2014 a session's kind is written once, when the session is created, and never changes; send the same sessionKind the session was created with, omit sessionKind to run the session as it is, or start a new session";
|
|
116
|
+
/** 部署记不了种类(会话店没有出生回执面 / 种类读)⇒ 400 `request.precondition_unmet`(受理门读同一只能力事实 `capability-facts.ts` 的 `sessionKinds`,先拒在那里;这里是纵深)。 */
|
|
117
|
+
export declare const SESSION_KIND_UNRECORDABLE_MESSAGE = "sessionKind requires a session store that records a session's kind and ages such sessions out (DB_BACKEND=mysql|pg|local) \u2014 this deployment cannot, so the session would be created as a top-level conversation; capabilities.sessionKinds lists the kinds a deployment accepts";
|
|
107
118
|
/** 读一只会话行的 {@link SessionOwnerCell}:有主行 = 属主那一格(`owner-faces.ts` 的 `ownerCellOf`,属主列读数的唯一铸法);无主时问一次店的 `placementOf`
|
|
108
119
|
* (既有读口;店不交它 = 不实现 placement = 没有 placed 行)。`owner` = 调用点那一读。 */
|
|
109
120
|
export declare function sessionOwnerCellOf(store: Pick<OwnerAwareSessionStore, "placementOf"> | undefined, sessionId: string, owner: string | null): Promise<SessionOwnerCell>;
|
|
@@ -135,35 +146,25 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
135
146
|
register?: (sessionId: string, owner: string | null) => Promise<void>;
|
|
136
147
|
/** [ref] placed 分区的元组读口(店的既有读口,一行 PK 读;`undefined` = 普通会话或无此行)。店不交它 = 不实现 placement = 没有 placed 行(无 repo 的内存店)。两个读者:
|
|
137
148
|
* ① 会话面的属主门只在属主为 NULL 时读它一次(无主的 placed 行不是公共行,`http/principal-gate.ts` 的 `sessionOwnerCellOf`);
|
|
138
|
-
* ② `agent` 的唯一读口 `
|
|
149
|
+
* ② `agent` 的唯一读口 `http/owner-access.ts` 的 `readSessionAgent`(会话视图体顶层、运维审批队列的停驻行同读):店没有这一面 ⇒ 键缺席,读面不凭别处另铸子代身份。 */
|
|
139
150
|
placementOf?: (sessionId: string) => Promise<SessionPlacementRecord | undefined>;
|
|
140
151
|
/** E16 — enumerate the caller's sessions (owner-filtered on the session store's OWN owner column).
|
|
141
152
|
* `includeUnowned` = [ref] 窄互认第二臂的**第三条件**(`owner IS NULL`)的 SQL 承载位:置真时
|
|
142
153
|
* 谓词放宽为 `owner = ? OR owner IS NULL`。只在 `owner` 在场时有意义(路由已判①③);`owner` 缺席
|
|
143
154
|
* (fleet-wide)时本位无效——那一面本来就不钉 owner。 */
|
|
144
|
-
listSessions?: (opts:
|
|
145
|
-
owner?: string;
|
|
146
|
-
includeUnowned?: boolean;
|
|
147
|
-
cursor?: {
|
|
148
|
-
lastActivityAt: string;
|
|
149
|
-
sessionId: string;
|
|
150
|
-
};
|
|
151
|
-
limit: number;
|
|
152
|
-
q?: string;
|
|
153
|
-
}) => Promise<SessionListItem[]>;
|
|
155
|
+
listSessions?: (opts: SessionListQuery) => Promise<SessionListItem[]>;
|
|
154
156
|
/** The SAME list face as {@link listSessions} (same SELECT, same mapper, same predicate and keyset) with each row's occupant — the row's owner and
|
|
155
157
|
* incarnation as read in that one read. The incarnation never enters the row (it is not a wire fact: `session-incarnation.ts`); this pair is for the
|
|
156
158
|
* in-process reader that must address a row by occupant — the peer directory's `PeerSessionRecord.occupant`. `listSessions` is this face's rows. */
|
|
157
|
-
listSessionRows?: (opts:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
limit: number;
|
|
165
|
-
|
|
166
|
-
}) => Promise<Array<SessionRowAnswer<SessionListItem>>>;
|
|
159
|
+
listSessionRows?: (opts: SessionListQuery) => Promise<Array<SessionRowAnswer<SessionListItem>>>;
|
|
160
|
+
/** 按 id 的种类读(律 `session-kind.ts`;授权口的种类判与会话视图的 `sessionKind` 读它):读到它时行上的住客 + 种类。三只持久店都交,包装原样转发。 */
|
|
161
|
+
sessionKindOf?: (sessionId: string) => Promise<SessionKindReading | undefined>;
|
|
162
|
+
/** 老化候选面(律 `session-kind.ts`;唯一读者 = 维护拍的老化腿 `boot/session-age-out.ts`):种类为 `kind`、最后活动早于 `idleBefore`、当下无活引用的会话(在删的照交),
|
|
163
|
+
* 最老先出、`(lastActivityAt, sessionId)` 升序 keyset 续页(`after` = 上一页最后一条)。与 `listPlaced`、删除面 `pending()` 同族的用途专一枚举 —— 不出列表投影。 */
|
|
164
|
+
listIdleOfKind?: (kind: SessionKind, idleBefore: Date, page: {
|
|
165
|
+
readonly after?: IdleSessionCursor;
|
|
166
|
+
readonly limit: number;
|
|
167
|
+
}) => Promise<IdleSession[]>;
|
|
167
168
|
/** ONE session's list row — the SAME projection {@link listSessions} emits for it (same columns, same mapper). `undefined` = not a
|
|
168
169
|
* row of the list face (no such session, or a placed / delegation-transcript session, which never lists). Reader: the 2c
|
|
169
170
|
* manifest (`title` / `pinned`). */
|
|
@@ -215,10 +216,7 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
215
216
|
* `opts.batchSize` is the page size (default 500). Resolves to `null` (NOT an empty iterable) when the session does
|
|
216
217
|
* not exist (the existence probe is async — `session_meta` first, like {@link exportEntries} — so the method returns
|
|
217
218
|
* a Promise of the iterable-or-null; the iterable itself then pages lazily). The read half of exportEntries, paged. */
|
|
218
|
-
exportEntriesStream?: (sessionId: string, opts
|
|
219
|
-
afterSeq?: number;
|
|
220
|
-
batchSize?: number;
|
|
221
|
-
}) => Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
219
|
+
exportEntriesStream?: (sessionId: string, opts: EntriesStreamOptions) => Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
222
220
|
/** 2c session-sync — IMPORT a verbatim entry log into `sessionId`, re-stamping `owner` to the
|
|
223
221
|
* authenticated importing principal (never the bundle's). The log is passed through core's
|
|
224
222
|
* `validateEntriesForImport` (the single fail-closed invariant gate) before any write. */
|
|
@@ -303,7 +301,7 @@ export interface AuthContext {
|
|
|
303
301
|
* `PROJECT_ID_REGEX` 门后折小写回传;[ref]/[ref] 宽读严写 —— 词法带 /i 收下大写形,但派生 scope 键
|
|
304
302
|
* 与 config.projects 查表都只认这一个归一形,否则同一个项目会按大小写分成两只记忆盘)。
|
|
305
303
|
* 身份半场(scope 的 tenant 段)永远来自 verified principal — projectId 只选「哪个项目盘/哪条登记」
|
|
306
|
-
* (config.projects 查表键 + proj: 键的 projectId 段),不是 capability
|
|
304
|
+
* (config.projects 查表键 + proj: 键的 projectId 段),不是 capability。装配器拿它判 defaultScopes 种子项目(对提交者可见才算,`project-registry.ts`)。 */
|
|
307
305
|
resolvedProjectId?: string;
|
|
308
306
|
}
|
|
309
307
|
/** 授权口的入参:请求、体,与提交出口收候选的口(`submission-exit.ts`;只有登记了新行才调,传了也可能一次不调)。 */
|
|
@@ -385,9 +383,9 @@ export declare const CHECKPOINT_PUBLIC_SCOPE: "_";
|
|
|
385
383
|
*
|
|
386
384
|
* 写侧不是本仓能单方面改的:core 的 `treeScope = reviveClaim?.row.scope ?? ctx.principal ??
|
|
387
385
|
* opts.background?.scope` 同时喂**进程内** `defaultTaskRegistry` 与 **durable** 行,而本仓/`core` 全域的
|
|
388
|
-
*
|
|
389
|
-
* `sessionTenantScope`(删除协调器的子代 / 信箱 / 后台 shell 三腿)、`http/routes/runs.ts` 的 subagent
|
|
390
|
-
*
|
|
386
|
+
* 读侧经唯一换算 `engine-identity.ts` 的 `engineScopeOf` / `engineScopeOfOwner`(匿名 ⇒ `"default"`;读者:`runs.ts` markStopSourceForOwner、
|
|
387
|
+
* 会话的引擎租户分区 `session-children-retire.ts` `sessionTenantScope`(删除协调器的子代 / 信箱 / 后台 shell 三腿)、`http/routes/runs.ts` 的 subagent
|
|
388
|
+
* output/stream 与句柄三口、`agents-roster.ts`、`fleet.ts` 的工作流行)。⇒ **把铸点改成 `"_"` 会把这一整族读者一起打瞎**(本车实测:`subagent-tail-content-supply`
|
|
391
389
|
* 的 tail 建连当场 404)。所以归一只能发生在**读侧**:checkpoint 侧拿着 `"_"` 去查 bg 分区时,
|
|
392
390
|
* 显式把这两个键当同一格。
|
|
393
391
|
*/
|
|
@@ -396,9 +394,9 @@ export declare const BACKGROUND_REGISTRY_ANON_SCOPE: "default";
|
|
|
396
394
|
* checkpoint 的 scope → 该在哪些 **bg 注册簿分区**里找它的 parked 子代([ref])。
|
|
397
395
|
*
|
|
398
396
|
* 匿名(`"_"`)⇒ 两个都查:`"_"`(将来若统一了写侧)与 `"default"`(今天 core 真写下去的那个)。
|
|
399
|
-
* 其余 ⇒
|
|
400
|
-
*
|
|
401
|
-
*
|
|
397
|
+
* 其余 ⇒ 引擎那一格单查:停驻行的 scope 列是**主体**,bg 行是引擎按它的任务 scope 写的(落点今天只写人)⇒ 经唯一换算
|
|
398
|
+
* `engine-identity.ts` 的 `engineScopeOfOwner`:没带场景的主体逐字节同(两套约定折出同一个串),带场景的主体 ⇒ 那个人;
|
|
399
|
+
* 不存在第二个候选。多租户部署里一个**真名叫 `default`** 的租户只匹配自己那格 —— 所以别把别名做成双向。
|
|
402
400
|
*/
|
|
403
401
|
export declare function backgroundScopesForCheckpointScope(scope: string): readonly string[];
|
|
404
402
|
/** Encode a subject (the partition key — `owner-brands.ts`; or none) as the checkpoint `scope` column value. A row owner read back from a store is the
|
package/dist/security.js
CHANGED
|
@@ -3,8 +3,10 @@ import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
|
|
|
3
3
|
import { FACES, OWNERLESS_ORDINARY_CELL, ownerCellOf, ownerlessCellWithoutRead, qualsOf, recoveredSubject, visibleOn } from "./owner-faces.js";
|
|
4
4
|
import { mintDurableOwnerKey, mintPerson, partsOf, personOf, scenarioNamed, subjectOf } from "./owner-brands.js";
|
|
5
5
|
import { deletionHeadReadOf } from "./session-incarnation.js";
|
|
6
|
+
import { isSessionKind, sessionKindFaceOf } from "./session-kind.js";
|
|
6
7
|
import { memoryScopeFor } from "./memory-scope.js";
|
|
7
8
|
import { verifyPrincipalJwt } from "./principal-jwt.js";
|
|
9
|
+
import { engineScopeOfOwner } from "./engine-identity.js";
|
|
8
10
|
import { fieldConflictFacts } from "./field-conflict.js";
|
|
9
11
|
import { refusalReservedKeyMessage, refusalReservedKeyOf } from "./http/refusal-body.js";
|
|
10
12
|
import { PRINCIPAL_MAX_BYTES, principalShapeProblem } from "./principal-shape.js";
|
|
@@ -33,6 +35,14 @@ export const ATTACH_ABSENT_MESSAGE = "requireExistingSession: session does not e
|
|
|
33
35
|
function attachAbsentError() {
|
|
34
36
|
return createCodedHttpError(404, "resume.session_not_found", ATTACH_ABSENT_MESSAGE);
|
|
35
37
|
}
|
|
38
|
+
export const SESSION_KIND_MISMATCH_MESSAGE = "this session already exists with a different session kind — a session's kind is written once, when the session is created, and never changes; send the same sessionKind the session was created with, omit sessionKind to run the session as it is, or start a new session";
|
|
39
|
+
function sessionKindMismatch(rowKind) {
|
|
40
|
+
return createCodedHttpError(409, "conflict.session_kind_mismatch", SESSION_KIND_MISMATCH_MESSAGE, rowKind === undefined ? undefined : { sessionKind: rowKind });
|
|
41
|
+
}
|
|
42
|
+
export const SESSION_KIND_UNRECORDABLE_MESSAGE = "sessionKind requires a session store that records a session's kind and ages such sessions out (DB_BACKEND=mysql|pg|local) — this deployment cannot, so the session would be created as a top-level conversation; capabilities.sessionKinds lists the kinds a deployment accepts";
|
|
43
|
+
function sessionKindUnrecordable() {
|
|
44
|
+
return createCodedHttpError(400, "request.precondition_unmet", SESSION_KIND_UNRECORDABLE_MESSAGE);
|
|
45
|
+
}
|
|
36
46
|
export async function sessionOwnerCellOf(store, sessionId, owner) {
|
|
37
47
|
if (owner !== null)
|
|
38
48
|
return ownerCellOf(owner);
|
|
@@ -122,13 +132,25 @@ export function createAuthorizer(config, sessionStore, logger) {
|
|
|
122
132
|
};
|
|
123
133
|
const birthFace = birthFaceOf(sessionStore);
|
|
124
134
|
const withdrawFace = withdrawFaceOf(sessionStore);
|
|
125
|
-
const
|
|
126
|
-
|
|
135
|
+
const kindFace = sessionKindFaceOf(sessionStore);
|
|
136
|
+
const registerNew = async (id, owner, kind, register, onBirth) => {
|
|
137
|
+
if (kind !== undefined && birthFace === undefined)
|
|
138
|
+
throw sessionKindUnrecordable();
|
|
139
|
+
if (birthFace === undefined || (withdrawFace === undefined && kind === undefined))
|
|
127
140
|
return register(id, owner);
|
|
128
|
-
const receipt = await birthFace.registerWithReceipt(id, owner);
|
|
129
|
-
if (receipt.minted !== undefined)
|
|
141
|
+
const receipt = await birthFace.registerWithReceipt(id, owner, kind);
|
|
142
|
+
if (receipt.minted !== undefined && withdrawFace !== undefined)
|
|
130
143
|
onBirth?.(receipt.minted, withdrawFace);
|
|
131
144
|
};
|
|
145
|
+
const judgeKind = async (id, wanted, judged, subject) => {
|
|
146
|
+
if (kindFace === undefined)
|
|
147
|
+
throw sessionKindUnrecordable();
|
|
148
|
+
const reading = await kindFace.sessionKindOf(id);
|
|
149
|
+
if (reading === undefined || judged === undefined || reading.incarnation !== judged.incarnation)
|
|
150
|
+
throw attachRefused("not_visible", subject);
|
|
151
|
+
if (reading.kind !== wanted)
|
|
152
|
+
throw sessionKindMismatch(reading.kind);
|
|
153
|
+
};
|
|
132
154
|
return async ({ req, body, onBirth }) => {
|
|
133
155
|
const subject = verifiedSubject(req, config);
|
|
134
156
|
if (config.requirePrincipal && !subject) {
|
|
@@ -142,6 +164,7 @@ export function createAuthorizer(config, sessionStore, logger) {
|
|
|
142
164
|
projectId = body.projectId.toLowerCase();
|
|
143
165
|
}
|
|
144
166
|
const requireExisting = body.requireExistingSession === true;
|
|
167
|
+
const kind = isSessionKind(body.sessionKind) ? body.sessionKind : undefined;
|
|
145
168
|
const headOf = deletionHeadReadOf(sessionStore);
|
|
146
169
|
let head;
|
|
147
170
|
const readOwner = headOf === undefined ? undefined : async (id) => {
|
|
@@ -159,7 +182,7 @@ export function createAuthorizer(config, sessionStore, logger) {
|
|
|
159
182
|
throw attachRefused("missing", subject);
|
|
160
183
|
}
|
|
161
184
|
if (register) {
|
|
162
|
-
await registerNew(requested, subject ?? null, register, onBirth);
|
|
185
|
+
await registerNew(requested, subject ?? null, kind, register, onBirth);
|
|
163
186
|
owner = await readOwner(requested);
|
|
164
187
|
}
|
|
165
188
|
else if (config.requirePrincipal) {
|
|
@@ -170,11 +193,18 @@ export function createAuthorizer(config, sessionStore, logger) {
|
|
|
170
193
|
const claimCaller = claimCallerOf(subject, config);
|
|
171
194
|
if (!visibleOn("session.attach", qualsOf(claimCaller, await sessionCellFor("session.attach", claimCaller, sessionStore, requested, owner))))
|
|
172
195
|
throw attachRefused("not_visible", subject);
|
|
196
|
+
if (kind !== undefined)
|
|
197
|
+
await judgeKind(requested, kind, head, subject);
|
|
198
|
+
}
|
|
199
|
+
else if (kind !== undefined) {
|
|
200
|
+
throw register ? attachRefused("missing", subject) : sessionKindUnrecordable();
|
|
173
201
|
}
|
|
174
202
|
}
|
|
175
203
|
else if (config.requirePrincipal) {
|
|
176
204
|
throw new HttpError(403, "session reuse needs an owner-aware session store on a multi-tenant deployment: this worker's session store cannot attest who owns a session, so a sessionId cannot be authorized — including one this worker itself minted a moment ago (without a register seam it was never recorded as yours). Configure a durable session backend (SESSION_BACKEND), or omit sessionId on every turn to start fresh.");
|
|
177
205
|
}
|
|
206
|
+
if (!readOwner && kind !== undefined)
|
|
207
|
+
throw sessionKindUnrecordable();
|
|
178
208
|
sessionId = requested;
|
|
179
209
|
}
|
|
180
210
|
else {
|
|
@@ -183,9 +213,13 @@ export function createAuthorizer(config, sessionStore, logger) {
|
|
|
183
213
|
}
|
|
184
214
|
sessionId = uuidv7();
|
|
185
215
|
if (register)
|
|
186
|
-
await registerNew(sessionId, subject ?? null, register, onBirth);
|
|
216
|
+
await registerNew(sessionId, subject ?? null, kind, register, onBirth);
|
|
217
|
+
else if (kind !== undefined)
|
|
218
|
+
throw sessionKindUnrecordable();
|
|
187
219
|
if (readOwner)
|
|
188
220
|
await readOwner(sessionId);
|
|
221
|
+
if (kind !== undefined)
|
|
222
|
+
await judgeKind(sessionId, kind, head, subject);
|
|
189
223
|
}
|
|
190
224
|
return { subject, sessionId, memoryScope: memoryScopeFor(config, subject === undefined ? undefined : personOf(subject), projectId), resolvedProjectId: projectId, ...(head === undefined ? {} : { head }) };
|
|
191
225
|
};
|
|
@@ -223,7 +257,7 @@ export function subjectWidthExceeded(subject) {
|
|
|
223
257
|
export const CHECKPOINT_PUBLIC_SCOPE = "_";
|
|
224
258
|
export const BACKGROUND_REGISTRY_ANON_SCOPE = "default";
|
|
225
259
|
export function backgroundScopesForCheckpointScope(scope) {
|
|
226
|
-
return scope === CHECKPOINT_PUBLIC_SCOPE ? [CHECKPOINT_PUBLIC_SCOPE, BACKGROUND_REGISTRY_ANON_SCOPE] : [scope];
|
|
260
|
+
return scope === CHECKPOINT_PUBLIC_SCOPE ? [CHECKPOINT_PUBLIC_SCOPE, BACKGROUND_REGISTRY_ANON_SCOPE] : [engineScopeOfOwner(scope)];
|
|
227
261
|
}
|
|
228
262
|
export const encodeCheckpointScope = (subject) => subject ?? CHECKPOINT_PUBLIC_SCOPE;
|
|
229
263
|
export const decodeCheckpointScope = (scope) => (scope === CHECKPOINT_PUBLIC_SCOPE ? undefined : mintDurableOwnerKey(scope));
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
* `ADB_VENDOR_KEYS` / `AWS_SECRET_ACCESS_KEY` 一类,实测)。三个继承词只在引擎一处判:
|
|
19
19
|
* · `"all"` = 整份环境 **减** 本进程声明的自有凭据名;`"scrub"`(缺省)= 形状剥 ∪ 该名单;`[names]` = 严格白名单,点到名单中的名 ⇒ 引擎响亮拒
|
|
20
20
|
* (`inheritEnvPolicyProblem`:构造时与 spawn 时两格都拒,拒句带名;本仓不自判 withheld、不留第二读法)。
|
|
21
|
-
* · 名单 =
|
|
21
|
+
* · 名单 = 本包凭据类变量名({@link CREDENTIAL_ENV_NAMES}:配置目录(`config-catalog.ts`)全部 `type:"secret"` 名 ∪ bake-runner 进程自己的凭据名 `BAKE_RUNNER_CREDENTIAL_ENV`
|
|
22
|
+
* —— 目录只装服务进程读的 env,runner 的 bearer 不是目录行)∪ 名单型旋钮名(`env-name-allowlist-knobs.ts`,其原文可能夹着被错展开的令牌)∪ **生效配置
|
|
22
23
|
* 模型条目的 `apiKeyEnv`**(key-resolver 取凭据的那张表 `config.modelApiKeyEnv` 的值 —— 本进程消费的凭据变量名,条目由中心热应用新增 / 改名),
|
|
23
24
|
* **机器派生**、不手抄、不按「归谁消费」切({@link serverWithheldEnvNames} 一处)。声明两个时机、同一只 {@link declareServerWithheldEnv}:起服第一步(三个进程入口:
|
|
24
25
|
* `boot/stage-01-config.ts` / `run-local.ts` / `bake-runner/main.ts`,在任何执行环境构造与 spawn 之前 —— 声明先于构造才有构造时拒;此时没有生效配置 = 空表),
|
|
@@ -29,9 +30,10 @@
|
|
|
29
30
|
* `loadConfig()` 的**声明前提**({@link ownCredentialDeclarationRefusal}:起服表的名没全扣 ⇒ `loadConfig` 抛,拒句点名 {@link declareServerWithheldEnv} —— 「先声明」不再只是入口里的位置契约,
|
|
30
31
|
* 不经入口直接调 `loadConfig` 的进程〔包根嵌入方 / bench / 探针脚本〕得先声明,声明对它们才不是空的)与能力词 `inherit_env.own_credentials_withheld` 在本进程的事实
|
|
31
32
|
* {@link ownCredentialsWithheld}(当前生效配置应声明的名全被扣;活配置经 {@link bindOwnCredentialsConfig} 在 `loadConfig()` 之后绑一次;未绑 / 没扣 ⇒ false)。
|
|
32
|
-
* · **值臂**(core 7.52.0 [ref]):声明是一张表 `{ names, values }`。`values` =
|
|
33
|
-
* 此刻装着的**每一枚**本服务凭据 —— 颗粒按本服务读这只变量的那一只解析器定(
|
|
34
|
-
* `APPROVAL_HMAC_KEYS`
|
|
33
|
+
* · **值臂**(core 7.52.0 [ref]):声明是一张表 `{ names, values }`。`values` = 本包凭据类变量(本包凭据类变量名 ∪ 模型条目 `apiKeyEnv`,{@link serverCredentialValueSources})
|
|
34
|
+
* 此刻装着的**每一枚**本服务凭据 —— 颗粒按本服务读这只变量的那一只解析器定(行的 `credentialForm`:装着凭据值的颗粒整值总在内,`SERVICE_AUTH_TOKENS` 另加每一枚令牌、
|
|
35
|
+
* `APPROVAL_HMAC_KEYS` 另加每一把钥;名单型旋钮的颗粒 `name-list` 是零枚 —— 原文是变量名单,不是凭据;一只变量有几个读者就取几个读法的并集 —— 模型条目的 `apiKeyEnv` 指着它 ⇒
|
|
36
|
+
* key-resolver 把它整值读成一枚,哪怕它是一行名单型旋钮;{@link credentialsHeldBy})—— 引擎按整串比,所以一枚令牌换了个变量名放着与原变量同扣,部分重叠 / 前后缀不同的值不扣。
|
|
35
37
|
* 逐枚交给引擎的同一只判;引擎判「不是凭据值」的那一枚不扣、名照扣、不拒启、点名那个变量一次。能力词 `inherit_env.own_credential_values_withheld` 的事实 = {@link ownCredentialValuesWithheld}(位真 ⇔ 值臂每一枚都真扣)。
|
|
36
38
|
* 「这个变量是不是本服务的凭据」(名是,或值是)只有一只读法 {@link ownCredentialVariable}(判官 = 引擎此刻的声明):名单型旋钮的解析器与声明增长时的重判都问它。
|
|
37
39
|
* · 调用方显式传入的 env(`cfg.env` / 单次命令的 `env` / 沙箱的点名放回)不是继承,照旧原样叠在组合结果之上 —— 那是适配器自己的凭据通道。
|
|
@@ -54,19 +56,19 @@
|
|
|
54
56
|
import { type InheritEnvPolicy, type SecretEnvFinding } from "@sema-agent/core";
|
|
55
57
|
import type { ServiceConfig } from "./config-types.js";
|
|
56
58
|
import { type SecretEnvScrubSite } from "./observability/secret-env-scrub.js";
|
|
57
|
-
/**
|
|
58
|
-
export declare const
|
|
59
|
+
/** 本包凭据类变量名({@link CREDENTIAL_FORM_OF} 的键;排序只为读数稳定)。 */
|
|
60
|
+
export declare const CREDENTIAL_ENV_NAMES: ReadonlySet<string>;
|
|
59
61
|
/** 生效配置模型条目 name → `apiKeyEnv`(变量**名**,值从本进程 env 取)—— `ServiceConfig.modelApiKeyEnv` 的形,key-resolver 读凭据的那张表。 */
|
|
60
62
|
export type ModelApiKeyEnvTable = Readonly<Record<string, string>>;
|
|
61
63
|
/**
|
|
62
|
-
* 本进程的自有凭据名(
|
|
64
|
+
* 本进程的自有凭据名(机器派生,三臂一处:本包凭据类变量名 ∪ 名单型旋钮名 ∪ `modelApiKeyEnv` 表的值;排序只为读数稳定)。纯函数:给哪张表就答哪张表的应声明
|
|
63
65
|
* 集合 —— 声明时给候选表、能力位给活表,同一只派生。名字按原文交引擎(目录臂同形),不在本仓折叠大小写。
|
|
64
66
|
*/
|
|
65
67
|
export declare function serverWithheldEnvNames(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
|
|
66
68
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
69
|
+
* 本进程的**凭据类变量**名:本包凭据类变量名 ∪ 模型条目 `apiKeyEnv` 的值 —— 名单与值臂两臂同一张表派生,只少不在那张表里的名单型旋钮名(今天 = bake-runner 进程的
|
|
70
|
+
* `BAKE_ENV_ALLOW`)。两个读者问同一张:值臂按每只的颗粒读出它此刻装着的凭据值({@link credentialsHeldBy};名单型旋钮的颗粒 `name-list` ⇒ 零枚,名照扣),
|
|
71
|
+
* 请求 `settings.env` 的凭据判据按名拒(`task-settings.ts` `settingsEnvCredentialIssue`)。纯函数,排序只为读数稳定。
|
|
70
72
|
*/
|
|
71
73
|
export declare function serverCredentialValueSources(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
|
|
72
74
|
/**
|