@sema-agent/server 7.150.0 → 7.152.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 +451 -0
- package/README.md +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +144 -87
- package/deploy/sema-up/README.md +11 -4
- 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 +7 -6
- package/deploy/sema-up/kube-up.sh +6 -6
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +12 -14
- package/dist/approval-gate-currency.d.ts +9 -9
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.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 +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +3 -6
- package/dist/bind-host.js +4 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +9 -14
- package/dist/boot/execution-env.js +85 -22
- 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/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +6 -1
- package/dist/boot/reapers.js +13 -2
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +43 -48
- package/dist/boot/runner-deps.d.ts +46 -35
- package/dist/boot/runner-deps.js +94 -91
- 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 +9 -5
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +3 -2
- package/dist/boot/stage-06-runners.d.ts +9 -4
- package/dist/boot/stage-06-runners.js +24 -9
- package/dist/boot/stage-07-capability-layer.d.ts +8 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +8 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +12 -5
- package/dist/boot/stage-09-leader.js +14 -5
- package/dist/boot/stage-10-http-server.d.ts +19 -5
- package/dist/boot/stage-10-http-server.js +14 -21
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +5 -8
- 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/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +43 -32
- package/dist/capability-facts.js +45 -51
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- 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 +26 -22
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +20 -8
- package/dist/config-invariants.js +55 -12
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +38 -42
- package/dist/config.d.ts +58 -7
- package/dist/config.js +90 -40
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- 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 +7 -0
- package/dist/device-ws-hub.js +10 -3
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/elicitation.js +2 -2
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +29 -0
- package/dist/execution-env-refusal.js +8 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- 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 +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +18 -3
- package/dist/host-decision.d.ts +11 -11
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +10 -7
- package/dist/http/checkpoint-ctx.d.ts +4 -0
- package/dist/http/checkpoint-ctx.js +2 -0
- package/dist/http/dispatch.d.ts +8 -3
- package/dist/http/dispatch.js +59 -32
- package/dist/http/durable-run-leg.js +16 -17
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +3 -1
- package/dist/http/owner-access.d.ts +33 -14
- package/dist/http/owner-access.js +40 -10
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +42 -3
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +367 -117
- package/dist/http/route-ctx.d.ts +91 -15
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +5 -1
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +99 -51
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +38 -10
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +171 -65
- package/dist/http/routes/session-sync.d.ts +22 -9
- package/dist/http/routes/session-sync.js +204 -107
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +30 -15
- package/dist/http/routes/tasks.js +46 -41
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +30 -30
- package/dist/http/server.js +16 -4
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +7 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +5 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +2 -2
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +116 -11
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +23 -11
- package/dist/memory-scope.js +18 -6
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +25 -17
- package/dist/observability/fail-open.js +25 -17
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- 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/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +2 -2
- package/dist/parked-decide.d.ts +106 -55
- 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/permission-mode-admission.d.ts +74 -5
- package/dist/permission-mode-admission.js +56 -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 +14 -2
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
- package/dist/plugins/approval-ask-store-memory.js +35 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
- package/dist/plugins/approval-ask-store-sql.js +45 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- 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/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- 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/execution-placement-sql.js +6 -6
- 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 +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- 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-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +104 -80
- package/dist/plugins/one-time-migrations.js +226 -132
- 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 +35 -10
- 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 +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- 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 +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +46 -10
- package/dist/plugins/remote-env-host.js +124 -52
- package/dist/plugins/remote-env-k8s.d.ts +109 -41
- package/dist/plugins/remote-env-k8s.js +160 -54
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- 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.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 +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +5 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- 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/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -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/sql-json-column.d.ts +1 -1
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- 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 +84 -15
- package/dist/plugins/store-backend.js +236 -72
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -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.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +14 -1
- 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 +21 -25
- 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-custody.d.ts +4 -3
- 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/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- 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/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +9 -9
- package/dist/runs.d.ts +54 -16
- package/dist/runs.js +67 -13
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- 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 +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +25 -103
- package/dist/session-sync.js +14 -76
- 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/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
- package/dist/stores-sql/file-history-store-sql.js +205 -95
- 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 +1 -9
- package/dist/stores-sql/retention-store-sql.js +5 -19
- 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 +2 -2
- package/dist/task-settings.d.ts +7 -5
- package/dist/task-settings.js +3 -3
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +465 -507
- package/dist/tool-approval.js +606 -1222
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +571 -178
- package/dist/trace/self-minted-wire.js +189 -56
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
- package/package.json +7 -3
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.151.0.json +762 -0
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
package/dist/config.js
CHANGED
|
@@ -32,11 +32,11 @@ import { MODEL_THINKING_LEVELS, THINKING_LEVELS, THINKING_FORMATS, buildModelCom
|
|
|
32
32
|
import {} from "./posture-source.js";
|
|
33
33
|
import { COST_QUOTA_WINDOW_SEC_RANGE, costQuotaWindowSecInRange } from "./observability/cost-quota.js";
|
|
34
34
|
import { NAME_TABLE_BEHAVIOR, TOOL_NAME_ROSTER, describeUnmatchableRuleName, isRetiredLeftOut, retiredLeftOutEntries, ruleEntryToolName, unmatchableRuleNameOf } from "./namespaced-rule-name.js";
|
|
35
|
-
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, centerIdentityRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal, operatorSingleUserRefusal, remoteConfigProviderUrlRefusal, retentionLaneRefusal, workflowParkDecisionDomainRefusal } from "./config-invariants.js";
|
|
35
|
+
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, centerIdentityRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal, operatorSingleUserRefusal, operatorRosterWellFormedRefusal, remoteConfigProviderUrlRefusal, retentionLaneRefusal, workflowParkDecisionDomainRefusal } from "./config-invariants.js";
|
|
36
36
|
import { declaredSemaConfigDir } from "./sema-config-dir.js";
|
|
37
37
|
import { lkgPathOverrideOf } from "./config-lkg.js";
|
|
38
38
|
import { K8S_WORKSPACE_MOUNT_DEFAULT, WORKSPACE_PERSIST_DEFAULT, WORKSPACE_PERSIST_WORDS, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_RANGE, WORKSPACE_SNAPSHOT_TIMEOUT_MS_DEFAULT, WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE, parseWorkspaceSnapshotExclude, parseWorkspaceSnapshotPrefix } from "./workspace-space.js";
|
|
39
|
-
import { SESSION_SNAPSHOT_BUCKET_DEFAULT, WORKSPACE_SNAPSHOT_BUCKET_DEFAULT } from "./object-store-buckets.js";
|
|
39
|
+
import { S3_PUBLIC_BUCKET_DEFAULT, SENDFILE_PRIVATE_PREFIX, SESSION_SNAPSHOT_BUCKET_DEFAULT, SIGV4_PRESIGN_MAX_SEC, WORKSPACE_SNAPSHOT_BUCKET_DEFAULT, sessionSnapshotPrefixProblem } from "./object-store-buckets.js";
|
|
40
40
|
import { laneLivenessOf } from "./exec-bounds.js";
|
|
41
41
|
import { SANDBOX_IPV6_DEFAULT, SANDBOX_IPV6_WORDS } from "./sandbox-egress-policy.js";
|
|
42
42
|
import { WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_MOUNT_DEFAULT, WORKSPACE_CACHE_MOUNT_RESERVED, WORKSPACE_CACHE_SIZE_DEFAULT, WORKSPACE_CACHE_WORDS, isK8sQuantity, mountsOverlap, reservedMountCollision } from "./workspace-cache.js";
|
|
@@ -46,10 +46,11 @@ import { sandboxForwardedEnvOf } from "./execution-config-root.js";
|
|
|
46
46
|
import { SANDBOX_READ_FLOOR_DEFAULT, SANDBOX_READ_FLOOR_WORDS, laneMissingEnv, readDeclaredLaneTable } from "./execution-lane-caps.js";
|
|
47
47
|
import { MEMORY_ENGINE_BACKENDS, SESSION_BACKENDS, STORE_BACKENDS } from "@sema-agent/settings-schema/execution-lanes";
|
|
48
48
|
import { AUTONOMY_MODES } from "./runtime-governance.js";
|
|
49
|
+
import { CC_RULE_FORM } from "./entry-problems.js";
|
|
49
50
|
import { deploymentRuleRefusal } from "./rule-issue-reading.js";
|
|
50
51
|
import { MAX_NAMED_INERT_ENTRIES, allowLayerEntryCountIssue, describeInertRuleEntries, inertRuleEntriesOf, inertRuleEntryGuidance, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
51
52
|
import { readReadDenyEntry } from "./read-deny-entry.js";
|
|
52
|
-
import { createCenterCredentialSource,
|
|
53
|
+
import { createCenterCredentialSource, credentialOriginOf, readWebAdminCredentialDeclaration } from "./center-credential.js";
|
|
53
54
|
import { parseCenterCredentialRenewLeadMs } from "./center-credential-renewer.js";
|
|
54
55
|
import { catalogBrainLane, modelProviderRefusal } from "./model-provider.js";
|
|
55
56
|
import { modelRouteUrlRefusal } from "./model-route-url.js";
|
|
@@ -408,15 +409,39 @@ function parseDeviceRelayUrlEnv(raw) {
|
|
|
408
409
|
export function entryDeclarableRemoteExec(lane) {
|
|
409
410
|
switch (lane) {
|
|
410
411
|
case "host":
|
|
411
|
-
return {
|
|
412
|
-
provider: "host",
|
|
413
|
-
...(process.env.HOST_WORKSPACE_BASE ? { workspaceBase: process.env.HOST_WORKSPACE_BASE } : {}),
|
|
414
|
-
...((n) => (n !== undefined ? { commandTimeoutMs: n } : {}))(optNumEnvStrict("HOST_COMMAND_TIMEOUT_MS")),
|
|
415
|
-
};
|
|
412
|
+
return { provider: "host", ...parseHostLaneEnv() };
|
|
416
413
|
case "none":
|
|
417
414
|
return { provider: "none" };
|
|
418
415
|
}
|
|
419
416
|
}
|
|
417
|
+
export function parseHostLaneEnv() {
|
|
418
|
+
return {
|
|
419
|
+
...(process.env.HOST_WORKSPACE_BASE ? { workspaceBase: process.env.HOST_WORKSPACE_BASE } : {}),
|
|
420
|
+
...((n) => (n !== undefined ? { commandTimeoutMs: n } : {}))(optNumEnvStrict("HOST_COMMAND_TIMEOUT_MS")),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
export function parseLocalDockerLaneEnv(singleUserTurnkey) {
|
|
424
|
+
return {
|
|
425
|
+
...(process.env.DOCKER_IMAGE ? { image: process.env.DOCKER_IMAGE } : {}),
|
|
426
|
+
...(process.env.DOCKER_MOUNT_PATH ? { mountPath: process.env.DOCKER_MOUNT_PATH } : {}),
|
|
427
|
+
...(process.env.DOCKER_PATH ? { dockerPath: process.env.DOCKER_PATH } : {}),
|
|
428
|
+
...(process.env.DOCKER_HOST ? { dockerHost: process.env.DOCKER_HOST } : {}),
|
|
429
|
+
...(process.env.DOCKER_MEMORY ? { memory: process.env.DOCKER_MEMORY } : {}),
|
|
430
|
+
...((n) => (n !== undefined ? { cpus: n } : {}))(optNumEnvStrict("DOCKER_CPUS")),
|
|
431
|
+
...((n) => (n !== undefined ? { pidsLimit: n } : {}))(optFinitePositiveEnv("DOCKER_PIDS_LIMIT")),
|
|
432
|
+
...(boolEnv("DOCKER_DROP_CAPS", false) ? { dropAllCaps: true } : {}),
|
|
433
|
+
...(process.env.DOCKER_NETWORK
|
|
434
|
+
? { network: enumEnv("DOCKER_NETWORK", "bridge", ["none", "bridge", "host"]) }
|
|
435
|
+
: {}),
|
|
436
|
+
...((n) => (n !== undefined ? { commandTimeoutMs: n } : {}))(optNumEnvStrict("DOCKER_COMMAND_TIMEOUT_MS")),
|
|
437
|
+
...((names) => (names !== undefined ? { env: allowlistedEnv(names, process.env) } : {}))(parseEnvNameAllowlist("DOCKER_SANDBOX_ENV", singleUserTurnkey)),
|
|
438
|
+
...((capacity) => (capacity !== undefined ? { capacity } : {}))(parseLocalDockerCapacityEnv()),
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
export const FILE_LANE_CELL_ENV = {
|
|
442
|
+
host: { workspaceBase: "HOST_WORKSPACE_BASE", commandTimeoutMs: "HOST_COMMAND_TIMEOUT_MS" },
|
|
443
|
+
"local-docker": { image: "DOCKER_IMAGE", mountPath: "DOCKER_MOUNT_PATH", memory: "DOCKER_MEMORY", cpus: "DOCKER_CPUS", network: "DOCKER_NETWORK" },
|
|
444
|
+
};
|
|
420
445
|
const envNamesNoLane = (raw) => raw === undefined || raw === "";
|
|
421
446
|
function declaredExecutionLane(raw) {
|
|
422
447
|
if (envNamesNoLane(raw))
|
|
@@ -470,6 +495,41 @@ function parseDeviceTrustedProxyCidrsEnv(raw) {
|
|
|
470
495
|
`(e.g. 10.0.0.0/8,fd00::/8); unset it to read no proxy header at all (the cap is then keyed on the socket peer).`);
|
|
471
496
|
});
|
|
472
497
|
}
|
|
498
|
+
function sessionSnapshotPrefixKnob(prefix) {
|
|
499
|
+
const problem = sessionSnapshotPrefixProblem(prefix);
|
|
500
|
+
if (problem !== undefined)
|
|
501
|
+
throw new Error(`SESSION_SNAPSHOT_PREFIX=${JSON.stringify(prefix)} is refused: ${problem} — give each engine on the bucket a prefix that does not end in a domain segment (e.g. "engine-a/")`);
|
|
502
|
+
return prefix;
|
|
503
|
+
}
|
|
504
|
+
function presignLifetimeKnob(knob, sec, alternative) {
|
|
505
|
+
if (sec > SIGV4_PRESIGN_MAX_SEC) {
|
|
506
|
+
throw new Error(`${knob}=${sec} is longer than a presigned URL can live (at most ${SIGV4_PRESIGN_MAX_SEC} s (7 days)) — set ${knob} to at most ${SIGV4_PRESIGN_MAX_SEC}${alternative ? `, ${alternative}` : ""}`);
|
|
507
|
+
}
|
|
508
|
+
return sec;
|
|
509
|
+
}
|
|
510
|
+
function presignLifetimeSpelled(knob, raw, legal, alternative) {
|
|
511
|
+
const spelled = raw?.trim() ?? "";
|
|
512
|
+
if (spelled === "")
|
|
513
|
+
return undefined;
|
|
514
|
+
if (!/^(0|[1-9]\d*)$/.test(spelled)) {
|
|
515
|
+
const shown = raw.length > 40 ? `${raw.slice(0, 40)}…` : raw;
|
|
516
|
+
throw new Error(`${knob}=${JSON.stringify(shown)} is not ${legal}`);
|
|
517
|
+
}
|
|
518
|
+
return presignLifetimeKnob(knob, Number(spelled), alternative);
|
|
519
|
+
}
|
|
520
|
+
function sendUserFileUrlTtlKnob(raw) {
|
|
521
|
+
return (presignLifetimeSpelled("SEND_USER_FILE_URL_TTL", raw, `a link lifetime — set 0 (or leave it unset) for a permanent public link, or a whole number of seconds from 1 to ${SIGV4_PRESIGN_MAX_SEC} (7 days) for a private presigned link that expires`, "or 0 for a permanent link") ?? 0);
|
|
522
|
+
}
|
|
523
|
+
function sessionSnapshotTtlKnob(raw) {
|
|
524
|
+
const sec = presignLifetimeSpelled("SESSION_SNAPSHOT_TTL_SEC", raw, `a presigned-URL lifetime — leave it unset for the default, or set a whole number of seconds from 1 to ${SIGV4_PRESIGN_MAX_SEC} (7 days) in decimal digits`);
|
|
525
|
+
if (sec !== 0)
|
|
526
|
+
return sec;
|
|
527
|
+
CONFIG_WARNINGS.push({ env: "SESSION_SNAPSHOT_TTL_SEC", raw: raw });
|
|
528
|
+
return undefined;
|
|
529
|
+
}
|
|
530
|
+
function workspaceSnapshotTtlKnob(raw) {
|
|
531
|
+
return presignLifetimeSpelled("WORKSPACE_SNAPSHOT_TTL_SEC", raw, `a presigned-URL lifetime — leave it unset (or 0) for the default, or set a whole number of seconds from 1 to ${SIGV4_PRESIGN_MAX_SEC} (7 days) in decimal digits`);
|
|
532
|
+
}
|
|
473
533
|
function parseFileHistoryRetention() {
|
|
474
534
|
const raw = process.env.FILE_HISTORY_RETENTION_KEEP;
|
|
475
535
|
if (raw === undefined || raw === "")
|
|
@@ -1012,8 +1072,8 @@ function parseStoreDomain(ctx) {
|
|
|
1012
1072
|
accessKey: process.env.MINIO_ACCESS_KEY,
|
|
1013
1073
|
secretKey: process.env.MINIO_SECRET_KEY,
|
|
1014
1074
|
...(process.env.MINIO_REGION ? { region: process.env.MINIO_REGION } : {}),
|
|
1015
|
-
...(process.env.SESSION_SNAPSHOT_PREFIX ? { keyPrefix: process.env.SESSION_SNAPSHOT_PREFIX } : {}),
|
|
1016
|
-
...((ttl) => (ttl !== undefined ? { presignTtlSec: ttl } : {}))(
|
|
1075
|
+
...(process.env.SESSION_SNAPSHOT_PREFIX ? { keyPrefix: sessionSnapshotPrefixKnob(process.env.SESSION_SNAPSHOT_PREFIX) } : {}),
|
|
1076
|
+
...((ttl) => (ttl !== undefined ? { presignTtlSec: ttl } : {}))(sessionSnapshotTtlKnob(process.env.SESSION_SNAPSHOT_TTL_SEC)),
|
|
1017
1077
|
}
|
|
1018
1078
|
: undefined,
|
|
1019
1079
|
snapshotBlobSqlMaxBytes: optFinitePositiveEnv("SNAPSHOT_BLOB_SQL_MAX_BYTES"),
|
|
@@ -1026,14 +1086,14 @@ function parseStoreDomain(ctx) {
|
|
|
1026
1086
|
...(process.env.S3_PUBLIC_ENDPOINT || process.env.S3_ENDPOINT
|
|
1027
1087
|
? { publicEndpoint: (process.env.S3_PUBLIC_ENDPOINT || process.env.S3_ENDPOINT) }
|
|
1028
1088
|
: {}),
|
|
1029
|
-
publicBucket: process.env.S3_PUBLIC_BUCKET ??
|
|
1089
|
+
publicBucket: process.env.S3_PUBLIC_BUCKET ?? S3_PUBLIC_BUCKET_DEFAULT,
|
|
1030
1090
|
privateBucket: process.env.SESSION_SNAPSHOT_BUCKET ?? SESSION_SNAPSHOT_BUCKET_DEFAULT,
|
|
1031
|
-
privateKeyPrefix:
|
|
1091
|
+
privateKeyPrefix: SENDFILE_PRIVATE_PREFIX,
|
|
1032
1092
|
...(process.env.SEND_USER_FILE_SANDBOX_PUT_ENDPOINT ? { sandboxPutEndpoint: process.env.SEND_USER_FILE_SANDBOX_PUT_ENDPOINT } : {}),
|
|
1033
1093
|
accessKey: process.env.MINIO_ACCESS_KEY,
|
|
1034
1094
|
secretKey: process.env.MINIO_SECRET_KEY,
|
|
1035
1095
|
...(process.env.MINIO_REGION ? { region: process.env.MINIO_REGION } : {}),
|
|
1036
|
-
defaultTtlSec: (
|
|
1096
|
+
defaultTtlSec: sendUserFileUrlTtlKnob(process.env.SEND_USER_FILE_URL_TTL),
|
|
1037
1097
|
}
|
|
1038
1098
|
: undefined,
|
|
1039
1099
|
};
|
|
@@ -1339,7 +1399,7 @@ function findUnmatchableToolNames(names, opts) {
|
|
|
1339
1399
|
if (opts.consumer === "tool-name-table") {
|
|
1340
1400
|
const ccGuidance = ccRuleFormGuidance(name);
|
|
1341
1401
|
if (ccGuidance !== undefined) {
|
|
1342
|
-
out.push({ name, guidance: ccGuidance, reason:
|
|
1402
|
+
out.push({ name, guidance: ccGuidance, reason: CC_RULE_FORM });
|
|
1343
1403
|
continue;
|
|
1344
1404
|
}
|
|
1345
1405
|
}
|
|
@@ -1395,7 +1455,6 @@ export function approvalGrantRefusal(names) {
|
|
|
1395
1455
|
}
|
|
1396
1456
|
function streamApprovalConfig(gates) {
|
|
1397
1457
|
const cfg = {
|
|
1398
|
-
enabled: boolEnv("STREAM_APPROVAL_ENABLED", true),
|
|
1399
1458
|
windowMs: numEnv("STREAM_ASK_WINDOW_MS", gates.windowMsSource === "posture" ? "86400000" : "300000"),
|
|
1400
1459
|
replayMax: numEnv("STREAM_APPROVAL_REPLAY_MAX", "50"),
|
|
1401
1460
|
admitMaxPerTask: numEnv("STREAM_APPROVAL_ADMIT_MAX_PER_TASK", "32"),
|
|
@@ -1419,7 +1478,7 @@ function streamApprovalConfig(gates) {
|
|
|
1419
1478
|
if (cfg.windowMs + cfg.adhocGraceMs >= cfg.orphanTtlMs) {
|
|
1420
1479
|
throw new Error(`env STREAM_ASK_WINDOW_MS=${cfg.windowMs} + STREAM_APPROVAL_ADHOC_GRACE_MS=${cfg.adhocGraceMs} must be STRICTLY LESS than STREAM_APPROVAL_ORPHAN_TTL_MS=${cfg.orphanTtlMs} — the adhoc arm fires at (createdAt + window + grace) while the orphan backstop fires at (createdAt + ttl); if the backstop wins, every adhoc-leg row is attributed "orphan_ttl_exceeded" instead of "adhoc_leg_no_durable_domain" (attribution honesty, design/172 §6.1)`);
|
|
1421
1480
|
}
|
|
1422
|
-
const suspendedRowsPossible =
|
|
1481
|
+
const suspendedRowsPossible = gates.toolApprovalEnabled && gates.unattendedPolicy !== "deny";
|
|
1423
1482
|
if (suspendedRowsPossible && cfg.unreachedTtlMs + cfg.adhocGraceMs >= cfg.orphanTtlMs) {
|
|
1424
1483
|
throw new Error(`env UNREACHED_ASK_TTL_MS=${cfg.unreachedTtlMs} + STREAM_APPROVAL_ADHOC_GRACE_MS=${cfg.adhocGraceMs} must be STRICTLY LESS than STREAM_APPROVAL_ORPHAN_TTL_MS=${cfg.orphanTtlMs} — an ask minted with NO live stream (case A: a workflow child ask) waits UNREACHED_ASK_TTL_MS, so its row expires at (createdAt + that window); the orphan backstop fires at (createdAt + ttl). If the backstop wins, every suspended row is attributed "orphan_ttl_exceeded" instead of its real cause (attribution honesty, same rule as the STREAM_ASK_WINDOW_MS line above)`);
|
|
1425
1484
|
}
|
|
@@ -1997,7 +2056,6 @@ function parseAuthDomain(ctx) {
|
|
|
1997
2056
|
const authTokens = parseServiceAuthTokens(process.env.SERVICE_AUTH_TOKENS);
|
|
1998
2057
|
return {
|
|
1999
2058
|
bindHost: process.env.BIND_HOST || undefined,
|
|
2000
|
-
bindHostSource: process.env.BIND_HOST ? "BIND_HOST" : undefined,
|
|
2001
2059
|
authToken: process.env.SERVICE_AUTH_TOKEN,
|
|
2002
2060
|
authTokens,
|
|
2003
2061
|
allowUnauthedWrites: boolEnv("ALLOW_UNAUTHED_WRITES", false),
|
|
@@ -2007,6 +2065,7 @@ function parseAuthDomain(ctx) {
|
|
|
2007
2065
|
autonomy: parseAutonomy(process.env.AUTONOMY),
|
|
2008
2066
|
...parseGovernanceDeclarations(),
|
|
2009
2067
|
operatorPrincipals: csv("OPERATOR_PRINCIPALS"),
|
|
2068
|
+
operatorDrainPrincipals: csv("OPERATOR_DRAIN_PRINCIPALS"),
|
|
2010
2069
|
operatorSingleUser: boolEnv("OPERATOR_SINGLE_USER", false),
|
|
2011
2070
|
serviceTokenActsForDeployment: boolEnv("SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT", true),
|
|
2012
2071
|
configCatalogEnabled: boolEnv("CONFIG_CATALOG_ENABLED", true),
|
|
@@ -2127,23 +2186,8 @@ function parseOrchestrationDomain(ctx) {
|
|
|
2127
2186
|
? entryDeclarableRemoteExec(declaredLane)
|
|
2128
2187
|
:
|
|
2129
2188
|
declaredLane === "local-docker" && process.env.DOCKER_IMAGE
|
|
2130
|
-
?
|
|
2131
|
-
provider: "local-docker",
|
|
2132
|
-
image: process.env.DOCKER_IMAGE,
|
|
2133
|
-
...(process.env.DOCKER_MOUNT_PATH ? { mountPath: process.env.DOCKER_MOUNT_PATH } : {}),
|
|
2134
|
-
...(process.env.DOCKER_PATH ? { dockerPath: process.env.DOCKER_PATH } : {}),
|
|
2135
|
-
...(process.env.DOCKER_HOST ? { dockerHost: process.env.DOCKER_HOST } : {}),
|
|
2136
|
-
...(process.env.DOCKER_MEMORY ? { memory: process.env.DOCKER_MEMORY } : {}),
|
|
2137
|
-
...((n) => (n !== undefined ? { cpus: n } : {}))(optNumEnvStrict("DOCKER_CPUS")),
|
|
2138
|
-
...((n) => (n !== undefined ? { pidsLimit: n } : {}))(optFinitePositiveEnv("DOCKER_PIDS_LIMIT")),
|
|
2139
|
-
...(boolEnv("DOCKER_DROP_CAPS", false) ? { dropAllCaps: true } : {}),
|
|
2140
|
-
...(process.env.DOCKER_NETWORK
|
|
2141
|
-
? { network: enumEnv("DOCKER_NETWORK", "bridge", ["none", "bridge", "host"]) }
|
|
2142
|
-
: {}),
|
|
2143
|
-
...((n) => (n !== undefined ? { commandTimeoutMs: n } : {}))(optNumEnvStrict("DOCKER_COMMAND_TIMEOUT_MS")),
|
|
2144
|
-
...((names) => (names !== undefined ? { env: allowlistedEnv(names, process.env) } : {}))(parseEnvNameAllowlist("DOCKER_SANDBOX_ENV", singleUserTurnkey)),
|
|
2145
|
-
...((capacity) => (capacity !== undefined ? { capacity } : {}))(parseLocalDockerCapacityEnv()),
|
|
2146
|
-
}
|
|
2189
|
+
?
|
|
2190
|
+
{ provider: "local-docker", ...parseLocalDockerLaneEnv(singleUserTurnkey), image: process.env.DOCKER_IMAGE }
|
|
2147
2191
|
:
|
|
2148
2192
|
declaredLane === "device"
|
|
2149
2193
|
? {
|
|
@@ -2488,12 +2532,14 @@ function parseCenterBaseUrl(name, raw, role) {
|
|
|
2488
2532
|
}
|
|
2489
2533
|
function parseWebAdmin(baseUrl, requirePrincipal, liveBaseUrl, webBaseUrl) {
|
|
2490
2534
|
const worker = process.env[WEB_ADMIN_ENV.worker] || undefined;
|
|
2491
|
-
const declared =
|
|
2535
|
+
const declared = readWebAdminCredentialDeclaration("access");
|
|
2536
|
+
const assertion = credentialOriginOf(readWebAdminCredentialDeclaration("assertion"));
|
|
2492
2537
|
return {
|
|
2493
2538
|
baseUrl,
|
|
2494
2539
|
...(liveBaseUrl !== undefined ? { liveBaseUrl } : {}),
|
|
2495
2540
|
...(webBaseUrl !== undefined ? { webBaseUrl } : {}),
|
|
2496
2541
|
credential: createCenterCredentialSource(declared.from === "file" ? { ...declared, multiTenant: requirePrincipal } : declared, worker),
|
|
2542
|
+
...(assertion.from !== "absent" ? { assertionToken: assertion } : {}),
|
|
2497
2543
|
dryRun: boolEnv(WEB_ADMIN_ENV.dryRun, false),
|
|
2498
2544
|
worker,
|
|
2499
2545
|
};
|
|
@@ -2651,8 +2697,8 @@ const MEMORY_GROUP_KEYS = [
|
|
|
2651
2697
|
const AUTH_GROUP_KEYS = [
|
|
2652
2698
|
"authToken", "authTokens", "allowUnauthedWrites", "corsOrigins", "principalHeader", "requirePrincipal", "autonomy",
|
|
2653
2699
|
"commandPolicy", "compliancePosture", "lockedConfigKeys", "retentionPolicy", "retentionSweep",
|
|
2654
|
-
"operatorPrincipals", "operatorSingleUser", "serviceTokenActsForDeployment", "configCatalogEnabled", "principalJwtPubkeys", "principalJwtIss", "principalJwtAud",
|
|
2655
|
-
"principalJwtMaxTtlSec", "authBridgeIssuer", "bindHost",
|
|
2700
|
+
"operatorPrincipals", "operatorDrainPrincipals", "operatorSingleUser", "serviceTokenActsForDeployment", "configCatalogEnabled", "principalJwtPubkeys", "principalJwtIss", "principalJwtAud",
|
|
2701
|
+
"principalJwtMaxTtlSec", "authBridgeIssuer", "bindHost",
|
|
2656
2702
|
];
|
|
2657
2703
|
const ORCHESTRATION_GROUP_KEYS = [
|
|
2658
2704
|
"sandboxGit", "remoteExec", "remoteExecHomeDir", "worktreeIsolation", "leaderEnabled", "leaderFanoutEnabled", "routerEnabled", "selfOrchestrationEnabled",
|
|
@@ -2750,7 +2796,7 @@ function k8sWorkspaceStore() {
|
|
|
2750
2796
|
secretKey,
|
|
2751
2797
|
...(process.env.MINIO_REGION ? { region: process.env.MINIO_REGION } : {}),
|
|
2752
2798
|
...(keyPrefix !== undefined ? { keyPrefix } : {}),
|
|
2753
|
-
...((n) => (n !== undefined ? { presignTtlSec: n } : {}))(
|
|
2799
|
+
...((n) => (n !== undefined ? { presignTtlSec: n } : {}))(workspaceSnapshotTtlKnob(process.env.WORKSPACE_SNAPSHOT_TTL_SEC)),
|
|
2754
2800
|
},
|
|
2755
2801
|
};
|
|
2756
2802
|
}
|
|
@@ -2825,7 +2871,7 @@ export function loadConfig() {
|
|
|
2825
2871
|
throw new Error(retentionRefusal);
|
|
2826
2872
|
}
|
|
2827
2873
|
const { directApprovalDoor, durableApproval: dgDurable, approvalHmacKeys: dgHmacKeys } = approval;
|
|
2828
|
-
const { principalJwtPubkeys, principalJwtIss, principalJwtAud, operatorPrincipals: dgOperators, operatorSingleUser, authTokens } = auth;
|
|
2874
|
+
const { principalJwtPubkeys, principalJwtIss, principalJwtAud, operatorPrincipals: dgOperators, operatorDrainPrincipals, operatorSingleUser, authTokens } = auth;
|
|
2829
2875
|
const directDoorActive = directApprovalDoor && dgDurable && dgHmacKeys.length > 0 && principalJwtPubkeys.length > 0 && !!principalJwtIss && !!principalJwtAud;
|
|
2830
2876
|
const doorRefusal = halfOpenDirectDoorRefusal({
|
|
2831
2877
|
directApprovalDoor,
|
|
@@ -2844,10 +2890,14 @@ export function loadConfig() {
|
|
|
2844
2890
|
if (operatorsRefusal !== undefined) {
|
|
2845
2891
|
throw new Error(operatorsRefusal);
|
|
2846
2892
|
}
|
|
2847
|
-
const singleUserOperatorRefusal = operatorSingleUserRefusal({ operatorSingleUser, requirePrincipal, operatorPrincipals: dgOperators });
|
|
2893
|
+
const singleUserOperatorRefusal = operatorSingleUserRefusal({ operatorSingleUser, requirePrincipal, operatorPrincipals: dgOperators, operatorDrainPrincipals });
|
|
2848
2894
|
if (singleUserOperatorRefusal !== undefined) {
|
|
2849
2895
|
throw new Error(singleUserOperatorRefusal);
|
|
2850
2896
|
}
|
|
2897
|
+
const rosterRefusal = operatorRosterWellFormedRefusal({ operatorPrincipals: dgOperators, operatorDrainPrincipals });
|
|
2898
|
+
if (rosterRefusal !== undefined) {
|
|
2899
|
+
throw new Error(rosterRefusal);
|
|
2900
|
+
}
|
|
2851
2901
|
const bakeOperatorsRefusal = bakeOperatorPrincipalsRefusal({ imageBakes: orchestration.imageBakes, operatorPrincipals: dgOperators });
|
|
2852
2902
|
if (bakeOperatorsRefusal !== undefined) {
|
|
2853
2903
|
throw new Error(bakeOperatorsRefusal);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Server } from "node:http";
|
|
2
|
+
/** 开不了口的原因词(闭集;`listening` 行的 `controlSocketUnavailable` 取值;顺序 = 开口序)。 */
|
|
3
|
+
export declare const CONTROL_SOCKET_UNAVAILABLE_REASONS: readonly ["unsupported_platform", "data_root_not_exclusive", "path_too_long", "dir_not_private", "path_occupied", "bind_failed"];
|
|
4
|
+
export type ControlSocketUnavailableReason = (typeof CONTROL_SOCKET_UNAVAILABLE_REASONS)[number];
|
|
5
|
+
/** 开口的结局:在听(绝对路径)或缺席(原因词)—— 恰一形。 */
|
|
6
|
+
export type ControlSocketOpening = {
|
|
7
|
+
readonly listening: true;
|
|
8
|
+
readonly path: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly listening: false;
|
|
11
|
+
readonly reason: ControlSocketUnavailableReason;
|
|
12
|
+
};
|
|
13
|
+
/** 数据根(锁所守的物理路径)→ 控制 socket 的绝对路径。唯一推导:`listening` 行报的、开口判的、附着方连的是同一只。 */
|
|
14
|
+
export declare function controlSocketPathOf(physicalDataRoot: string): string;
|
|
15
|
+
/** 私有判的读数(`lstat`,不跟符号链接)。`absent` = 不在;`unreadable` = 读不出(按不私有处置)。 */
|
|
16
|
+
export type ControlPathReading = {
|
|
17
|
+
readonly kind: "absent";
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "unreadable";
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "directory" | "socket" | "symlink" | "other";
|
|
22
|
+
readonly uid: number;
|
|
23
|
+
readonly mode: number;
|
|
24
|
+
};
|
|
25
|
+
/** 读一只路径(`lstat`)。不在 ⇒ `absent`;别的读错 ⇒ `unreadable`。 */
|
|
26
|
+
export declare function readControlPath(path: string): ControlPathReading;
|
|
27
|
+
/** `control/` 私有吗:是目录(不是符号链接)∧ 属主 = `euid` ∧ 无组 / 他人位。任何别的读数 ⇒ 否。 */
|
|
28
|
+
export declare function controlDirIsPrivate(reading: ControlPathReading, euid: number): boolean;
|
|
29
|
+
/** `engine.sock` 是不是本用户的 socket:是 socket(不是符号链接)∧ 属主 = `euid`。任何别的读数 ⇒ 否。 */
|
|
30
|
+
export declare function controlSocketIsOwned(reading: ControlPathReading, euid: number): boolean;
|
|
31
|
+
export interface ControlSocketOpenOptions {
|
|
32
|
+
/** 本进程持锁独占的物理数据根(`StoreBackend.exclusiveDataRoot()`);缺席 ⇒ 不开口。 */
|
|
33
|
+
readonly exclusiveDataRoot: string | undefined;
|
|
34
|
+
/** 平台读数(缺省 = 全仓唯一平台读点 `HOST_PLATFORM`)。 */
|
|
35
|
+
readonly platform?: string;
|
|
36
|
+
/** 属主判对照的 euid(缺省 `process.geteuid()`)。 */
|
|
37
|
+
readonly euid?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 在 `server`(控制口那只 `http.Server`,`createHttpServer` 交出的 `controlSocketServer`)上开控制 socket —— 判序见头注。
|
|
41
|
+
* 结局恰一形;`listening: false` 时 `server` 不在听(绑上又判不过的那一形已先关)。调用点:TCP listen 成功之后、`listening` 行之前(起服第 10 段)。
|
|
42
|
+
*/
|
|
43
|
+
export declare function openControlSocket(server: Server, opts: ControlSocketOpenOptions): Promise<ControlSocketOpening>;
|
|
44
|
+
/** `listening` 行的两键 —— 同一次开口结局的投影,恰一键在场(`controlSocket` ⟺ 在听;`controlSocketUnavailable` ⟺ 缺席)。 */
|
|
45
|
+
export interface ControlSocketLineKeys {
|
|
46
|
+
readonly controlSocket?: string;
|
|
47
|
+
readonly controlSocketUnavailable?: ControlSocketUnavailableReason;
|
|
48
|
+
}
|
|
49
|
+
/** 开口结局 → `listening` 行两键(唯一投影)。 */
|
|
50
|
+
export declare function controlSocketLineKeysOf(opening: ControlSocketOpening): ControlSocketLineKeys;
|
|
51
|
+
//# sourceMappingURL=control-socket.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { lstatSync, unlinkSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { ensureDir } from "@sema-agent/core";
|
|
4
|
+
import { HOST_PLATFORM } from "./plugins/host-platform.js";
|
|
5
|
+
export const CONTROL_SOCKET_UNAVAILABLE_REASONS = ["unsupported_platform", "data_root_not_exclusive", "path_too_long", "dir_not_private", "path_occupied", "bind_failed"];
|
|
6
|
+
const SUN_PATH_MAX_BYTES = {
|
|
7
|
+
darwin: 104,
|
|
8
|
+
linux: 107,
|
|
9
|
+
aix: "unsupported",
|
|
10
|
+
android: "unsupported",
|
|
11
|
+
freebsd: "unsupported",
|
|
12
|
+
haiku: "unsupported",
|
|
13
|
+
openbsd: "unsupported",
|
|
14
|
+
sunos: "unsupported",
|
|
15
|
+
win32: "unsupported",
|
|
16
|
+
cygwin: "unsupported",
|
|
17
|
+
netbsd: "unsupported",
|
|
18
|
+
};
|
|
19
|
+
export function controlSocketPathOf(physicalDataRoot) {
|
|
20
|
+
return join(physicalDataRoot, "control", "engine.sock");
|
|
21
|
+
}
|
|
22
|
+
function readingOf(stats) {
|
|
23
|
+
const kind = stats.isSymbolicLink() ? "symlink" : stats.isDirectory() ? "directory" : stats.isSocket() ? "socket" : "other";
|
|
24
|
+
return { kind, uid: stats.uid, mode: stats.mode };
|
|
25
|
+
}
|
|
26
|
+
export function readControlPath(path) {
|
|
27
|
+
try {
|
|
28
|
+
return readingOf(lstatSync(path));
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return err.code === "ENOENT" ? { kind: "absent" } : { kind: "unreadable" };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function controlDirIsPrivate(reading, euid) {
|
|
35
|
+
return reading.kind === "directory" && reading.uid === euid && (reading.mode & 0o077) === 0;
|
|
36
|
+
}
|
|
37
|
+
export function controlSocketIsOwned(reading, euid) {
|
|
38
|
+
return reading.kind === "socket" && reading.uid === euid;
|
|
39
|
+
}
|
|
40
|
+
function sunPathMaxBytesOf(platform) {
|
|
41
|
+
if (!Object.hasOwn(SUN_PATH_MAX_BYTES, platform))
|
|
42
|
+
return undefined;
|
|
43
|
+
const limit = SUN_PATH_MAX_BYTES[platform];
|
|
44
|
+
return typeof limit === "number" ? limit : undefined;
|
|
45
|
+
}
|
|
46
|
+
const unavailable = (reason) => ({ listening: false, reason });
|
|
47
|
+
async function ioStep(act) {
|
|
48
|
+
try {
|
|
49
|
+
await act();
|
|
50
|
+
return { ok: true };
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return { ok: false, error };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function listenOn(server, path) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const onError = (err) => reject(err);
|
|
59
|
+
server.once("error", onError);
|
|
60
|
+
server.listen(path, () => {
|
|
61
|
+
server.removeListener("error", onError);
|
|
62
|
+
resolve();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export async function openControlSocket(server, opts) {
|
|
67
|
+
const maxBytes = sunPathMaxBytesOf(opts.platform ?? HOST_PLATFORM);
|
|
68
|
+
if (maxBytes === undefined)
|
|
69
|
+
return unavailable("unsupported_platform");
|
|
70
|
+
const euid = opts.euid ?? process.geteuid?.();
|
|
71
|
+
if (euid === undefined)
|
|
72
|
+
return unavailable("unsupported_platform");
|
|
73
|
+
const root = opts.exclusiveDataRoot;
|
|
74
|
+
if (root === undefined)
|
|
75
|
+
return unavailable("data_root_not_exclusive");
|
|
76
|
+
const path = controlSocketPathOf(root);
|
|
77
|
+
if (Buffer.byteLength(path, "utf8") > maxBytes)
|
|
78
|
+
return unavailable("path_too_long");
|
|
79
|
+
const dir = dirname(path);
|
|
80
|
+
await ioStep(() => ensureDir(dir));
|
|
81
|
+
if (!controlDirIsPrivate(readControlPath(dir), euid))
|
|
82
|
+
return unavailable("dir_not_private");
|
|
83
|
+
const existing = readControlPath(path);
|
|
84
|
+
switch (existing.kind) {
|
|
85
|
+
case "absent":
|
|
86
|
+
break;
|
|
87
|
+
case "socket":
|
|
88
|
+
if (!controlSocketIsOwned(existing, euid))
|
|
89
|
+
return unavailable("path_occupied");
|
|
90
|
+
if (!(await ioStep(() => unlinkSync(path))).ok)
|
|
91
|
+
return unavailable("bind_failed");
|
|
92
|
+
break;
|
|
93
|
+
case "directory":
|
|
94
|
+
case "symlink":
|
|
95
|
+
case "other":
|
|
96
|
+
return unavailable("path_occupied");
|
|
97
|
+
case "unreadable":
|
|
98
|
+
return unavailable("bind_failed");
|
|
99
|
+
default: {
|
|
100
|
+
const unknownReading = existing;
|
|
101
|
+
throw new Error(`control socket: unknown path reading ${JSON.stringify(unknownReading)}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!(await ioStep(() => listenOn(server, path))).ok)
|
|
105
|
+
return unavailable("bind_failed");
|
|
106
|
+
if (!controlSocketIsOwned(readControlPath(path), euid) || !controlDirIsPrivate(readControlPath(dir), euid)) {
|
|
107
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
108
|
+
return unavailable("bind_failed");
|
|
109
|
+
}
|
|
110
|
+
return { listening: true, path };
|
|
111
|
+
}
|
|
112
|
+
export function controlSocketLineKeysOf(opening) {
|
|
113
|
+
return opening.listening ? { controlSocket: opening.path } : { controlSocketUnavailable: opening.reason };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=control-socket.js.map
|
|
@@ -64,7 +64,8 @@ export interface PathAdjudication {
|
|
|
64
64
|
* · `durable` —— checkpoint suspend/resume 服 ask(HTTP 腿 durable 开、park 赎回腿)。core 的问答策略
|
|
65
65
|
* (`createDurableQuestionPolicy()`,原形逐字)**只**叠在这一形上:它对引擎的问题工具答 `ask`,落点归 core 的同步优先
|
|
66
66
|
* (有问题席 ⇒ 先投卡、席在窗内拿到答即交答;没拿到 ⇒ 停驻 —— 卡由活面呈出而窗走完的那一问除外:席抛,引擎的投递失败臂不停驻)。
|
|
67
|
-
* · `live` —— Runner 的活 onAsk 席当场服 ask(run-local 的 `createLocalApprover`:TTY 问 y/N / 无 TTY 当场拒;
|
|
67
|
+
* · `live` —— Runner 的活 onAsk 席当场服 ask(run-local 的 `createLocalApprover`:TTY 问 y/N / 无 TTY 当场拒;leader 车道不耐久的腿
|
|
68
|
+
* (`leader/leader.ts` `leaderLegDurability` 判为不耐久:各修复腿、没递停驻设施或续跑上下文没落的 worker)的无人值守层:答集内的类按策略答,其余交回 core 的缺席路 —— 这条腿没有停驻设施 ⇒ 拒;
|
|
68
69
|
* core `isLiveApproverSeat(onAsk)` 为真时 `suspendAsk` 早退,ask 落回调)。三张名单与 durable 席**同一只**策略。
|
|
69
70
|
* · `absent` —— 没有谁服 ask ⇒ adjudicated allow-all;**只**服务零名单(HTTP 腿「durable 关 ∧ 单用户零意图」)。
|
|
70
71
|
* 带名单进来 = 响亮拒:名单被一条没有席的腿静默吞掉,正是 [ref] 的病形。
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* `holds` 的入参型 = 所声明轴读入形的交叉({@link DeploymentShapeInput}),所以调用方递完整 `ServiceConfig` 或只递那几键的窄形都行。
|
|
18
18
|
*
|
|
19
19
|
* ## 什么进表、什么不进
|
|
20
|
-
* 进表的是**形规则**:只由部署形事实决定的布尔(去重后
|
|
20
|
+
* 进表的是**形规则**:只由部署形事实决定的布尔(去重后 16 行;同一条规则的多个消费者读同一行,不各成一行)。
|
|
21
21
|
* 把一行与**非形事实**(锁键、合规档位、审批意图、请求身份、请求体)合取的能力判据是**消费者**,住在它自己的模块
|
|
22
22
|
* (`mcpInjectionHonored` = 锁 ∧ 合规 ∧ `!multiTenant`;`taskHooksHonored`;身份门 …),读行、不读原始键。
|
|
23
23
|
* 车道表(`execution-lane-caps.ts`)按车道词键控的布尔列(`laneIsolated` 等)是车道轴自己的事实表,不是「部署」的谓词;行读它们。
|
|
@@ -111,6 +111,14 @@ export declare const DEPLOYMENT_SHAPE_PREDICATES: Readonly<{
|
|
|
111
111
|
* 一次性迁移 M48 的输入(`plugins/store-backend.ts`:有边界 ⇒ 不改写哨兵属主)。
|
|
112
112
|
*/
|
|
113
113
|
identityBoundary: DeploymentShapePredicate<"principal" | "identity">;
|
|
114
|
+
/**
|
|
115
|
+
* 「这台部署接没接**过凭据门**的来源」的问法 —— 身份来源律 5(`identity-source.ts` 头注)在部署上的投影:配置接了的来源里有凭据门认的那一类
|
|
116
|
+
* (service 凭据,或鉴权桥 issuer —— 含中心回退;`passesCredentialGate` 那一列)。**不是** {@link DEPLOYMENT_SHAPE_PREDICATES.identityBoundary}:
|
|
117
|
+
* 那一行把 `REQUIRE_PRINCIPAL` / 只读 trace 凭据 / 直连门也算作边界(它们让主体头不再是 dev-open 的自报),本行只问「有没有一类凭据过得了门」——
|
|
118
|
+
* 三样都不过,所以只配其中之一的部署两行答案相反,这是两问,不是一问两答。没接 ⇒ 写门(问请求)对每一次请求都拒(`ALLOW_UNAUTHED_WRITES` 之外)。
|
|
119
|
+
* 读者:记忆整理阀门的启动期告警(`boot/stage-06-runners.ts`;「这台部署上 run 口对谁都开不了」)。请求面不读本行:写门问的是请求。
|
|
120
|
+
*/
|
|
121
|
+
credentialGateSource: DeploymentShapePredicate<"identity">;
|
|
114
122
|
/**
|
|
115
123
|
* 租户轴的问法。今天与 {@link DEPLOYMENT_SHAPE_PREDICATES.principalRequired} 读**同一个声明**([ref] ①:托管 / 多租 ⇔ `REQUIRE_PRINCIPAL=true`,
|
|
116
124
|
* 签发方配置是身份验签轴、不算租户证据)—— 两个问题、一根轴、一个读口;「鉴权必需」与「多租形」拆成两个声明时只改这一行的判官。
|
package/dist/deployment-shape.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { capabilitiesFor, executionLaneCaps, executionLaneOf, handsOnWorkerFilePlane, laneWiresExecutionEnv } from "./execution-lane-caps.js";
|
|
2
|
-
import { configuredIdentitySources } from "./identity-source.js";
|
|
2
|
+
import { configuredIdentitySources, passesCredentialGate } from "./identity-source.js";
|
|
3
3
|
function readPrincipalAxis(deployment) {
|
|
4
4
|
return { declared: deployment.requirePrincipal === true };
|
|
5
5
|
}
|
|
@@ -54,6 +54,7 @@ const VM_ISOLATION_RUNTIME_CLASSES = new Set(["kata", "kata-qemu", "kata-clh", "
|
|
|
54
54
|
export const DEPLOYMENT_SHAPE_PREDICATES = Object.freeze({
|
|
55
55
|
principalRequired: createPredicate(["principal"], "身份轴:运维声明了 REQUIRE_PRINCIPAL=true —— 每个调用方都必须带一个验过的主体。", ({ principal }) => principal.declared),
|
|
56
56
|
identityBoundary: createPredicate(["principal", "identity"], "身份轴:这台部署有身份边界 —— 声明了 REQUIRE_PRINCIPAL,或配置接了任一已验身份来源(service 凭据 / 鉴权桥 / 直连门),或声明了只读 trace 凭据。", ({ principal, identity }) => principal.declared || identity.sources.length > 0 || identity.traceTokenDeclared),
|
|
57
|
+
credentialGateSource: createPredicate(["identity"], "身份轴:这台部署接了一类过凭据门的来源 —— service 凭据,或鉴权桥(登录令牌);只开 REQUIRE_PRINCIPAL / 只配 trace 凭据 / 只开直连门都不算。", ({ identity }) => identity.sources.some(passesCredentialGate)),
|
|
57
58
|
multiTenant: createPredicate(["principal"], "租户轴:这台部署服务不止一个主人(托管 / 多租;C-R100 ① 由 REQUIRE_PRINCIPAL=true 声明)。", ({ principal }) => principal.declared),
|
|
58
59
|
callerCwd: createPredicate(["lane", "principal"], "车道 × 租户 / 设备归属:调用方送来的 cwd(与 settings.env)被尊重 —— host 车道且单主,或 device 车道。", ({ lane, principal }) => lane.caps !== undefined && capabilityHolds(lane.caps.callerCwd, principal)),
|
|
59
60
|
callerOwnsWorkerDisk: createPredicate(["lane", "principal"], "车道 × 租户:手就在本 worker 的盘上且部署只有一个主人 —— 这块盘上的路径就是调用方自己的。", ({ lane, principal }) => lane.lane !== undefined && handsOnWorkerFilePlane(lane.lane) && !principal.declared),
|
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 为什么是精选而不是把 `device-ws-protocol.ts` 整只暴露:那个模块里还有**服务端**自己的半场(帧解析与准入、
|
|
9
9
|
* 验签、各种铸 id)。把它们变成公开面,等于替实现细节背上 semver。这里只再导出 executor **会用到**的:
|
|
10
|
-
*
|
|
11
|
-
* (`DEVICE_OUTCOME_ERROR_CODES_BY_REVISION` + 取集函数 `deviceOutcomeErrorCodesAt`:executor 按自己声明的修订号裁剪会发的词)
|
|
10
|
+
* 闭集常量、两向帧型、构造握手签名字节所需的两只纯函数,以及三份「随协议修订号走」的事实:结局码按修订号分行的增量表
|
|
11
|
+
* (`DEVICE_OUTCOME_ERROR_CODES_BY_REVISION` + 取集函数 `deviceOutcomeErrorCodesAt`:executor 按自己声明的修订号裁剪会发的词)、指令 kind 按修订号分行的增量表
|
|
12
|
+
* (`DEVICE_INSTRUCTION_KINDS_BY_REVISION` + 取集函数 `deviceInstructionKindsAt`:executor 按自己声明的修订号裁剪 `hello.supports` —— 高于它的 kind 声明了也不会下发)与
|
|
12
13
|
* helloAck 数值位的界表(`DEVICE_HELLO_ACK_BOUNDS` + 判据 `deviceHelloAckNumberFlaw`:executor 读到越界值 ⇒ 协议违例)。要加名字 = 改这只文件 + 同批改
|
|
13
14
|
* `test/device-protocol-subpath.test.ts` 的闭集(新增公开面必须是一次有意的动作)。
|
|
14
15
|
*/
|
|
15
|
-
export { DEVICE_WS_PATH, DEVICE_PROTOCOL_VERSION, DEVICE_MIN_PROTOCOL_VERSION, DEVICE_HELLO_DOMAIN_TAG, DEVICE_WS_LIMITS, DEVICE_FRAME_TYPES, DEVICE_SERVER_FRAME_TYPES, DEVICE_HELLO_REJECT_CODES, DEVICE_BYE_REASONS, DEVICE_GOODBYE_REASONS, DEVICE_CHUNK_KINDS, DEVICE_CANCEL_STATES, DEVICE_INSTRUCTION_KINDS, DEVICE_OUTCOME_ERROR_CODES, DEVICE_OUTCOME_ERROR_CODES_BY_REVISION, DEVICE_HELLO_ACK_BOUNDS, buildHelloSignaturePayload, decodeUlid16, deviceOutcomeErrorCodesAt, deviceHelloAckNumberFlaw, } from "./device-ws-protocol.js";
|
|
16
|
-
export type { DeviceFrameType, DeviceServerFrameType, DeviceHelloRejectCode, DeviceByeReason, DeviceGoodbyeReason, DeviceChunkKind, DeviceCancelState, DeviceInstructionKind, DeviceOutcomeErrorCode, DeviceProtocolRevision, DeviceHelloAckNumericField, WireFileInfo, WireWriteExpectation, DeviceInstructionOutcome, DeviceInstructionArgsByKind, DeviceChallengeFrame, DeviceHelloAckFrame, DeviceHelloRejectFrame, DeviceInstructionFrame, DevicePayloadFrame, DeviceServerFrame, DeviceHelloFrame, DeviceFrame, DeviceResultFrame, DeviceChunkFrame, DeviceGoodbyeFrame, DeviceHeartbeatFrame, } from "./device-ws-protocol.js";
|
|
16
|
+
export { DEVICE_WS_PATH, DEVICE_PROTOCOL_VERSION, DEVICE_MIN_PROTOCOL_VERSION, DEVICE_HELLO_DOMAIN_TAG, DEVICE_WS_LIMITS, DEVICE_FRAME_TYPES, DEVICE_SERVER_FRAME_TYPES, DEVICE_HELLO_REJECT_CODES, DEVICE_BYE_REASONS, DEVICE_GOODBYE_REASONS, DEVICE_CHUNK_KINDS, DEVICE_CANCEL_STATES, DEVICE_INSTRUCTION_KINDS, DEVICE_INSTRUCTION_KINDS_BY_REVISION, DEVICE_BOUND_READ_OPS, DEVICE_OUTCOME_ERROR_CODES, DEVICE_OUTCOME_ERROR_CODES_BY_REVISION, DEVICE_HELLO_ACK_BOUNDS, buildHelloSignaturePayload, decodeUlid16, deviceOutcomeErrorCodesAt, deviceInstructionKindsAt, deviceHelloAckNumberFlaw, } from "./device-ws-protocol.js";
|
|
17
|
+
export type { DeviceFrameType, DeviceServerFrameType, DeviceHelloRejectCode, DeviceByeReason, DeviceGoodbyeReason, DeviceChunkKind, DeviceCancelState, DeviceInstructionKind, DeviceBoundReadOp, DeviceOutcomeErrorCode, DeviceProtocolRevision, DeviceHelloAckNumericField, WireFileInfo, WireWriteExpectation, DeviceInstructionOutcome, DeviceInstructionArgsByKind, DeviceChallengeFrame, DeviceHelloAckFrame, DeviceHelloRejectFrame, DeviceInstructionFrame, DevicePayloadFrame, DeviceServerFrame, DeviceHelloFrame, DeviceFrame, DeviceResultFrame, DeviceChunkFrame, DeviceGoodbyeFrame, DeviceHeartbeatFrame, } from "./device-ws-protocol.js";
|
|
17
18
|
//# sourceMappingURL=device-protocol.d.ts.map
|
package/dist/device-protocol.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { DEVICE_WS_PATH, DEVICE_PROTOCOL_VERSION, DEVICE_MIN_PROTOCOL_VERSION, DEVICE_HELLO_DOMAIN_TAG, DEVICE_WS_LIMITS, DEVICE_FRAME_TYPES, DEVICE_SERVER_FRAME_TYPES, DEVICE_HELLO_REJECT_CODES, DEVICE_BYE_REASONS, DEVICE_GOODBYE_REASONS, DEVICE_CHUNK_KINDS, DEVICE_CANCEL_STATES, DEVICE_INSTRUCTION_KINDS, DEVICE_OUTCOME_ERROR_CODES, DEVICE_OUTCOME_ERROR_CODES_BY_REVISION, DEVICE_HELLO_ACK_BOUNDS, buildHelloSignaturePayload, decodeUlid16, deviceOutcomeErrorCodesAt, deviceHelloAckNumberFlaw, } from "./device-ws-protocol.js";
|
|
1
|
+
export { DEVICE_WS_PATH, DEVICE_PROTOCOL_VERSION, DEVICE_MIN_PROTOCOL_VERSION, DEVICE_HELLO_DOMAIN_TAG, DEVICE_WS_LIMITS, DEVICE_FRAME_TYPES, DEVICE_SERVER_FRAME_TYPES, DEVICE_HELLO_REJECT_CODES, DEVICE_BYE_REASONS, DEVICE_GOODBYE_REASONS, DEVICE_CHUNK_KINDS, DEVICE_CANCEL_STATES, DEVICE_INSTRUCTION_KINDS, DEVICE_INSTRUCTION_KINDS_BY_REVISION, DEVICE_BOUND_READ_OPS, DEVICE_OUTCOME_ERROR_CODES, DEVICE_OUTCOME_ERROR_CODES_BY_REVISION, DEVICE_HELLO_ACK_BOUNDS, buildHelloSignaturePayload, decodeUlid16, deviceOutcomeErrorCodesAt, deviceInstructionKindsAt, deviceHelloAckNumberFlaw, } from "./device-ws-protocol.js";
|
|
2
2
|
//# sourceMappingURL=device-protocol.js.map
|
package/dist/device-ws-hub.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ import { type DeviceOwner, type DeviceStore } from "./device-store.js";
|
|
|
40
40
|
import type { DeviceEnrollment, DeviceRejection } from "./device-enrollment.js";
|
|
41
41
|
import { type CidrSet } from "./net-address.js";
|
|
42
42
|
import { type DeviceChunkKind, type DeviceInstructionArgsByKind, type DeviceInstructionKind, type DeviceInstructionOutcome } from "./device-ws-protocol.js";
|
|
43
|
+
import type { NonPersonTier } from "./operator-roster.js";
|
|
43
44
|
/** 交给调用方的一片上行流(`data` 已从 base64 解回字节)。 */
|
|
44
45
|
export interface DeviceChunkDelivery {
|
|
45
46
|
streamSeq: number;
|
|
@@ -129,6 +130,12 @@ export interface DeviceWsHubOptions {
|
|
|
129
130
|
enrollment: DeviceEnrollment;
|
|
130
131
|
/** 本副本 id(写进连接租约行,跨副本排障用)。 */
|
|
131
132
|
replicaId: string;
|
|
133
|
+
/**
|
|
134
|
+
* hello 准入的属主圈禁读者:这一台设备行的属主此刻落在名册的哪一档**非人档**(圈禁,`undefined` = 不圈禁)。答「是」⇒ `helloReject: auth_failed`,不夺租约、不顶替旧连接。
|
|
135
|
+
* 汇聚端自己不 import 名册、不判档位:判官只有一只(`http/principal-gate.ts` 的 `confinedTierOf`,设备读点 `deviceOwnerConfinedTier`),装配方(`boot/device-lane.ts`)把它连进来。
|
|
136
|
+
* **必填**:可选会让漏接静默(没接 = 不圈禁,安全轴上的静默放宽)—— 漏接编译红。每次 hello 现读(名册是现态,不拍快照);读者抛 ⇒ 握手失败、连接关(`device_hello_failed`),不放行。
|
|
137
|
+
*/
|
|
138
|
+
ownerConfinedTier: (owner: DeviceOwner) => NonPersonTier | undefined;
|
|
132
139
|
logger?: DeviceWsHubLogger;
|
|
133
140
|
metrics?: {
|
|
134
141
|
inc(name: string, labels?: Record<string, string>): void;
|
package/dist/device-ws-hub.js
CHANGED
|
@@ -5,7 +5,7 @@ import { WebSocketServer } from "ws";
|
|
|
5
5
|
import { DEVICE_DRAINING_CODE, DEVICE_ERROR_CODES, DEVICE_ERROR_STATUS, assertDeviceIdShape, } from "./device-store.js";
|
|
6
6
|
import { MAX_TIMER_DELAY_MS } from "./config-types.js";
|
|
7
7
|
import { canonicalAddress, createTrustedProxySet } from "./net-address.js";
|
|
8
|
-
import { DEVICE_HELLO_ACK_BOUNDS, DEVICE_MIN_PROTOCOL_VERSION, DEVICE_WS_LIMITS, DEVICE_WS_PATH, DEVICE_PROTOCOL_VERSION,
|
|
8
|
+
import { DEVICE_HELLO_ACK_BOUNDS, DEVICE_MIN_PROTOCOL_VERSION, DEVICE_WS_LIMITS, DEVICE_WS_PATH, DEVICE_PROTOCOL_VERSION, asInstructionKindAt, buildHelloSignaturePayload, deviceHelloAckNumberFlaw, deviceProtocolRevisionRefusal, formatGeneration, mintChallengeNonce, mintInstructionId, parseDeviceFrameText, verifyHelloSignature, } from "./device-ws-protocol.js";
|
|
9
9
|
const OUTCOME_UNKNOWN_SENTENCE = "outcome unknown — the command may have already executed on the device; verify its effect before re-running";
|
|
10
10
|
const SETTLED_MEMO_MAX = 512;
|
|
11
11
|
const DRAIN_RETRY_AFTER_SEC = 15;
|
|
@@ -66,6 +66,7 @@ const ALLOWED_SUCCESS_OUTCOME_KINDS = {
|
|
|
66
66
|
remove: ["void"],
|
|
67
67
|
createTempDir: ["write"],
|
|
68
68
|
createTempFile: ["write"],
|
|
69
|
+
openBound: ["stat", "read"],
|
|
69
70
|
};
|
|
70
71
|
const HELLO_ACK_FIELD_SOURCES = {
|
|
71
72
|
heartbeatIntervalMs: "option heartbeatIntervalMs",
|
|
@@ -120,7 +121,7 @@ function forwardedHopAddress(hop) {
|
|
|
120
121
|
return canonicalAddress(t);
|
|
121
122
|
}
|
|
122
123
|
export function createDeviceWsHub(options) {
|
|
123
|
-
const { store, enrollment, replicaId, logger, metrics } = options;
|
|
124
|
+
const { store, enrollment, replicaId, ownerConfinedTier, logger, metrics } = options;
|
|
124
125
|
const heartbeatIntervalMs = options.heartbeatIntervalMs ?? 15_000;
|
|
125
126
|
const heartbeatMisses = options.heartbeatMisses ?? 3;
|
|
126
127
|
const leaseSeconds = options.leaseSeconds ?? 45;
|
|
@@ -437,6 +438,12 @@ export function createDeviceWsHub(options) {
|
|
|
437
438
|
}
|
|
438
439
|
if (row.status === "revoked")
|
|
439
440
|
return rejectHello(conn, "revoked");
|
|
441
|
+
const confined = ownerConfinedTier(row.owner);
|
|
442
|
+
if (confined !== undefined) {
|
|
443
|
+
logger?.warn("device_hello_owner_confined", { deviceId: row.deviceId, tier: confined });
|
|
444
|
+
metrics?.inc("device_hello_rejected_total", { code: "auth_failed" });
|
|
445
|
+
return rejectHello(conn, "auth_failed");
|
|
446
|
+
}
|
|
440
447
|
const existing = conns.get(row.deviceId);
|
|
441
448
|
if (existing && existing !== conn) {
|
|
442
449
|
const fresh = Date.now() - existing.lastFrameAt < heartbeatIntervalMs * heartbeatMisses;
|
|
@@ -500,7 +507,7 @@ export function createDeviceWsHub(options) {
|
|
|
500
507
|
conn.workspaceRoot = frame.workspaceRoot;
|
|
501
508
|
const supported = new Set();
|
|
502
509
|
for (const s of frame.supports) {
|
|
503
|
-
const k =
|
|
510
|
+
const k = asInstructionKindAt(s, frame.protocolVersion);
|
|
504
511
|
if (k !== null)
|
|
505
512
|
supported.add(k);
|
|
506
513
|
}
|