@sema-agent/server 7.145.0 → 7.147.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 +876 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +374 -99
- package/deploy/facts/CHANGES.json +25 -0
- package/deploy/facts/README.md +57 -0
- package/deploy/facts/lanes.json +61 -0
- package/deploy/facts/lanes.schema.json +57 -0
- package/deploy/facts/sandbox-rbac.json +113 -0
- package/deploy/facts/sandbox-rbac.schema.json +74 -0
- package/deploy/facts/sealed-key.json +9 -0
- package/deploy/facts/sealed-key.schema.json +52 -0
- package/deploy/sema-up/README.md +2 -2
- package/deploy/sema-up/chart/templates/_helpers.tpl +41 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +9 -4
- package/deploy/sema-up/chart/templates/server.yaml +9 -4
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +2 -1
- package/deploy/sema-up/lib/flagshape.sh +4 -0
- package/deploy/sema-up/lib/lanes.json +2 -5
- package/deploy/sema-up/sema-up.sh +12 -9
- package/deploy/sema-up/stack/compose.yaml +5 -4
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +34 -17
- package/dist/adoption/import-limits.d.ts +6 -0
- package/dist/adoption/import-limits.js +7 -0
- package/dist/adoption/import.d.ts +62 -0
- package/dist/adoption/import.js +107 -0
- package/dist/adoption/wire.d.ts +52 -0
- package/dist/adoption/wire.js +9 -0
- package/dist/approval-ask-machine.d.ts +2 -2
- package/dist/approval-card.d.ts +7 -16
- package/dist/approval-card.js +0 -4
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-gate-currency.js +1 -1
- package/dist/approval-reconciler.d.ts +1 -1
- package/dist/approval.d.ts +3 -3
- package/dist/audit.js +2 -2
- package/dist/bench/s1/live-deps.js +3 -1
- package/dist/boot/crash-last.js +2 -1
- package/dist/boot/deployment-mods.d.ts +11 -1
- package/dist/boot/deployment-mods.js +15 -2
- package/dist/boot/device-lane.js +7 -5
- package/dist/boot/engine-lease.d.ts +195 -22
- package/dist/boot/engine-lease.js +146 -20
- package/dist/boot/execution-env.d.ts +5 -0
- package/dist/boot/execution-env.js +57 -33
- package/dist/boot/execution-lane.d.ts +37 -9
- package/dist/boot/execution-lane.js +74 -20
- package/dist/boot/exit-boundary.d.ts +50 -0
- package/dist/boot/exit-boundary.js +32 -0
- package/dist/boot/exit-last.d.ts +20 -4
- package/dist/boot/exit-last.js +23 -5
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/governance-seams.js +1 -0
- package/dist/boot/leader.js +1 -1
- package/dist/boot/memory-boundary.d.ts +11 -11
- package/dist/boot/memory-boundary.js +3 -3
- package/dist/boot/memory-consolidation.d.ts +42 -41
- package/dist/boot/memory-consolidation.js +26 -28
- package/dist/boot/org-memory.js +3 -2
- package/dist/boot/parked-revive-gate.d.ts +1 -1
- package/dist/boot/parked-revive-gate.js +1 -1
- package/dist/boot/reapers.d.ts +12 -4
- package/dist/boot/reapers.js +40 -16
- package/dist/boot/resolve-spec.d.ts +2 -0
- package/dist/boot/resolve-spec.js +126 -123
- package/dist/boot/retention-lane.d.ts +4 -42
- package/dist/boot/runner-deps.js +1 -1
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +11 -3
- package/dist/boot/shutdown.js +27 -9
- package/dist/boot/stage-01-config.d.ts +1 -1
- package/dist/boot/stage-01-config.js +7 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
- package/dist/boot/stage-02-web-admin-pull.js +10 -8
- package/dist/boot/stage-03-store-backend.d.ts +2 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +2 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -1
- package/dist/boot/stage-05-execution-env.js +6 -6
- package/dist/boot/stage-06-runners.d.ts +5 -2
- package/dist/boot/stage-06-runners.js +12 -13
- package/dist/boot/stage-07-capability-layer.d.ts +5 -2
- package/dist/boot/stage-07-capability-layer.js +7 -7
- package/dist/boot/stage-08-reapers.d.ts +5 -2
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +6 -2
- package/dist/boot/stage-10-http-server.d.ts +6 -2
- package/dist/boot/stage-10-http-server.js +5 -3
- package/dist/boot/stores.d.ts +10 -0
- package/dist/boot/stores.js +53 -26
- package/dist/boot/web-admin.js +3 -3
- package/dist/boot/workflow-orchestration.d.ts +1 -1
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/capabilities/center-plugins.d.ts +2 -0
- package/dist/capabilities/center-plugins.js +6 -2
- package/dist/capabilities/composite-members.d.ts +4 -1
- package/dist/capabilities/composite-members.js +4 -1
- package/dist/capabilities/execution-lane.d.ts +7 -7
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +1 -1
- package/dist/capabilities/scenarios.d.ts +34 -20
- package/dist/capabilities/scenarios.js +13 -9
- package/dist/capabilities/settings-contract.d.ts +29 -0
- package/dist/capabilities/settings-contract.js +14 -0
- package/dist/capabilities/skills.d.ts +5 -5
- package/dist/capability-facts.d.ts +56 -1
- package/dist/capability-facts.js +59 -8
- package/dist/center-credential-renewer.js +3 -2
- package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
- package/dist/config-catalog.js +19 -9
- package/dist/config-invariants.d.ts +18 -3
- package/dist/config-invariants.js +36 -19
- package/dist/config-lkg.d.ts +1 -1
- package/dist/config-lkg.js +5 -6
- package/dist/config-provider.d.ts +2 -2
- package/dist/config-provider.js +2 -0
- package/dist/config-types.d.ts +228 -185
- package/dist/config.d.ts +74 -6
- package/dist/config.js +146 -64
- package/dist/degenerate-instrument.js +1 -1
- package/dist/deleted-session-ids.d.ts +19 -0
- package/dist/deleted-session-ids.js +26 -0
- package/dist/deploy-facts.d.ts +155 -0
- package/dist/deploy-facts.js +95 -0
- package/dist/deployment-shape.d.ts +21 -12
- package/dist/deployment-shape.js +24 -6
- package/dist/device-ws-hub.d.ts +48 -3
- package/dist/device-ws-hub.js +48 -2
- package/dist/env-facts.d.ts +7 -5
- package/dist/env-facts.js +10 -6
- package/dist/error-code-family.d.ts +35 -0
- package/dist/error-code-family.js +26 -0
- package/dist/execution-config-root.d.ts +5 -5
- package/dist/execution-config-root.js +5 -5
- package/dist/execution-env-purpose.d.ts +14 -0
- package/dist/execution-env-purpose.js +29 -0
- package/dist/execution-lane-caps.d.ts +49 -86
- package/dist/execution-lane-caps.js +52 -62
- package/dist/execution-placement.d.ts +18 -2
- package/dist/execution-placement.js +19 -0
- package/dist/file-history-disclosure.d.ts +2 -2
- package/dist/fleet/drain-entry.d.ts +46 -3
- package/dist/fleet/drain-entry.js +6 -0
- package/dist/fleet/fleet-bus.d.ts +2 -1
- package/dist/fleet/serving-lease.js +3 -4
- package/dist/history-anchor.d.ts +22 -0
- package/dist/history-anchor.js +14 -0
- package/dist/hooks/branch-transcript.d.ts +1 -1
- package/dist/hooks/branch-transcript.js +1 -0
- package/dist/hooks/classic-stations.d.ts +25 -8
- package/dist/hooks/classic-stations.js +29 -3
- package/dist/hooks/command-spawn.d.ts +1 -4
- package/dist/hooks/command-spawn.js +0 -11
- package/dist/hooks/hook-runner.d.ts +85 -24
- package/dist/hooks/hook-runner.js +326 -109
- package/dist/hooks/hook-source.d.ts +14 -2
- package/dist/hooks/hook-source.js +8 -0
- package/dist/http/active-run-conflict.d.ts +1 -1
- package/dist/http/active-run-conflict.js +1 -1
- package/dist/http/admission.js +11 -1
- package/dist/http/approval-sweeps.d.ts +2 -5
- package/dist/http/approval-sweeps.js +3 -2
- package/dist/http/checkpoint-ctx.d.ts +76 -71
- package/dist/http/checkpoint-ctx.js +40 -40
- package/dist/http/claim-latency.d.ts +10 -0
- package/dist/http/claim-latency.js +12 -0
- package/dist/http/dispatch.js +19 -3
- package/dist/http/durable-run-leg.d.ts +5 -0
- package/dist/http/durable-run-leg.js +3 -1
- package/dist/http/execution-context.d.ts +7 -1
- package/dist/http/execution-context.js +13 -0
- package/dist/http/health-self-report.d.ts +6 -2
- package/dist/http/health-self-report.js +3 -2
- package/dist/http/memory-compliance-failure-reply.d.ts +2 -2
- package/dist/http/memory-compliance-failure-reply.js +5 -15
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
- package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
- package/dist/http/memory-store-refusal-reply.d.ts +3 -3
- package/dist/http/memory-store-refusal-reply.js +3 -0
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +7 -4
- package/dist/http/principal-gate.d.ts +28 -16
- package/dist/http/principal-gate.js +10 -19
- package/dist/http/request-guards.d.ts +2 -2
- package/dist/http/request-guards.js +5 -5
- package/dist/http/resume-legs.d.ts +29 -10
- package/dist/http/resume-legs.js +94 -56
- package/dist/http/rewind-files-reply.d.ts +34 -0
- package/dist/http/rewind-files-reply.js +36 -0
- package/dist/http/route-ctx.d.ts +43 -26
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/adoption.d.ts +11 -0
- package/dist/http/routes/adoption.js +80 -6
- package/dist/http/routes/agents-roster.js +1 -0
- package/dist/http/routes/approvals-assistant.js +7 -26
- package/dist/http/routes/background.js +1 -0
- package/dist/http/routes/capabilities.js +12 -3
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +9 -14
- package/dist/http/routes/diagnostics.js +10 -20
- package/dist/http/routes/engine.d.ts +31 -0
- package/dist/http/routes/engine.js +81 -0
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-consolidation.js +3 -5
- package/dist/http/routes/memory-origin.d.ts +2 -2
- package/dist/http/routes/memory-origin.js +2 -4
- package/dist/http/routes/memory-policy.js +5 -1
- package/dist/http/routes/notify-wake.js +2 -1
- package/dist/http/routes/observability.js +3 -6
- package/dist/http/routes/projects.d.ts +70 -0
- package/dist/http/routes/projects.js +86 -0
- package/dist/http/routes/rules.js +30 -2
- package/dist/http/routes/runs.js +15 -11
- package/dist/http/routes/session-sync.js +39 -35
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +7 -1
- package/dist/http/routes/sessions.js +108 -2
- package/dist/http/routes/tasks.js +32 -8
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/run-concurrency-cap.d.ts +86 -0
- package/dist/http/run-concurrency-cap.js +54 -0
- package/dist/http/server.d.ts +31 -14
- package/dist/http/server.js +29 -3
- package/dist/http/stored-body-replay.d.ts +12 -7
- package/dist/http/stored-body-replay.js +28 -5
- package/dist/http/wire-types.d.ts +27 -13
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/instruction-source-notice.d.ts +1 -1
- package/dist/json-body-limit.d.ts +8 -0
- package/dist/json-body-limit.js +2 -0
- package/dist/leader/diffout.d.ts +1 -1
- package/dist/local-data-root.d.ts +2 -2
- package/dist/memory-embedder-reembed.d.ts +38 -0
- package/dist/memory-embedder-reembed.js +20 -0
- package/dist/memory-incident-sink.d.ts +0 -28
- package/dist/memory-incident-sink.js +5 -0
- package/dist/memory-operator-faces.d.ts +9 -4
- package/dist/memory-scope-stores.d.ts +9 -7
- package/dist/memory-scope-stores.js +3 -14
- package/dist/memory-scope.d.ts +38 -2
- package/dist/memory-scope.js +33 -2
- package/dist/memory-store-refusal.d.ts +17 -4
- package/dist/memory-store-refusal.js +1 -1
- package/dist/memory-sync-client.d.ts +2 -0
- package/dist/memory-sync-client.js +13 -11
- package/dist/memory-sync.js +1 -1
- package/dist/model-compat.d.ts +35 -21
- package/dist/model-compat.js +49 -21
- package/dist/model-entry-refusal.d.ts +11 -1
- package/dist/model-entry-refusal.js +7 -0
- package/dist/namespaced-rule-name.d.ts +18 -1
- package/dist/namespaced-rule-name.js +12 -0
- package/dist/net-address.d.ts +53 -0
- package/dist/net-address.js +111 -0
- package/dist/observability/fail-open.d.ts +29 -17
- package/dist/observability/fail-open.js +29 -17
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.js +2 -0
- package/dist/observability/secret-env-scrub.d.ts +30 -4
- package/dist/observability/secret-env-scrub.js +15 -3
- package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
- package/dist/orchestration/workflow-agent-session-index.js +1 -6
- package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
- package/dist/orchestration/workflow-completion-inbox.js +63 -45
- package/dist/orchestration/workflow-notify-journal.js +2 -3
- package/dist/org-delivery-gate.js +1 -1
- package/dist/org-memory-admission.d.ts +5 -2
- package/dist/org-memory-admission.js +25 -10
- package/dist/parked-decide.d.ts +33 -26
- package/dist/parked-decide.js +36 -44
- package/dist/peer-directory.d.ts +6 -12
- package/dist/peer-directory.js +5 -1
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +37 -4
- package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
- package/dist/plugins/approval-ask-store-memory.js +11 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
- package/dist/plugins/approval-ask-store-sql.js +3 -1
- package/dist/plugins/blob-backend.d.ts +38 -195
- package/dist/plugins/blob-backend.js +33 -229
- package/dist/plugins/caching-session-store.d.ts +12 -5
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
- package/dist/plugins/checkpoint-index-columns.js +3 -2
- package/dist/plugins/checkpoint-store-face.d.ts +426 -0
- package/dist/plugins/checkpoint-store-face.js +152 -0
- package/dist/plugins/device-store-sql.d.ts +2 -2
- package/dist/plugins/device-store-sql.js +5 -10
- package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
- package/dist/plugins/execution-lane-rename-m40.js +10 -0
- package/dist/plugins/execution-placement-sql.d.ts +63 -88
- package/dist/plugins/execution-placement-sql.js +94 -54
- package/dist/plugins/file-run-store.d.ts +26 -18
- package/dist/plugins/file-run-store.js +64 -75
- package/dist/plugins/fork-routing-session-store.d.ts +6 -2
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/imported-layer-root-retirement.d.ts +22 -11
- package/dist/plugins/imported-layer-root-retirement.js +4 -8
- package/dist/plugins/inbox-payload-column.d.ts +14 -0
- package/dist/plugins/inbox-payload-column.js +13 -0
- package/dist/plugins/local-checkpoint-store.d.ts +7 -2
- package/dist/plugins/local-checkpoint-store.js +13 -8
- package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
- package/dist/plugins/local-data-dir-modes-m39.js +182 -0
- package/dist/plugins/local-engine-high-water.d.ts +11 -0
- package/dist/plugins/local-engine-high-water.js +59 -0
- package/dist/plugins/local-session-store.d.ts +119 -30
- package/dist/plugins/local-session-store.js +156 -53
- package/dist/plugins/local-task-attachment-store.d.ts +2 -0
- package/dist/plugins/local-task-attachment-store.js +10 -11
- package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
- package/dist/plugins/memory-embedder-fingerprint.js +52 -12
- package/dist/plugins/memory-embedder.d.ts +1 -1
- package/dist/plugins/memory-embedder.js +2 -2
- package/dist/plugins/memory-engine-pg.d.ts +30 -6
- package/dist/plugins/memory-engine-pg.js +96 -214
- package/dist/plugins/memory-engine-sql-apply.d.ts +130 -0
- package/dist/plugins/memory-engine-sql-apply.js +358 -0
- package/dist/plugins/memory-engine-tidb.d.ts +38 -9
- package/dist/plugins/memory-engine-tidb.js +99 -230
- package/dist/plugins/memory-key-guards.d.ts +1 -1
- package/dist/plugins/memory-origin-law.d.ts +3 -3
- package/dist/plugins/one-time-migrations.d.ts +169 -83
- package/dist/plugins/one-time-migrations.js +295 -235
- package/dist/plugins/owner-only-file-mode.d.ts +29 -0
- package/dist/plugins/owner-only-file-mode.js +141 -0
- package/dist/plugins/permission-rule-store-file.d.ts +17 -3
- package/dist/plugins/permission-rule-store-file.js +20 -1
- package/dist/plugins/pg-pool.d.ts +2 -1
- package/dist/plugins/pg-pool.js +12 -5
- package/dist/plugins/release-version.d.ts +20 -0
- package/dist/plugins/release-version.js +28 -0
- package/dist/plugins/remote-env-adb.d.ts +20 -4
- package/dist/plugins/remote-env-adb.js +39 -11
- package/dist/plugins/remote-env-e2b.d.ts +12 -3
- package/dist/plugins/remote-env-e2b.js +6 -4
- package/dist/plugins/remote-env-host.d.ts +9 -1
- package/dist/plugins/remote-env-host.js +6 -5
- package/dist/plugins/remote-env-k8s.d.ts +5 -2
- package/dist/plugins/remote-env-k8s.js +15 -4
- package/dist/plugins/remote-env-local-docker.d.ts +4 -1
- package/dist/plugins/remote-env-local-docker.js +3 -3
- package/dist/plugins/remote-env-ssh.d.ts +8 -2
- package/dist/plugins/remote-env-ssh.js +26 -24
- package/dist/plugins/remote-shell.d.ts +59 -30
- package/dist/plugins/remote-shell.js +175 -62
- package/dist/plugins/retention-declaration.d.ts +37 -0
- package/dist/plugins/retention-declaration.js +9 -0
- package/dist/plugins/retention-deployment.d.ts +126 -0
- package/dist/plugins/retention-deployment.js +88 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
- package/dist/plugins/retention-lane-store-sql.js +103 -1
- package/dist/plugins/retention-sql.d.ts +29 -0
- package/dist/plugins/retention-sql.js +8 -0
- package/dist/plugins/run-store-sql.js +2 -2
- package/dist/plugins/schema-consistency.d.ts +0 -6
- package/dist/plugins/schema-consistency.js +1 -2
- package/dist/plugins/schema-ensure-legs.d.ts +1 -1
- package/dist/plugins/schema-ensure-legs.js +13 -3
- package/dist/plugins/session-ext-table.d.ts +74 -0
- package/dist/plugins/session-ext-table.js +121 -0
- package/dist/plugins/session-fork.d.ts +31 -9
- package/dist/plugins/session-fork.js +3 -2
- package/dist/plugins/session-placement.d.ts +4 -2
- package/dist/plugins/session-row-sql.d.ts +8 -7
- package/dist/plugins/session-row-sql.js +15 -7
- package/dist/plugins/session-store-sql.d.ts +131 -0
- package/dist/plugins/session-store-sql.js +298 -0
- package/dist/plugins/session-workspace-cell.d.ts +2 -2
- package/dist/plugins/session-workspace-cell.js +2 -2
- package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
- package/dist/plugins/shared-memory-store-sql.js +13 -13
- package/dist/plugins/snapshot-bucket-presence.js +1 -1
- package/dist/plugins/sql-driver.d.ts +23 -7
- package/dist/plugins/sql-driver.js +41 -8
- package/dist/plugins/sql-errors.d.ts +5 -2
- package/dist/plugins/sql-errors.js +4 -0
- package/dist/plugins/sql-json-column.d.ts +5 -1
- package/dist/plugins/store-backend.d.ts +46 -16
- package/dist/plugins/store-backend.js +192 -69
- package/dist/plugins/store-contracts.d.ts +10 -13
- package/dist/plugins/store-contracts.js +1 -9
- package/dist/plugins/store-sweep.d.ts +63 -0
- package/dist/plugins/store-sweep.js +48 -0
- package/dist/plugins/task-attachment-store.d.ts +6 -8
- package/dist/plugins/task-attachment-store.js +15 -10
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/text-column-capacity.d.ts +21 -0
- package/dist/plugins/text-column-capacity.js +5 -0
- package/dist/plugins/tidb-pool.d.ts +3 -2
- package/dist/plugins/tidb-pool.js +20 -32
- package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
- package/dist/prompt-screen.d.ts +6 -9
- package/dist/prompt-screen.js +2 -5
- package/dist/read-face-posture.d.ts +6 -6
- package/dist/read-face-posture.js +2 -2
- package/dist/request-value-closure.d.ts +5 -5
- package/dist/request-value-closure.js +1 -1
- package/dist/rules-consent.d.ts +48 -27
- package/dist/rules-consent.js +147 -23
- package/dist/run-cancel-context.d.ts +4 -1
- package/dist/run-cancel-context.js +2 -1
- package/dist/run-local.js +17 -13
- package/dist/runs.d.ts +48 -30
- package/dist/runs.js +27 -17
- package/dist/runtime-caps-resolver.d.ts +15 -8
- package/dist/runtime-caps-resolver.js +14 -10
- package/dist/sandbox-egress-policy.js +6 -11
- package/dist/sandbox-rbac-rules.d.ts +88 -0
- package/dist/sandbox-rbac-rules.js +80 -0
- package/dist/sealed-key-layout.d.ts +16 -0
- package/dist/sealed-key-layout.js +3 -0
- package/dist/sealed-key.js +8 -6
- package/dist/security.d.ts +43 -9
- package/dist/security.js +9 -2
- package/dist/sema-config-dir.js +2 -2
- package/dist/server-secret-env.d.ts +2 -0
- package/dist/service-version.d.ts +2 -1
- package/dist/service-version.js +2 -2
- package/dist/session-error-wire.d.ts +1 -1
- package/dist/session-incarnation.d.ts +8 -5
- package/dist/session-notify-door.d.ts +5 -3
- package/dist/session-resident-background.d.ts +110 -0
- package/dist/session-resident-background.js +88 -0
- package/dist/session-row.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +53 -14
- package/dist/session-sync-kernel.js +70 -1
- package/dist/session-sync.d.ts +5 -3
- package/dist/session-workspace.d.ts +12 -2
- package/dist/session-workspace.js +6 -0
- package/dist/sighup-idle.d.ts +9 -7
- package/dist/sighup-idle.js +4 -5
- package/dist/spec-fields.d.ts +16 -0
- package/dist/spec-fields.js +7 -0
- package/dist/store-posture.d.ts +2 -1
- package/dist/stored-request-env-credentials-m38.d.ts +3 -0
- package/dist/stored-request-env-credentials-m38.js +8 -0
- package/dist/stored-request-hooks-m20.d.ts +3 -2
- package/dist/stored-request-hooks-m20.js +19 -14
- package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
- package/dist/stores-sql/blob-index-sql.d.ts +148 -0
- package/dist/stores-sql/blob-index-sql.js +154 -0
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +14 -428
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +43 -220
- package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
- package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
- package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
- package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +27 -67
- package/dist/{plugins → stores-sql}/pg-session-storage.js +82 -207
- package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
- package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
- package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
- package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
- package/dist/stores-sql/session-write-hooks.d.ts +59 -0
- package/dist/stores-sql/session-write-hooks.js +2 -0
- package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
- package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
- package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +35 -112
- package/dist/{plugins → stores-sql}/tidb-session-store.js +73 -169
- package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +3 -3
- package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
- package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
- package/dist/stores-sql/windowed-session-storage.js +61 -0
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
- package/dist/task-a2a.d.ts +7 -1
- package/dist/task-a2a.js +15 -14
- package/dist/task-cwd.d.ts +11 -3
- package/dist/task-cwd.js +17 -1
- package/dist/task-mcp.d.ts +10 -2
- package/dist/task-mcp.js +13 -16
- package/dist/task-settings.d.ts +68 -8
- package/dist/task-settings.js +63 -6
- package/dist/tool-approval.d.ts +23 -10
- package/dist/tool-approval.js +10 -6
- package/dist/trace/core-keyset-guard.d.ts +17 -10
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +4 -0
- package/dist/trace/exit-seat.d.ts +29 -1
- package/dist/trace/exit-seat.js +4 -0
- package/dist/trace/project.d.ts +33 -16
- package/dist/trace/project.js +21 -9
- package/dist/trace/redact.d.ts +13 -2
- package/dist/trace/redact.js +347 -78
- package/dist/trace/self-minted-wire.d.ts +587 -16
- package/dist/trace/self-minted-wire.js +215 -9
- package/dist/trace/sema-provenance.d.ts +45 -41
- package/dist/trace/sema-provenance.js +81 -10
- package/dist/trace/task-notification-facets.d.ts +70 -2
- package/dist/trace/task-notification-facets.js +71 -1
- package/dist/trace/wire-projection-faces.d.ts +39 -3
- package/dist/trace/wire-projection-faces.js +27 -2
- package/dist/unread-request-members.d.ts +66 -0
- package/dist/unread-request-members.js +41 -0
- package/dist/usage-analytics.d.ts +4 -0
- package/dist/user-input-ledger.d.ts +2 -2
- package/dist/web-admin-client/apply-effective.js +22 -26
- package/dist/web-admin-client/candidate-gate.d.ts +35 -3
- package/dist/web-admin-client/candidate-gate.js +53 -5
- package/dist/web-admin-client/center-request.d.ts +4 -1
- package/dist/web-admin-client/center-request.js +2 -1
- package/dist/web-admin-client/effective-keys.js +0 -1
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/http-client.d.ts +1 -0
- package/dist/web-admin-client/http-client.js +17 -9
- package/dist/web-admin-client/restart-signal.js +5 -2
- package/dist/web-admin-client/skills-mcp.d.ts +20 -6
- package/dist/web-admin-client/skills-mcp.js +26 -21
- package/dist/web-admin-client/types.d.ts +34 -49
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
- package/package.json +22 -13
- package/scripts/drain-check-local.mjs +8 -55
- package/scripts/drain-check.mysql.sql +3 -40
- package/scripts/drain-check.pg.sql +3 -40
- package/skills/update-config.md +1 -1
- package/wire-changes/server@7.146.0.json +3221 -0
- package/wire-changes/server@7.147.0.json +813 -0
- package/dist/approval-batch-census.d.ts +0 -27
- package/dist/approval-batch-census.js +0 -27
package/dist/runs.js
CHANGED
|
@@ -11,7 +11,7 @@ import { withPrincipal } from "./observability/principal-context.js";
|
|
|
11
11
|
import { withModelReachScope } from "./model-reach-scope.js";
|
|
12
12
|
import { createInstructionSelectionLeg } from "./instruction-selection.js";
|
|
13
13
|
import { redactSecrets } from "./trace/redact.js";
|
|
14
|
-
import { taskNotificationEventData, appendModelUsageDelta,
|
|
14
|
+
import { taskNotificationEventData, appendModelUsageDelta, attachModelUsage, createPromptManifestSeat } from "./trace/project.js";
|
|
15
15
|
import { createLedgerSink } from "./trace/ledger-sink.js";
|
|
16
16
|
import { registerEngineNoticeLeg } from "./trace/engine-notice-wire.js";
|
|
17
17
|
import { recordTurnActivity } from "./turn-activity.js";
|
|
@@ -78,6 +78,8 @@ const PREPARE_REFUSAL_HTTP_STATUS = {
|
|
|
78
78
|
"rewind.child_scope_unsupported": 422,
|
|
79
79
|
"rewind.capture_disabled": 422,
|
|
80
80
|
"rewind.store_unconfigured": 409,
|
|
81
|
+
"rewind.session_busy": 409,
|
|
82
|
+
"rewind.files_env_unsupported": 409,
|
|
81
83
|
"memory.capture_optout_unpersisted": 503,
|
|
82
84
|
"config.memory_capture_spelling": 400,
|
|
83
85
|
"config.invalid_checkpoint_store": 400,
|
|
@@ -174,17 +176,25 @@ export async function releaseKeyIfZeroWorkRefusal(runStore, taskId, result) {
|
|
|
174
176
|
await runStore.releaseIdemKey(taskId);
|
|
175
177
|
}
|
|
176
178
|
export function createPromptCommitReader() {
|
|
177
|
-
|
|
179
|
+
const commits = [];
|
|
180
|
+
let frames = 0;
|
|
181
|
+
let appliedInputs = 0;
|
|
182
|
+
let settled = false;
|
|
178
183
|
return (ev) => {
|
|
184
|
+
if (settled)
|
|
185
|
+
return undefined;
|
|
179
186
|
if (ev.type === "human_input") {
|
|
180
187
|
const h = ev;
|
|
181
188
|
if (h.delivery !== "applied")
|
|
182
189
|
return undefined;
|
|
183
|
-
|
|
190
|
+
appliedInputs += 1;
|
|
191
|
+
if (appliedInputs === 1)
|
|
192
|
+
frames = Array.isArray(h.attachments) ? h.attachments.length : 0;
|
|
184
193
|
return undefined;
|
|
185
194
|
}
|
|
186
195
|
if (ev.type === "turn_end") {
|
|
187
|
-
|
|
196
|
+
if (commits.length > 0)
|
|
197
|
+
settled = true;
|
|
188
198
|
return undefined;
|
|
189
199
|
}
|
|
190
200
|
if (ev.type !== "message_committed")
|
|
@@ -192,17 +202,17 @@ export function createPromptCommitReader() {
|
|
|
192
202
|
const c = ev;
|
|
193
203
|
const entryId = typeof c.entryId === "string" && c.entryId.length > 0 ? c.entryId : undefined;
|
|
194
204
|
if (c.role === "user") {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return undefined;
|
|
198
|
-
}
|
|
199
|
-
return entryId;
|
|
205
|
+
commits.push(entryId);
|
|
206
|
+
return frames === 0 && commits.length === 1 ? entryId : undefined;
|
|
200
207
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
if (commits.length === 0)
|
|
209
|
+
return undefined;
|
|
210
|
+
settled = true;
|
|
211
|
+
if (frames === 0)
|
|
212
|
+
return commits.length > 1 ? commits[commits.length - 1] : undefined;
|
|
213
|
+
if (appliedInputs > 1 || commits.length < frames + 1)
|
|
204
214
|
return undefined;
|
|
205
|
-
return
|
|
215
|
+
return commits[commits.length - 1 - frames];
|
|
206
216
|
};
|
|
207
217
|
}
|
|
208
218
|
export async function settleResumeAnchor(write, where) {
|
|
@@ -285,7 +295,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
285
295
|
const startedAt = Date.now();
|
|
286
296
|
metrics?.addGauge("runs_active", 1);
|
|
287
297
|
fleetPublisher?.onStart();
|
|
288
|
-
const cancelCtrl = createRunAbort();
|
|
298
|
+
const cancelCtrl = createRunAbort(principal ?? null);
|
|
289
299
|
inflight?.set(taskId, cancelCtrl);
|
|
290
300
|
markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, principal);
|
|
291
301
|
const preemptEligible = verify === undefined && cascade === undefined;
|
|
@@ -385,8 +395,8 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
385
395
|
const flushModelUsage = () => appendModelUsageDelta(append, modelUsage, taskId);
|
|
386
396
|
const withModelUsage = (result) => attachModelUsage(result, { append, getEvents: (id, after) => runStore.getEvents(id, after), modelUsage, taskId });
|
|
387
397
|
modelUsage?.register(taskId);
|
|
388
|
-
const
|
|
389
|
-
const flushPromptManifest = () =>
|
|
398
|
+
const manifestSeat = createPromptManifestSeat(promptManifests, taskId);
|
|
399
|
+
const flushPromptManifest = () => manifestSeat.drain(append);
|
|
390
400
|
const elicitEmit = (frame) => {
|
|
391
401
|
const { type, ...rest } = frame;
|
|
392
402
|
return append(type, rest);
|
|
@@ -652,7 +662,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
652
662
|
for (const evict of subagentHandleEvictions)
|
|
653
663
|
evict();
|
|
654
664
|
modelUsage?.clear(taskId);
|
|
655
|
-
|
|
665
|
+
manifestSeat.release();
|
|
656
666
|
clearInterval(heartbeat);
|
|
657
667
|
}
|
|
658
668
|
}
|
|
@@ -66,6 +66,11 @@
|
|
|
66
66
|
* 人的授予、搭上一个人的在飞请求、带上一个人的 etag 去换 304。在飞期间换了人,答复由传输层丢弃
|
|
67
67
|
* (`http-client.ts` `requestPrincipalView`),按这一次取数失败走下面的 fail-closed 臂(降级项落在发起那一箱)。
|
|
68
68
|
*
|
|
69
|
+
* 🔐 场景面同一条故障律、另一种拒法:同一次硬失败把场景那一面记成 `"unavailable"`(读数第三态,见 `capabilities/scenarios.ts`
|
|
70
|
+
* `ScenarioRulingRead`),场景门据它拒这条 run(503 `state.scenario_assignment_unavailable`)—— 场景面没有「拒掉放大位、照跑」的中间形:
|
|
71
|
+
* 受限主体的指派与白名单此刻不可知,落部署缺省或照放点名都可能比他的指派更宽。治理两键形不对同记 `"unavailable"`(经 `onError` 一行)。
|
|
72
|
+
* 缺席(无 principal / 中心不发两键)仍是 `undefined`;没接中心的部署根本没有本客户端。
|
|
73
|
+
*
|
|
69
74
|
* The resolver maps center's `EntitlementRuntimeCaps` → the SUBSET core enforces ({@link RuntimeCaps}): center
|
|
70
75
|
* also carries `allowUltracode` (a shell/UX reasoning-tier cap the engine has no primitive for), which we DROP —
|
|
71
76
|
* this seam feeds the ENGINE, and `allowUltracode` is enforced at the service settings-resolution layer, not here.
|
|
@@ -77,7 +82,7 @@ import type { RuntimeCaps } from "@sema-agent/core";
|
|
|
77
82
|
import type { EntitlementRuntimeCaps } from "@sema-agent/settings-schema";
|
|
78
83
|
import { fetchPrincipalCaps, type ExecutionRuling } from "./web-admin-client/facade.js";
|
|
79
84
|
import type { CenterEndpoint } from "./web-admin-client/center-request.js";
|
|
80
|
-
import type {
|
|
85
|
+
import type { ScenarioRulingRead } from "./capabilities/scenarios.js";
|
|
81
86
|
import type { ServiceConfig } from "./config-types.js";
|
|
82
87
|
import { type Logger } from "./observability/logger.js";
|
|
83
88
|
/** test-only: reset the once-per-process trace so each test observes a fresh "first hit". */
|
|
@@ -181,17 +186,18 @@ export interface PrincipalEntitlementsClient {
|
|
|
181
186
|
* 都重抓,denyTtl 的界对提交腿失效)。让它升格的是一次真提交自己吃到的硬失败,不是那次读。
|
|
182
187
|
*/
|
|
183
188
|
peekRuntimeCaps: (principal: string | undefined) => Promise<RuntimeCaps | undefined>;
|
|
184
|
-
/** The resolved per-principal scenario ruling for resolveSpec's gateScenarioRequest —
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
|
|
189
|
+
/** The resolved per-principal scenario ruling for resolveSpec's gateScenarioRequest — a three-state read
|
|
190
|
+
* ({@link ScenarioRulingRead}): the ruling; `undefined` = absent (no principal ⇒ no center call; older center without
|
|
191
|
+
* the scenario keys) = no governance; `"unavailable"` = the center could not answer (hard fetch failure — same error entry
|
|
192
|
+
* as the caps face's fail-closed deny — or malformed ruling keys) ⇒ the gate refuses the run. */
|
|
193
|
+
scenarioRuling: (principal: string | undefined) => Promise<ScenarioRulingRead>;
|
|
188
194
|
/**
|
|
189
195
|
* {@link PrincipalEntitlementsClient.scenarioRuling} 的**只读**孪生(同 {@link PrincipalEntitlementsClient.peekRuntimeCaps} 的界):同一只缓存 / 同一条抓取 /
|
|
190
|
-
*
|
|
196
|
+
* 同一份三态读数(故障 ⇒ `"unavailable"`,读面与提交腿同拒),唯一的差别是 center 硬失败时本腿铸的降级项**只对读面自己算数**,提交腿不认、照常重抓。
|
|
191
197
|
* 读面(`GET /v1/capabilities/mcp?scenario=` 的场景门)问中心裁定时必须走这一只 —— 经 `scenarioRuling` 问,center 抖动的那一拍会替这个主体的**真提交**
|
|
192
198
|
* 留下 `{allowWorkflows:false, allowFork:false, autoMode:false}` 的短窗 deny(读面成了别人被拒的原因,与 `peekRuntimeCaps` 的病灶同一类)。
|
|
193
199
|
*/
|
|
194
|
-
peekScenarioRuling: (principal: string | undefined) => Promise<
|
|
200
|
+
peekScenarioRuling: (principal: string | undefined) => Promise<ScenarioRulingRead>;
|
|
195
201
|
/** (stage7 P5) The resolved per-principal execution-lane ruling for resolveSpec's
|
|
196
202
|
* gateExecutionLane. FAIL-OPEN + audit on error (this phase is "honest-but-bypassable";
|
|
197
203
|
* tightening to fail-closed is a future, separate decision) / older center without the execution key / no principal. */
|
|
@@ -215,7 +221,8 @@ export declare function gateExecutionLane(ruling: ExecutionRuling | undefined, o
|
|
|
215
221
|
* `(principal) => Promise<RuntimeCaps | undefined>`; `scenarioRuling` rides the SAME fetch/cache/in-flight
|
|
216
222
|
* (zero extra center RTT — center attaches the ruling to the caps body). Wire ONLY when a center is
|
|
217
223
|
* configured (and not in dry-run) — absent ⇒ core sees `undefined` ⇒ NO per-principal restriction, and the
|
|
218
|
-
* scenario gate sees `undefined` ⇒
|
|
224
|
+
* scenario gate sees `undefined` (absent) ⇒ request-name-or-deployment-default chain. Present ⇒ a center that cannot answer
|
|
225
|
+
* reads `"unavailable"` on the scenario face (the gate refuses), never `undefined`.
|
|
219
226
|
*/
|
|
220
227
|
export declare function createPrincipalEntitlementsClient(opts: EntitlementsResolverOpts): PrincipalEntitlementsClient;
|
|
221
228
|
/** Back-compat face for core's seam-only consumers: the caps half of {@link createPrincipalEntitlementsClient}. */
|
|
@@ -91,6 +91,13 @@ export function createPrincipalEntitlementsClient(opts) {
|
|
|
91
91
|
const fetchCaps = opts.fetchCaps ?? fetchPrincipalCaps;
|
|
92
92
|
const now = opts.now ?? (() => Date.now());
|
|
93
93
|
const onError = opts.onError ?? ((err, principal) => defaultLogger.warn("runtime_caps_resolve_failed", { principal, err: String(err) }));
|
|
94
|
+
const audit = (err, principal) => {
|
|
95
|
+
try {
|
|
96
|
+
onError(err, principal);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
}
|
|
100
|
+
};
|
|
94
101
|
const binNow = createIdentityBins(opts.center.credential, (credential) => ({
|
|
95
102
|
center: { baseUrl: opts.center.baseUrl, credential },
|
|
96
103
|
cache: new Map(),
|
|
@@ -136,14 +143,14 @@ export function createPrincipalEntitlementsClient(opts) {
|
|
|
136
143
|
return entry;
|
|
137
144
|
}
|
|
138
145
|
if (r.executionDrift) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
audit(new Error(`execution ruling wire drift: ${r.executionDrift}`), principal);
|
|
147
|
+
}
|
|
148
|
+
if (r.scenarioDrift) {
|
|
149
|
+
audit(new Error(`scenario ruling wire drift: ${r.scenarioDrift}`), principal);
|
|
143
150
|
}
|
|
144
151
|
const entry = {
|
|
145
152
|
caps: toCoreRuntimeCaps(r.runtimeCaps),
|
|
146
|
-
...(r.scenario ? { scenario: r.scenario } : {}),
|
|
153
|
+
...(r.scenarioDrift ? { scenario: "unavailable" } : r.scenario ? { scenario: r.scenario } : {}),
|
|
147
154
|
...(r.execution ? { execution: r.execution } : {}),
|
|
148
155
|
...(r.etag ? { etag: r.etag } : {}),
|
|
149
156
|
expiresAt: now() + ttlMs,
|
|
@@ -159,14 +166,11 @@ export function createPrincipalEntitlementsClient(opts) {
|
|
|
159
166
|
catch {
|
|
160
167
|
e = new Error("center fetch failed with an unstringifiable rejection reason");
|
|
161
168
|
}
|
|
162
|
-
const entry = { caps: { allowWorkflows: false, allowFork: false, autoMode: false, autoModeDenySource: "org", bypassPermissions: false }, expiresAt: now() + denyTtlMs };
|
|
169
|
+
const entry = { caps: { allowWorkflows: false, allowFork: false, autoMode: false, autoModeDenySource: "org", bypassPermissions: false }, scenario: "unavailable", expiresAt: now() + denyTtlMs };
|
|
163
170
|
if (!recordDeny)
|
|
164
171
|
readMintedDeny.add(entry);
|
|
165
172
|
putCache(bin.cache, principal, entry);
|
|
166
|
-
|
|
167
|
-
onError(e, principal);
|
|
168
|
-
}
|
|
169
|
-
catch { }
|
|
173
|
+
audit(e, principal);
|
|
170
174
|
return entry;
|
|
171
175
|
}
|
|
172
176
|
finally {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { createCidrSet, parseCidr as readCidrText } from "./net-address.js";
|
|
2
3
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
3
4
|
import { seatText } from "./trace/exit-seat.js";
|
|
4
5
|
export const SANDBOX_IPV6_WORDS = ["enabled", "disabled"];
|
|
@@ -155,22 +156,16 @@ function nodeAddresses(json) {
|
|
|
155
156
|
return out;
|
|
156
157
|
}
|
|
157
158
|
function parseCidr(cidr) {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
const fam = isIP(net);
|
|
161
|
-
const max = fam === 6 ? 128 : 32;
|
|
162
|
-
const prefix = slash < 0 ? max : Number(cidr.slice(slash + 1));
|
|
163
|
-
if (fam === 0 || !/^\d+$/.test(slash < 0 ? String(max) : cidr.slice(slash + 1)) || prefix > max)
|
|
159
|
+
const r = readCidrText(cidr);
|
|
160
|
+
if (!r.ok)
|
|
164
161
|
throw new Unjudgeable(`ipBlock cidr ${JSON.stringify(cidr)} does not parse`);
|
|
165
|
-
return
|
|
162
|
+
return r.cidr;
|
|
166
163
|
}
|
|
167
164
|
function inCidr(address, cidr) {
|
|
168
165
|
const c = parseCidr(cidr);
|
|
169
166
|
if ((isIP(address) === 6 ? "ipv6" : "ipv4") !== c.family)
|
|
170
167
|
return false;
|
|
171
|
-
|
|
172
|
-
list.addSubnet(c.net, c.prefix, c.family);
|
|
173
|
-
return list.check(address, c.family);
|
|
168
|
+
return createCidrSet([c]).has(address);
|
|
174
169
|
}
|
|
175
170
|
function ruleAllows(rule, address) {
|
|
176
171
|
if (rule.to === undefined)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 沙箱车道(`REMOTE_EXEC=k8s`)的服务账号在沙箱命名空间 / 集群里需要哪些 RBAC 规则,以及每条规则由哪个引擎特性开关决定 ——
|
|
3
|
+
* 「引擎需要哪条规则由哪个开关决定」**只写在这一张表里**。
|
|
4
|
+
*
|
|
5
|
+
* ## 谁读它(都是读者,没有第二份)
|
|
6
|
+
* · `scripts/gen-deploy-lanes.ts`:把本表渲成部署产物 —— chart `templates/sandbox-rbac.yaml` 的 Role / ClusterRole 规则区(开关条件规则包在 helm 条件里)、
|
|
7
|
+
* chart `templates/_helpers.tpl` 里把同一个开关值写进引擎旋钮的助手体、cluster 静态清单的同两个规则区(静态清单不能条件渲,引擎 env 里两个旋钮都没设,
|
|
8
|
+
* 开关条件规则渲成注释掉的规则块)、`docs/DEPLOY-PREREQS.md` 的规则表区,以及给取用方的只读数据 `deploy/facts/sandbox-rbac.json`。
|
|
9
|
+
* 「入库文件 ≡ 生成物」由 `--check` 与 `test/deploy-lane-projections.test.ts` 钉;行为由 `test/sandbox-rbac-table.test.ts` 钉。
|
|
10
|
+
* · secrets 那一行的动词**直接就是** {@link SANDBOX_SECRET_SEAT_VERBS}`.env`(起服门问的、适配器真发的同一张表)—— 不另抄一份。
|
|
11
|
+
* pvc 那一行的动词 ⊇ 适配器对 `persistentvolumeclaims` 真发的每个调用(`test/sandbox-rbac-table.test.ts` 读 `remote-env-k8s.ts` 对拍)。
|
|
12
|
+
*
|
|
13
|
+
* ## 形
|
|
14
|
+
* · `when`:`"always"`(恒授)或一个**特性开关词**({@link SANDBOX_RBAC_SWITCH_WORDS},闭集;加词必须同时给 {@link SANDBOX_RBAC_SWITCHES} 一行 —— 缺行是编译错)。
|
|
15
|
+
* · 开关 = 引擎旋钮的一个状态:`bool` 形 = 旋钮取某个词时开(`WORKSPACE_CACHE=volume`),`names` 形 = 旋钮是 NAME,NAME 名单、非空时开(`K8S_SANDBOX_ENV`)。
|
|
16
|
+
* 随包 chart 里同一个值(`chartValue`)既写引擎旋钮、又决定 Role 带不带那几行规则。
|
|
17
|
+
* · `need`:这一行的动词引擎适配器**真调**(`called`,`why` 里写着调用它的适配器方法〔`remote-env-k8s.ts#<方法名>`〕,源码钉对拍)还是只是**兼容保留**
|
|
18
|
+
* (`retained`:chart 与静态清单一直授着、适配器源码里零调用)。同一个资源的动词按 `need` 拆成两行;chart 与静态清单把同资源的行并回一条规则照授(本版不删 `retained`)。
|
|
19
|
+
* · 给取用方的数据 `deploy/facts/sandbox-rbac.json` = `{ schemaVersion, rules: [{ scope, apiGroups, resources, verbs, when, need, why }] }`(随包;npm 子路径同名),
|
|
20
|
+
* 形由本文件的 {@link SANDBOX_RBAC_FACTS_SCHEMA} 定义(和表放一起;生成器把它写成 `deploy/facts/sandbox-rbac.schema.json`)。
|
|
21
|
+
* 形变的加性 / 破坏性判法、登记与 `schemaVersion` 的派生是随包部署事实的统一规则,见 `src/deploy-facts.ts` 头注 —— 本表不另立一套。
|
|
22
|
+
*/
|
|
23
|
+
import type { WorkspaceCacheWord } from "./workspace-cache.js";
|
|
24
|
+
import { type FactsRootSchema } from "./deploy-facts.js";
|
|
25
|
+
/** `deploy/facts/sandbox-rbac.json` 的形版本(从形变登记表派生,见 `src/deploy-facts.ts` 的 `factsSchemaVersion`)。 */
|
|
26
|
+
export declare const SANDBOX_RBAC_SCHEMA_VERSION: number;
|
|
27
|
+
export declare const SANDBOX_RBAC_SCOPES: readonly ["Role", "ClusterRole"];
|
|
28
|
+
export type SandboxRbacScope = (typeof SANDBOX_RBAC_SCOPES)[number];
|
|
29
|
+
/** Kubernetes RBAC 动词闭集(规则只收这些词)。 */
|
|
30
|
+
export declare const SANDBOX_RBAC_VERBS: readonly ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"];
|
|
31
|
+
export declare const SANDBOX_RBAC_ALWAYS: "always";
|
|
32
|
+
/** 特性开关词:引擎旋钮的一个状态。词表是闭集 —— {@link SANDBOX_RBAC_SWITCHES} 对它做穷尽映射(新增一个词而不给开关行 ⇒ 编译错)。 */
|
|
33
|
+
export declare const SANDBOX_RBAC_SWITCH_WORDS: readonly ["WORKSPACE_CACHE=volume", "K8S_SANDBOX_ENV"];
|
|
34
|
+
export type SandboxRbacSwitchWord = (typeof SANDBOX_RBAC_SWITCH_WORDS)[number];
|
|
35
|
+
/** `when` 的全词表:恒授 + 开关词。 */
|
|
36
|
+
export declare const SANDBOX_RBAC_WHEN_WORDS: readonly ["always", "WORKSPACE_CACHE=volume", "K8S_SANDBOX_ENV"];
|
|
37
|
+
export type SandboxRbacWhen = (typeof SANDBOX_RBAC_WHEN_WORDS)[number];
|
|
38
|
+
export type SandboxRbacSwitch = {
|
|
39
|
+
/** 旋钮取 {@link envValue} 时开。 */
|
|
40
|
+
readonly kind: "bool";
|
|
41
|
+
readonly env: string;
|
|
42
|
+
readonly envValue: WorkspaceCacheWord;
|
|
43
|
+
/** 随包 chart 的值路径,恒 `sandbox.<键>`;布尔。 */
|
|
44
|
+
readonly chartValue: string;
|
|
45
|
+
readonly meaning: string;
|
|
46
|
+
} | {
|
|
47
|
+
/** 旋钮是 NAME,NAME 名单,非空时开。 */
|
|
48
|
+
readonly kind: "names";
|
|
49
|
+
readonly env: string;
|
|
50
|
+
/** 随包 chart 的值路径,恒 `sandbox.<键>`;名单字符串。 */
|
|
51
|
+
readonly chartValue: string;
|
|
52
|
+
readonly meaning: string;
|
|
53
|
+
};
|
|
54
|
+
export declare const SANDBOX_RBAC_SWITCHES: {
|
|
55
|
+
readonly [W in SandboxRbacSwitchWord]: SandboxRbacSwitch;
|
|
56
|
+
};
|
|
57
|
+
/** 一行动词的引擎用度:`called` = 适配器源码真调;`retained` = 兼容保留(chart 有、适配器零调用)。 */
|
|
58
|
+
export declare const SANDBOX_RBAC_NEEDS: readonly ["called", "retained"];
|
|
59
|
+
export type SandboxRbacNeed = (typeof SANDBOX_RBAC_NEEDS)[number];
|
|
60
|
+
export interface SandboxRbacRule {
|
|
61
|
+
readonly scope: SandboxRbacScope;
|
|
62
|
+
readonly apiGroups: readonly string[];
|
|
63
|
+
readonly resources: readonly string[];
|
|
64
|
+
readonly verbs: readonly string[];
|
|
65
|
+
readonly when: SandboxRbacWhen;
|
|
66
|
+
readonly need: SandboxRbacNeed;
|
|
67
|
+
/** 这一行为什么在(渲成产物里规则上方的注释;也是 `deploy/facts/sandbox-rbac.json` 的 `why`);`called` 行写着调用方的 `remote-env-k8s.ts#<方法名>` 坐标。 */
|
|
68
|
+
readonly why: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 规则表(表序 = 产物里的规则序)。`called` 行的调用坐标 = `remote-env-k8s.ts` 里的方法名(不写行号,免得每改一行适配器就漂);
|
|
72
|
+
* `test/sandbox-rbac-table.test.ts` 读该文件逐方法核「这一行的动词 ⊆ 那些方法真发的调用」,并核 `retained` 行没有任何调用。
|
|
73
|
+
*/
|
|
74
|
+
export declare const SANDBOX_RBAC_RULES: readonly SandboxRbacRule[];
|
|
75
|
+
/** 一份完整的表(生成器的输入;测试用变异夹具替换它)。 */
|
|
76
|
+
export interface SandboxRbacModel {
|
|
77
|
+
readonly switches: {
|
|
78
|
+
readonly [W in SandboxRbacSwitchWord]: SandboxRbacSwitch;
|
|
79
|
+
};
|
|
80
|
+
readonly rules: readonly SandboxRbacRule[];
|
|
81
|
+
}
|
|
82
|
+
export declare const SANDBOX_RBAC_MODEL: SandboxRbacModel;
|
|
83
|
+
/**
|
|
84
|
+
* `deploy/facts/sandbox-rbac.json` 的 Schema(随包方言,见 `src/deploy-facts.ts`)。闭集词表直接取本文件的常量:加一个 `when` / `need` / 范围 / 动词词
|
|
85
|
+
* = 闭集加词 = 破坏性形变(读方对闭集做穷尽判别),要登记、要抬版。一条规则的身份 = (范围, apiGroups, resources, need)—— 同一资源按 `need` 拆成两行。
|
|
86
|
+
*/
|
|
87
|
+
export declare const SANDBOX_RBAC_FACTS_SCHEMA: FactsRootSchema;
|
|
88
|
+
//# sourceMappingURL=sandbox-rbac-rules.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SANDBOX_SECRET_SEAT_VERBS } from "./plugins/k8s-exec-protocol.js";
|
|
2
|
+
import { FACTS_SCHEMA_DIALECT, factsSchemaVersion } from "./deploy-facts.js";
|
|
3
|
+
export const SANDBOX_RBAC_SCHEMA_VERSION = factsSchemaVersion("sandbox-rbac");
|
|
4
|
+
export const SANDBOX_RBAC_SCOPES = ["Role", "ClusterRole"];
|
|
5
|
+
export const SANDBOX_RBAC_VERBS = ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"];
|
|
6
|
+
export const SANDBOX_RBAC_ALWAYS = "always";
|
|
7
|
+
export const SANDBOX_RBAC_SWITCH_WORDS = ["WORKSPACE_CACHE=volume", "K8S_SANDBOX_ENV"];
|
|
8
|
+
export const SANDBOX_RBAC_WHEN_WORDS = [SANDBOX_RBAC_ALWAYS, ...SANDBOX_RBAC_SWITCH_WORDS];
|
|
9
|
+
export const SANDBOX_RBAC_SWITCHES = {
|
|
10
|
+
"WORKSPACE_CACHE=volume": { kind: "bool", env: "WORKSPACE_CACHE", envValue: "volume", chartValue: "sandbox.workspaceCacheVolume", meaning: "按工作区空间的构建缓存卷开着" },
|
|
11
|
+
K8S_SANDBOX_ENV: { kind: "names", env: "K8S_SANDBOX_ENV", chartValue: "sandbox.sandboxEnv", meaning: "沙箱带外 env 名单非空(名单点到的值留在服务进程环境里)" },
|
|
12
|
+
};
|
|
13
|
+
export const SANDBOX_RBAC_NEEDS = ["called", "retained"];
|
|
14
|
+
export const SANDBOX_RBAC_RULES = [
|
|
15
|
+
{ scope: "Role", apiGroups: [""], resources: ["pods"], verbs: ["get", "list", "create", "delete"], when: "always", need: "called", why: "沙箱 pod 的生命周期:remote-env-k8s.ts#createPod 建(POST pods)并读就绪(GET pods/<名>)· remote-env-k8s.ts#listSandboxPods 按标签列(GET pods?labelSelector)· remote-env-k8s.ts#reconnect 读存活(GET pods/<名>)· remote-env-k8s.ts#deletePod 删(DELETE pods/<名>)" },
|
|
16
|
+
{ scope: "Role", apiGroups: [""], resources: ["pods"], verbs: ["watch"], when: "always", need: "retained", why: "兼容保留:chart 一直授着,适配器没有 watch 调用" },
|
|
17
|
+
{ scope: "Role", apiGroups: [""], resources: ["pods/exec"], verbs: ["create", "get"], when: "always", need: "called", why: "在沙箱 pod 里执行命令:remote-env-k8s.ts#execUrl 拼 pods/<名>/exec 的连接地址" },
|
|
18
|
+
{ scope: "Role", apiGroups: [""], resources: ["pods/attach"], verbs: ["create", "get"], when: "always", need: "retained", why: "兼容保留:chart 一直授着,适配器没有 attach 调用" },
|
|
19
|
+
{ scope: "Role", apiGroups: [""], resources: ["pods/log"], verbs: ["get"], when: "always", need: "retained", why: "兼容保留:chart 一直授着,适配器没有读日志的调用" },
|
|
20
|
+
{
|
|
21
|
+
scope: "Role",
|
|
22
|
+
apiGroups: [""],
|
|
23
|
+
resources: ["persistentvolumeclaims"],
|
|
24
|
+
verbs: ["get", "create", "deletecollection"],
|
|
25
|
+
when: "WORKSPACE_CACHE=volume",
|
|
26
|
+
need: "called",
|
|
27
|
+
why: "按工作区空间的构建缓存卷:remote-env-k8s.ts#ensureCacheClaim 按名读、没有就建(GET / POST persistentvolumeclaims)· remote-env-k8s.ts#cacheClaimBound 按名读 · remote-env-k8s.ts#reclaimSpaceCache 空间结束按标签回收(DELETE persistentvolumeclaims?labelSelector = deletecollection);缺它 ⇒ 缓存卷拿不到,适配器按 fail-open 照起、不挂卷(计数 server.workspace-cache.unavailable)",
|
|
28
|
+
},
|
|
29
|
+
{ scope: "Role", apiGroups: [""], resources: ["persistentvolumeclaims"], verbs: ["delete"], when: "WORKSPACE_CACHE=volume", need: "retained", why: "兼容保留:chart 一直授着,适配器回收只发按标签的 deletecollection,没有按名 delete 的调用" },
|
|
30
|
+
{
|
|
31
|
+
scope: "Role",
|
|
32
|
+
apiGroups: [""],
|
|
33
|
+
resources: ["secrets"],
|
|
34
|
+
verbs: SANDBOX_SECRET_SEAT_VERBS.env,
|
|
35
|
+
when: "K8S_SANDBOX_ENV",
|
|
36
|
+
need: "called",
|
|
37
|
+
why: "沙箱秘密座:动词取自 SANDBOX_SECRET_SEAT_VERBS.env —— 起服门(boot/execution-env.ts ensureSandboxSecretSeat)问的与 remote-env-k8s.ts#createOwnedSecret 为 env Secret 真发的(POST secrets)是同一行;起服门只在有效转发集合非空(名单点到的键在服务进程环境里有值)时问:答 denied ⇒ server 起服拒,问不到 ⇒ 告警 sandbox_secret_seat_unverified 照起;名单非空而有效集合为空时本行是保守多授(安装器看不到服务进程的运行时环境,引擎此时既不问也不调)",
|
|
38
|
+
},
|
|
39
|
+
{ scope: "Role", apiGroups: ["networking.k8s.io"], resources: ["networkpolicies"], verbs: ["list"], when: "always", need: "called", why: "起服的出网自检读本 ns 的 NetworkPolicy 集合:remote-env-k8s.ts#egressPolicyGaps(GET .../networkpolicies)" },
|
|
40
|
+
{ scope: "Role", apiGroups: ["networking.k8s.io"], resources: ["networkpolicies"], verbs: ["get"], when: "always", need: "retained", why: "兼容保留:chart 一直授着,适配器只读集合(list),没有按名 get" },
|
|
41
|
+
{ scope: "ClusterRole", apiGroups: [""], resources: ["nodes"], verbs: ["list"], when: "always", need: "called", why: "出网自检读节点表(节点是集群级对象 ⇒ ClusterRole + Binding 给同一只服务账号):remote-env-k8s.ts#egressPolicyGaps(GET /api/v1/nodes)" },
|
|
42
|
+
{ scope: "ClusterRole", apiGroups: [""], resources: ["nodes"], verbs: ["get"], when: "always", need: "retained", why: "兼容保留:chart 一直授着,适配器只读集合(list),没有按名 get" },
|
|
43
|
+
];
|
|
44
|
+
export const SANDBOX_RBAC_MODEL = { switches: SANDBOX_RBAC_SWITCHES, rules: SANDBOX_RBAC_RULES };
|
|
45
|
+
const nonEmptyNames = (description) => ({ type: "array", minItems: 1, uniqueItems: true, items: { type: "string" }, description });
|
|
46
|
+
export const SANDBOX_RBAC_FACTS_SCHEMA = {
|
|
47
|
+
$schema: FACTS_SCHEMA_DIALECT,
|
|
48
|
+
description: "k8s 沙箱车道(REMOTE_EXEC=k8s)的服务账号在沙箱命名空间 / 集群里需要的 RBAC 规则;每条规则何时授、引擎适配器真调还是兼容保留。",
|
|
49
|
+
type: "object",
|
|
50
|
+
additionalProperties: false,
|
|
51
|
+
required: ["schemaVersion", "rules"],
|
|
52
|
+
properties: {
|
|
53
|
+
schemaVersion: { type: "integer", const: SANDBOX_RBAC_SCHEMA_VERSION, description: "本份数据的形版本;读方不认识的版本整份拒读。" },
|
|
54
|
+
rules: {
|
|
55
|
+
type: "array",
|
|
56
|
+
minItems: 1,
|
|
57
|
+
"x-uniqueKey": ["scope", "apiGroups", "resources", "need"],
|
|
58
|
+
description: "规则行;同一资源的动词按 need 拆成两行,授权时并回一条规则(Kubernetes 对同一资源的多条规则取并集)。",
|
|
59
|
+
items: {
|
|
60
|
+
type: "object",
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
required: ["scope", "apiGroups", "resources", "verbs", "when", "need", "why"],
|
|
63
|
+
properties: {
|
|
64
|
+
scope: { type: "string", enum: SANDBOX_RBAC_SCOPES, description: "Role = 沙箱命名空间里的 Role;ClusterRole = 集群级对象(节点)要的 ClusterRole,绑给同一只服务账号。" },
|
|
65
|
+
apiGroups: nonEmptyNames("API 组;核心组写空串。"),
|
|
66
|
+
resources: nonEmptyNames("资源名(子资源写 pods/exec 这种形)。"),
|
|
67
|
+
verbs: { type: "array", minItems: 1, uniqueItems: true, items: { type: "string", enum: SANDBOX_RBAC_VERBS }, description: "动词。" },
|
|
68
|
+
when: {
|
|
69
|
+
type: "string",
|
|
70
|
+
enum: SANDBOX_RBAC_WHEN_WORDS,
|
|
71
|
+
description: "always = 恒授;WORKSPACE_CACHE=volume = 引擎开着按工作区空间的缓存卷时授(引擎用到它的条件同一个);K8S_SANDBOX_ENV = 引擎的沙箱 env 名单非空时授 —— 这是保守的授权条件,引擎真正问 / 调用的条件是名单点到的键在服务进程环境里有值,两者之差写在该行 why 里。",
|
|
72
|
+
},
|
|
73
|
+
need: { type: "string", enum: SANDBOX_RBAC_NEEDS, description: "called = 引擎适配器源码真发这些调用;retained = 随包 chart 一直授着、适配器源码里零调用(兼容保留)。" },
|
|
74
|
+
why: { type: "string", description: "这一行为什么在(called 行写着调用它的适配器方法)。" },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=sandbox-rbac-rules.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 钥匙保管目录的布局常量 —— 引擎建目录、建停驻行封签子目录时用的**唯一**值(`src/sealed-key.ts` 读它们)。
|
|
3
|
+
* 钥匙文件的权限位不在这里:它就是本服务文件的那一个值 `plugins/owner-only-file-mode.ts` 的 `OWNER_ONLY_FILE_MODE`(部署事实同读它)。
|
|
4
|
+
*
|
|
5
|
+
* 单独成一只零依赖的叶子模块:随包部署事实 `deploy/facts/sealed-key.json`(`src/deploy-facts.ts` 投影、`scripts/gen-deploy-lanes.ts` 生成)
|
|
6
|
+
* 读的是同一份值,生成器不必为了三个常量把整只保管模块(libsodium / 中心上报)装载进来。
|
|
7
|
+
*/
|
|
8
|
+
/** 保管目录的权限位:每次建店都 `mkdir` + `chmod` 成它(目录预先存在时 `mkdir` 的 mode 不生效,所以另 `chmod` 一次)。 */
|
|
9
|
+
export declare const SEALED_KEY_DIR_MODE = 448;
|
|
10
|
+
/**
|
|
11
|
+
* 停驻行凭据封签那一域的保管子目录名(在模型钥匙保管目录之下:`<保管目录>/checkpoint-ctx-keys/`)。**一个域一对钥匙**:模型钥匙(`ModelEntry.sealedApiKey`,
|
|
12
|
+
* 浏览器对着 caps 公钥裸封)与停驻行封签各用自己目录里的钥匙对 —— 一边的开箱口在另一边的密文上恒「不持有那把钥匙」,不是靠哪一侧多判一句信封。
|
|
13
|
+
* 放在模型钥匙目录之下是为了「多副本共享 / 跨重启持久」只有一个目录要管(整个保管目录);模型钥匙店只读这一层的 `*.json`,子目录不进它的视野。
|
|
14
|
+
*/
|
|
15
|
+
export declare const CHECKPOINT_CTX_KEY_SUBDIR = "checkpoint-ctx-keys";
|
|
16
|
+
//# sourceMappingURL=sealed-key-layout.d.ts.map
|
package/dist/sealed-key.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { chmod,
|
|
2
|
+
import { chmod, readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { ensureDir } from "@sema-agent/core";
|
|
4
5
|
import _sodium from "libsodium-wrappers";
|
|
6
|
+
import { CHECKPOINT_CTX_KEY_SUBDIR, SEALED_KEY_DIR_MODE } from "./sealed-key-layout.js";
|
|
7
|
+
import { OWNER_ONLY_FILE_MODE } from "./plugins/owner-only-file-mode.js";
|
|
5
8
|
import { buildDisplaySafeUrl } from "./trace/redact.js";
|
|
6
9
|
import { createCenterCredentialSource } from "./center-credential.js";
|
|
7
10
|
import { centerFetch } from "./web-admin-client/center-request.js";
|
|
@@ -61,8 +64,8 @@ export function judgeSealedKeyPublicKey(publicKeyB64) {
|
|
|
61
64
|
export async function ensureSealedKeyStore(dir, logger) {
|
|
62
65
|
await _sodium.ready;
|
|
63
66
|
const sodium = _sodium;
|
|
64
|
-
|
|
65
|
-
await chmod(dir,
|
|
67
|
+
ensureDir(dir);
|
|
68
|
+
await chmod(dir, SEALED_KEY_DIR_MODE);
|
|
66
69
|
const keys = new Map();
|
|
67
70
|
for (const name of (await readdir(dir)).filter((n) => n.endsWith(".json")).sort()) {
|
|
68
71
|
const path = join(dir, name);
|
|
@@ -99,8 +102,8 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
99
102
|
createdAt: new Date().toISOString(),
|
|
100
103
|
};
|
|
101
104
|
const path = join(dir, `${record.publicKeyId}.json`);
|
|
102
|
-
await writeFile(path, JSON.stringify(record, null, 2) + "\n", { mode:
|
|
103
|
-
await chmod(path,
|
|
105
|
+
await writeFile(path, JSON.stringify(record, null, 2) + "\n", { mode: OWNER_ONLY_FILE_MODE });
|
|
106
|
+
await chmod(path, OWNER_ONLY_FILE_MODE);
|
|
104
107
|
keys.set(record.publicKeyId, { publicKey: kp.publicKey, privateKey: kp.privateKey, publicKeyB64, createdAt: record.createdAt });
|
|
105
108
|
logger?.info("sealed_key_generated", { publicKeyId: record.publicKeyId, publicKey: publicKeyB64, dir, note: "new X25519 sealed-box keypair in this directory — the private key exists only here: keep the directory across restarts and identical on every replica that has to open what it sealed, and back it up as a private key" });
|
|
106
109
|
}
|
|
@@ -120,7 +123,6 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
120
123
|
},
|
|
121
124
|
};
|
|
122
125
|
}
|
|
123
|
-
const CHECKPOINT_CTX_KEY_SUBDIR = "checkpoint-ctx-keys";
|
|
124
126
|
function mintCheckpointCtxKeyStore(store) {
|
|
125
127
|
return store;
|
|
126
128
|
}
|
package/dist/security.d.ts
CHANGED
|
@@ -4,10 +4,10 @@ import type { ServiceConfig } from "./config-types.js";
|
|
|
4
4
|
import { type DeploymentShapeInput } from "./deployment-shape.js";
|
|
5
5
|
import type { TaskRequestBody } from "./http/wire-types.js";
|
|
6
6
|
import type { StagingHandle } from "./session-sync-kernel.js";
|
|
7
|
-
import type { ClientSessionRowWrite, ReplaySessionRowWrite, ReplaySessionRowWriteOutcome, SessionRowPatch, SessionRowWriteOutcome } from "./session-row.js";
|
|
7
|
+
import type { ClientSessionRowWrite, ReplaySessionRowWrite, ReplaySessionRowWriteOutcome, SessionRowAnswer, SessionRowPatch, SessionRowWriteOutcome } from "./session-row.js";
|
|
8
8
|
import type { ExecutionPlacementSeat } from "./execution-placement.js";
|
|
9
9
|
import type { SessionUnreadable } from "./session-error-wire.js";
|
|
10
|
-
import type { ForkTarget, ForkToOutcome } from "./plugins/session-fork.js";
|
|
10
|
+
import type { ForkPlacement, ForkTarget, ForkToOutcome } from "./plugins/session-fork.js";
|
|
11
11
|
/** One row of the session-list projection (CC /resume picker) — the durable session abstraction's enumeration
|
|
12
12
|
* output (§0.5). Mirrors {@link RunStore}'s shipped `SessionSummary` shape so the wire response is unchanged. */
|
|
13
13
|
export interface SessionListItem {
|
|
@@ -25,7 +25,7 @@ export interface SessionListItem {
|
|
|
25
25
|
* ⇒ 在跑 latest 键诚实缺席)。
|
|
26
26
|
* 读法一致:缺席 = 「此行无已知 engine runId」,禁读成其它含义。⚠️ 与 `lastRunId`(= latest run 的 **task_id**)
|
|
27
27
|
* 是两条身份轴,命名对齐 core `SessionStoreSummary.lastTaskRunId`。wire:additive 键零投影透传
|
|
28
|
-
* (sessions-list.ts);sema-sdk spec `SessionSummary`
|
|
28
|
+
* (sessions-list.ts);sema-sdk spec `SessionSummary` 已声明此键(对账门 `test/sdk-live-parity.test.ts`)。 */
|
|
29
29
|
lastTaskRunId?: string;
|
|
30
30
|
/** The session's title — the user's (`PATCH /v1/sessions/:id`) or, until the user sets one, the auto-titler's
|
|
31
31
|
* (null = untitled / lister face has no session_meta). One column, two writers, one order: `session-row.ts`. */
|
|
@@ -104,7 +104,7 @@ export type SessionOwnerCell = {
|
|
|
104
104
|
readonly placed: boolean;
|
|
105
105
|
};
|
|
106
106
|
/** 会话行属主门的调用方:验过的主体(`gatedPrincipal`)+ 它是不是 **fleet 调用方**(dev-open 部署上的任何调用方,或出示了这台部署的 service 凭据、
|
|
107
|
-
* 不报主体的调用方)。唯一铸点 `http/principal-gate.ts` 的 `sessionCallerOf`。 */
|
|
107
|
+
* 不报主体的调用方 —— 除非部署声明 `SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT=false`)。唯一铸点 `http/principal-gate.ts` 的 `sessionCallerOf`。 */
|
|
108
108
|
export interface SessionCaller {
|
|
109
109
|
readonly principal: Principal | undefined;
|
|
110
110
|
readonly fleet: boolean;
|
|
@@ -114,7 +114,8 @@ export interface SessionCaller {
|
|
|
114
114
|
* 审批豁免面、notify 面的无主臂都经它,不各写一份):
|
|
115
115
|
* · 无主的**普通**会话行 ⇒ 成立(各臂照它自己的其余条件);
|
|
116
116
|
* · 无主的 **placed** 行(委派子代:属主 = 引擎判的委派树属主,三只持久会话店建行那一笔原样记 `placement.owner`,`null` = 根匿名;`delegated-session-owner.ts` 头注)⇒ 只对 **fleet 调用方**成立({@link SessionCaller}:dev-open 部署上的任何调用方,
|
|
117
|
-
* 或出示了 service 凭据、不报主体的调用方 —— 只配 token 的单用户部署、BFF
|
|
117
|
+
* 或出示了 service 凭据、不报主体的调用方 —— 只配 token 的单用户部署、BFF 的系统调用;部署声明 `SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT=false` 时后者不是 fleet)。
|
|
118
|
+
* 任何具名主体(含经 BFF 代发的)与无身份调用方(没有 service 凭据的;声明形上不报主体的 service 凭据)都不成立:
|
|
118
119
|
* 这一行要么属于一棵无身份调用方的树(引擎交的属主是 `null`),要么是属主从没被记下的行 —— 7.144.0 之前写下的存量(7.132.x 及更早建行不记属主;7.133.0–7.143.x 按本服务当年的推断写下,
|
|
119
120
|
* 推断那一刻来源还没有属主的仍无主;SQL 两店由一次性迁移 M23 在它的窗内回填),以及 local 文件店上 7.144.x 及更早建行两笔之间崩溃留下的行(7.145.0 起建行格先、存档后,不再新生)、
|
|
120
121
|
* 同一数据根上 run-local 腿经 core 店写下的 placed 存档(local 没有回填臂)
|
|
@@ -175,10 +176,25 @@ export declare function legacyUnownedSessionOk(deployment: DeploymentShapeInput<
|
|
|
175
176
|
* 单实体读/写点(fork/delete/同步族/workspace)**一律**用三条件齐的 {@link legacyUnownedSessionOk},不要用本函数。
|
|
176
177
|
*/
|
|
177
178
|
export declare function legacyUnownedAmnestyOpen(deployment: DeploymentShapeInput<"principal">, gateOwner: string | null): boolean;
|
|
179
|
+
/** [ref] 存量哨兵窄互认的行属主字面量 —— cli ≤1.0.70 在本地单用户模式自发的 principal 头,存量会话的属主列就是它(引擎不发明这个字面量)。 */
|
|
180
|
+
export declare const LEGACY_SHELL_SENTINEL_OWNER = "anon:shell-live";
|
|
181
|
+
/**
|
|
182
|
+
* 🔴 **会话属主等价律 —— 「行上记下的属主」与「这一次的调用方 / 住客」是不是同一位,唯一判官**(两只窄互认臂收在这一处,读者不各写一份):
|
|
183
|
+
* · 字面相等(含两边都无主 —— 单用户形无身份的调用方与无主的行);
|
|
184
|
+
* · [ref] 窄互认第二臂的身份半支:单机形 ∧ 行无主 ∧ 对方恰为 `default`({@link legacyUnownedAmnestyOpen});
|
|
185
|
+
* · [ref] 存量哨兵臂:非 `requirePrincipal` ∧ 行恰为 {@link LEGACY_SHELL_SENTINEL_OWNER} ∧ 对方没有主体。
|
|
186
|
+
* **有方向、不传递**:`rowOwner` 是行上记下的(或删前记下的)属主,`principal` 是这一次的调用方 / 住客(没有主体 = `null`);
|
|
187
|
+
* 两条臂各自只认它那一对,不由它们推出 `default` ≡ 哨兵、也不反过来认「`default` 的行 ≡ 无主体的调用方」。
|
|
188
|
+
* 读者:`createAuthorizer` 的会话属主门(有主的行)、`http/principal-gate.ts` 的 `runOwnerReadable`(有主的行)、`deleted-session-ids.ts` 的墓碑读点(删前属主 vs 本次住客)。
|
|
189
|
+
* 不在本判官里的两件(它们问的不是「是不是同一位」):无主的委派子代 placed 行只对 fleet 调用方开放(读面律 {@link ownerlessRowOpen});
|
|
190
|
+
* 删除 / fork / 同步族的放行另有 fleet 臂与 placed 判({@link legacyUnownedSessionOk} = 本判官的第二臂 ∧ {@link ownerlessRowOpen})。
|
|
191
|
+
*/
|
|
192
|
+
export declare function sameSessionOwner(deployment: DeploymentShapeInput<"principal">, rowOwner: string | null, principal: string | null): boolean;
|
|
178
193
|
/**
|
|
179
194
|
* 本仓会话店的面 = core `SessionStore` + 本仓的行面(登记 / 列表 / 换装 / 同步……)。
|
|
180
195
|
* 🔴 **按 id 读一行只有一只**:core 的 `headOf(id)`(`{ owner, incarnation, leafId }`,同一行一次读;core 7.55.0 [ref] S2)。
|
|
181
|
-
* 属主 = `headOf(id)?.owner`、住客 = 头的 `incarnation`(
|
|
196
|
+
* 属主 = `headOf(id)?.owner`、住客 = 头的 `incarnation`(两头比较用 core `compareOccupants`:没有行 ⇒ `unknown`,两侧都有令牌且相等或都无令牌 ⇒ `same`,
|
|
197
|
+
* 一侧有一侧无 ⇒ `different`;拿令牌去写用 `sessionFaceOfHead`,它对无令牌的头响亮拒)、叶子 = 头的 `leafId`
|
|
182
198
|
* —— 此前本面另有五只按 id 读(`ownerOf` / `incarnationOf` / `sessionFaceOf` / `getHead` / `getLeafId`),全部退役;规则在 `src/session-incarnation.ts` 头注,
|
|
183
199
|
* 「店有没有这只读」只判 `headReadOf` 一处。
|
|
184
200
|
*/
|
|
@@ -203,6 +219,19 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
203
219
|
limit: number;
|
|
204
220
|
q?: string;
|
|
205
221
|
}) => Promise<SessionListItem[]>;
|
|
222
|
+
/** 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
|
|
223
|
+
* 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
|
|
224
|
+
* in-process reader that must address a row by occupant — the peer directory's `PeerSessionRecord.occupant`. `listSessions` is this face's rows. */
|
|
225
|
+
listSessionRows?: (opts: {
|
|
226
|
+
owner?: string;
|
|
227
|
+
includeUnowned?: boolean;
|
|
228
|
+
cursor?: {
|
|
229
|
+
lastActivityAt: string;
|
|
230
|
+
sessionId: string;
|
|
231
|
+
};
|
|
232
|
+
limit: number;
|
|
233
|
+
q?: string;
|
|
234
|
+
}) => Promise<Array<SessionRowAnswer<SessionListItem>>>;
|
|
206
235
|
/** ONE session's list row — the SAME projection {@link listSessions} emits for it (same columns, same mapper). `undefined` = not a
|
|
207
236
|
* row of the list face (no such session, or a placed / delegation-transcript session, which never lists). Reader: the 2c
|
|
208
237
|
* manifest (`title` / `pinned`). */
|
|
@@ -217,8 +246,12 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
217
246
|
writeSessionRowCells?: SessionRowCellsWriter;
|
|
218
247
|
/** E17 — fork a session's whole history to a NEW session; null if the source is unknown. The fork row records `owner` when it is a
|
|
219
248
|
* string, else (`null`) the SOURCE row's owner — a copy of an owned history is never anonymous (core `SessionStore.fork`, 7.55.0 S2).
|
|
220
|
-
* On the three stores it is the projection `forkTo(…, { id: uuidv7() })` of {@link forkTo} (one private body).
|
|
221
|
-
|
|
249
|
+
* On the three stores it is the projection `forkTo(…, { id: uuidv7(), placement? })` of {@link forkTo} (one private body). `opts.placement`
|
|
250
|
+
* (core `SessionStore.fork`; engine-internal: a background fork child's transcript) forks INTO the delegation partition — the creating write
|
|
251
|
+
* lays the tuple down as a placed acquire does; a store that declares no partition ignores it. */
|
|
252
|
+
fork?: (sourceId: string, owner: string | null, opts?: {
|
|
253
|
+
placement?: ForkPlacement;
|
|
254
|
+
}) => Promise<string | null>;
|
|
222
255
|
/** fork 续写的店契约(三店同一只私有体;规则与结果闭集在 `plugins/session-fork.ts`):把源会话整份历史拷进调用方给的目标 id;`target.key` 存进新行那一格 fork 键。
|
|
223
256
|
* `null` = 源不在;`created` / `replayed`(同属主同键)/ `occupied{sameOwner}`(撞上别的行)。目标行原子新建(SQL 主键排他、meta 先;local 两把写锁 + 格先)。 */
|
|
224
257
|
forkTo?: (sourceId: string, owner: string | null, target: ForkTarget) => Promise<ForkToOutcome | null>;
|
|
@@ -256,7 +289,8 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
256
289
|
importEntries?: (sessionId: string, owner: string | null, entries: SessionTreeEntry[]) => Promise<void>;
|
|
257
290
|
/** 2c session-sync (§7/§8) — IDEMPOTENT replace: atomically purge any existing conversation log for `sessionId`
|
|
258
291
|
* then import `entries` verbatim under `owner`. Unlike importEntries (plain INSERT, fresh-only) this is safe to
|
|
259
|
-
* re-run / apply over an existing session (fast-forward, retry).
|
|
292
|
+
* re-run / apply over an existing session (fast-forward, retry). Owner-guarded (defense-in-depth): the importer's own row is
|
|
293
|
+
* rewritten in place — its incarnation and the deployment cells kept on it (title, pin, instruction baseline, workspace, placement) stay. */
|
|
260
294
|
replaceEntries?: (sessionId: string, owner: string | null, entries: SessionTreeEntry[]) => Promise<void>;
|
|
261
295
|
/** 2c session-sync P1d-β (PUSH streaming) — begin a STAGED import into `realSessionId` under a shadow id
|
|
262
296
|
* `${realSessionId}#stg-${token}` (the route mints the uuidv7 `token`). Returns a {@link StagingHandle} the NDJSON
|