@sema-agent/server 1.323.0 → 2.0.1
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/dist/approval-hmac.d.ts +40 -0
- package/dist/approval-hmac.js +67 -0
- package/dist/approval.d.ts +31 -0
- package/dist/approval.js +72 -4
- package/dist/audit.d.ts +26 -0
- package/dist/audit.js +40 -1
- package/dist/auth-bridge.d.ts +10 -0
- package/dist/auth-bridge.js +47 -4
- package/dist/auth-keys.d.ts +19 -0
- package/dist/auth-keys.js +13 -0
- package/dist/bake-runner/main.d.ts +5 -0
- package/dist/bake-runner/main.js +43 -4
- package/dist/bake-runner/protocol.d.ts +57 -0
- package/dist/bake-runner/protocol.js +58 -3
- package/dist/bake-runner/runner.d.ts +54 -0
- package/dist/bake-runner/runner.js +87 -5
- package/dist/bench/l8/artifact.d.ts +63 -0
- package/dist/bench/l8/artifact.js +61 -2
- package/dist/bench/l8/escape.d.ts +36 -0
- package/dist/bench/l8/escape.js +25 -0
- package/dist/bench/l8/index.d.ts +14 -0
- package/dist/bench/l8/index.js +14 -0
- package/dist/bench/l8/probes.d.ts +74 -0
- package/dist/bench/l8/probes.js +60 -0
- package/dist/bench/l8/run-probes.d.ts +43 -0
- package/dist/bench/l8/run-probes.js +45 -2
- package/dist/bench/s1/arms.d.ts +126 -0
- package/dist/bench/s1/arms.js +188 -13
- package/dist/bench/s1/live-deps.d.ts +66 -0
- package/dist/bench/s1/live-deps.js +249 -11
- package/dist/bench/s1/oracle.d.ts +49 -0
- package/dist/bench/s1/oracle.js +36 -1
- package/dist/bench/s1/repair-oracle-adapter.d.ts +33 -0
- package/dist/bench/s1/repair-oracle-adapter.js +30 -0
- package/dist/bench/s1/reviewer.d.ts +38 -0
- package/dist/bench/s1/reviewer.js +34 -0
- package/dist/bench/s1/row.d.ts +77 -0
- package/dist/bench/s1/row.js +62 -0
- package/dist/bench/s1/run-firm.d.ts +47 -0
- package/dist/bench/s1/run-firm.js +70 -4
- package/dist/bench/s1/runner-ctx.d.ts +71 -0
- package/dist/bench/s1/runner-ctx.js +36 -0
- package/dist/bench/s1/tasks.d.ts +108 -0
- package/dist/bench/s1/tasks.js +115 -0
- package/dist/boot/budget-tracing.d.ts +48 -0
- package/dist/boot/budget-tracing.js +86 -0
- package/dist/boot/config-center.d.ts +62 -0
- package/dist/boot/config-center.js +995 -0
- package/dist/boot/coordinators.d.ts +33 -0
- package/dist/boot/coordinators.js +97 -0
- package/dist/boot/execution-env.d.ts +26 -0
- package/dist/boot/execution-env.js +370 -0
- package/dist/boot/leader.d.ts +27 -0
- package/dist/boot/leader.js +81 -0
- package/dist/boot/reapers.d.ts +53 -0
- package/dist/boot/reapers.js +252 -0
- package/dist/boot/resolve-spec.d.ts +70 -0
- package/dist/boot/resolve-spec.js +1072 -0
- package/dist/boot/runner-deps.d.ts +101 -0
- package/dist/boot/runner-deps.js +343 -0
- package/dist/boot/runtime-caps.d.ts +21 -0
- package/dist/boot/runtime-caps.js +62 -0
- package/dist/boot/session-faces.d.ts +57 -0
- package/dist/boot/session-faces.js +157 -0
- package/dist/boot/shutdown.d.ts +50 -0
- package/dist/boot/shutdown.js +129 -0
- package/dist/boot/stores.d.ts +32 -0
- package/dist/boot/stores.js +361 -0
- package/dist/boot/workflow-orchestration.d.ts +46 -0
- package/dist/boot/workflow-orchestration.js +150 -0
- package/dist/boot-reclaim.d.ts +19 -0
- package/dist/boot-reclaim.js +20 -0
- package/dist/brain.d.ts +25 -0
- package/dist/brain.js +61 -1
- package/dist/budget.d.ts +66 -0
- package/dist/budget.js +128 -4
- package/dist/capabilities/builtin-tools.d.ts +3 -0
- package/dist/capabilities/builtin-tools.js +3 -0
- package/dist/capabilities/center-plugins.d.ts +17 -1
- package/dist/capabilities/center-plugins.js +45 -4
- package/dist/capabilities/center-prompts.d.ts +46 -0
- package/dist/capabilities/center-prompts.js +57 -3
- package/dist/capabilities/code-review-council.d.ts +28 -0
- package/dist/capabilities/code-review-council.js +40 -7
- package/dist/capabilities/collab-wire.d.ts +2 -0
- package/dist/capabilities/collab-workflows.d.ts +7 -0
- package/dist/capabilities/collab-workflows.js +44 -1
- package/dist/capabilities/oa-tools.d.ts +6 -0
- package/dist/capabilities/oa-tools.js +10 -0
- package/dist/capabilities/prompt.d.ts +14 -0
- package/dist/capabilities/prompt.js +14 -0
- package/dist/capabilities/prompts/code-review.d.ts +14 -0
- package/dist/capabilities/prompts/code-review.js +14 -0
- package/dist/capabilities/prompts/identity.d.ts +6 -0
- package/dist/capabilities/prompts/identity.js +6 -0
- package/dist/capabilities/prompts/team.d.ts +4 -0
- package/dist/capabilities/prompts/team.js +4 -0
- package/dist/capabilities/repo-tools.d.ts +11 -0
- package/dist/capabilities/repo-tools.js +8 -0
- package/dist/capabilities/sandbox-file-send.d.ts +95 -0
- package/dist/capabilities/sandbox-file-send.js +91 -3
- package/dist/capabilities/scenarios.d.ts +130 -0
- package/dist/capabilities/scenarios.js +180 -7
- package/dist/capabilities/select-environment-tool.d.ts +7 -0
- package/dist/capabilities/select-environment-tool.js +30 -0
- package/dist/capabilities/send-user-file-tool.d.ts +33 -0
- package/dist/capabilities/send-user-file-tool.js +65 -1
- package/dist/capabilities/skills.d.ts +29 -0
- package/dist/capabilities/skills.js +13 -2
- package/dist/capabilities/team.d.ts +22 -0
- package/dist/capabilities/team.js +22 -2
- package/dist/capabilities/tool-defer.d.ts +26 -0
- package/dist/capabilities/tool-defer.js +3 -0
- package/dist/config-center/apply-effective.d.ts +65 -0
- package/dist/config-center/apply-effective.js +204 -12
- package/dist/config-center/http-client.d.ts +34 -0
- package/dist/config-center/http-client.js +68 -0
- package/dist/config-center/restart-signal.d.ts +22 -0
- package/dist/config-center/restart-signal.js +39 -0
- package/dist/config-center/skills-mcp.d.ts +20 -1
- package/dist/config-center/skills-mcp.js +42 -7
- package/dist/config-center/types.d.ts +92 -1
- package/dist/config-lkg.d.ts +12 -0
- package/dist/config-lkg.js +41 -0
- package/dist/config-provider.d.ts +78 -0
- package/dist/config-provider.js +165 -2
- package/dist/config-types.d.ts +585 -1
- package/dist/config.d.ts +78 -2
- package/dist/config.js +874 -301
- package/dist/degenerate-instrument.d.ts +38 -0
- package/dist/degenerate-instrument.js +55 -3
- package/dist/elicitation.d.ts +39 -0
- package/dist/elicitation.js +87 -3
- package/dist/env-facts.d.ts +61 -0
- package/dist/env-facts.js +73 -7
- package/dist/fleet/fleet-bus.d.ts +185 -0
- package/dist/fleet/fleet-bus.js +333 -27
- package/dist/fleet/subagent-tail-bus.d.ts +11 -0
- package/dist/fleet/subagent-tail-bus.js +33 -2
- package/dist/fleet-client.d.ts +38 -0
- package/dist/fleet-client.js +44 -9
- package/dist/fleet-lease.d.ts +46 -0
- package/dist/fleet-lease.js +73 -5
- package/dist/hooks/branch-transcript.d.ts +8 -0
- package/dist/hooks/branch-transcript.js +33 -0
- package/dist/hooks/cc-stop-prompt.d.ts +42 -0
- package/dist/hooks/cc-stop-prompt.js +43 -1
- package/dist/hooks/hook-llm.d.ts +15 -0
- package/dist/hooks/hook-llm.js +47 -0
- package/dist/hooks/hook-runner.d.ts +89 -0
- package/dist/hooks/hook-runner.js +327 -18
- package/dist/http/idempotency.d.ts +31 -0
- package/dist/http/idempotency.js +34 -0
- package/dist/http/principal-gate.d.ts +17 -0
- package/dist/http/principal-gate.js +35 -3
- package/dist/http/route-ctx.d.ts +36 -0
- package/dist/http/routes/approvals-assistant.d.ts +25 -0
- package/dist/http/routes/approvals-assistant.js +253 -23
- package/dist/http/routes/attachments.js +22 -4
- package/dist/http/routes/capabilities.d.ts +7 -0
- package/dist/http/routes/capabilities.js +202 -1
- package/dist/http/routes/fleet.d.ts +6 -0
- package/dist/http/routes/fleet.js +94 -5
- package/dist/http/routes/images.d.ts +17 -0
- package/dist/http/routes/images.js +222 -14
- package/dist/http/routes/leader.d.ts +7 -0
- package/dist/http/routes/leader.js +10 -0
- package/dist/http/routes/memory-policy.d.ts +6 -0
- package/dist/http/routes/memory-policy.js +38 -6
- package/dist/http/routes/notify-wake.d.ts +10 -0
- package/dist/http/routes/notify-wake.js +19 -3
- package/dist/http/routes/observability.d.ts +6 -0
- package/dist/http/routes/observability.js +19 -2
- package/dist/http/routes/runs.d.ts +15 -0
- package/dist/http/routes/runs.js +464 -41
- package/dist/http/routes/session-sync.d.ts +15 -0
- package/dist/http/routes/session-sync.js +229 -19
- package/dist/http/routes/sessions-list.d.ts +6 -0
- package/dist/http/routes/sessions-list.js +35 -4
- package/dist/http/routes/sessions.d.ts +14 -0
- package/dist/http/routes/sessions.js +176 -31
- package/dist/http/routes/side-query.d.ts +8 -0
- package/dist/http/routes/side-query.js +26 -1
- package/dist/http/routes/tasks.d.ts +18 -0
- package/dist/http/routes/tasks.js +501 -38
- package/dist/http/routes/trace-usage.d.ts +10 -0
- package/dist/http/routes/trace-usage.js +66 -14
- package/dist/http/routes/workflows.d.ts +12 -0
- package/dist/http/routes/workflows.js +180 -19
- package/dist/http/run-meta.d.ts +11 -0
- package/dist/http/run-meta.js +6 -0
- package/dist/http/send.d.ts +19 -0
- package/dist/http/send.js +11 -0
- package/dist/http/server.d.ts +255 -0
- package/dist/http/server.js +921 -75
- package/dist/http/sse-log.d.ts +15 -0
- package/dist/http/sse-log.js +16 -0
- package/dist/http/tar.d.ts +9 -0
- package/dist/http/tar.js +21 -5
- package/dist/http/wire-gate.d.ts +9 -0
- package/dist/http/wire-gate.js +9 -0
- package/dist/http/wire-types.d.ts +187 -0
- package/dist/http/workspace-content.d.ts +8 -0
- package/dist/http/workspace-content.js +10 -0
- package/dist/images/bake-validate.d.ts +63 -0
- package/dist/images/bake-validate.js +71 -1
- package/dist/images/manifest.d.ts +19 -0
- package/dist/images/manifest.js +6 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +10 -5
- package/dist/key-resolver.d.ts +23 -0
- package/dist/key-resolver.js +27 -2
- package/dist/leader/diffout.d.ts +23 -0
- package/dist/leader/diffout.js +8 -1
- package/dist/leader/diffup.d.ts +32 -0
- package/dist/leader/diffup.js +43 -0
- package/dist/leader/endpoint.d.ts +20 -0
- package/dist/leader/endpoint.js +25 -2
- package/dist/leader/fanout.d.ts +60 -0
- package/dist/leader/fanout.js +29 -3
- package/dist/leader/grader-env-factory.d.ts +74 -0
- package/dist/leader/grader-env-factory.js +62 -3
- package/dist/leader/leader.d.ts +97 -0
- package/dist/leader/leader.js +151 -4
- package/dist/leader/merge.d.ts +94 -0
- package/dist/leader/merge.js +112 -9
- package/dist/leader/planner.d.ts +52 -0
- package/dist/leader/planner.js +47 -3
- package/dist/leader/repair-oracle.d.ts +61 -0
- package/dist/leader/repair-oracle.js +59 -1
- package/dist/leader/repair-wire.d.ts +78 -0
- package/dist/leader/repair-wire.js +79 -2
- package/dist/leader/wire.d.ts +79 -0
- package/dist/leader/wire.js +255 -8
- package/dist/lsp/e2b-bridge.d.ts +16 -0
- package/dist/lsp/e2b-bridge.js +32 -4
- package/dist/lsp/e2b-manager.d.ts +10 -0
- package/dist/lsp/e2b-manager.js +18 -2
- package/dist/lsp/lsp-frames.d.ts +12 -0
- package/dist/lsp/lsp-frames.js +12 -0
- package/dist/lsp/manager.d.ts +12 -0
- package/dist/lsp/manager.js +35 -2
- package/dist/lsp/types.d.ts +10 -0
- package/dist/lsp/ws-transport.d.ts +12 -0
- package/dist/lsp/ws-transport.js +53 -5
- package/dist/lsp-evict.d.ts +14 -0
- package/dist/lsp-evict.js +15 -1
- package/dist/main.js +530 -2129
- package/dist/memory-export.d.ts +1 -0
- package/dist/memory-export.js +4 -0
- package/dist/memory-scope.d.ts +49 -0
- package/dist/memory-scope.js +87 -4
- package/dist/memory-sync-client.d.ts +24 -0
- package/dist/memory-sync-client.js +41 -2
- package/dist/memory-sync.d.ts +23 -0
- package/dist/memory-sync.js +70 -1
- package/dist/model-select.d.ts +39 -0
- package/dist/model-select.js +42 -1
- package/dist/observability/cost-quota.d.ts +20 -0
- package/dist/observability/cost-quota.js +4 -0
- package/dist/observability/cost-taxonomy.d.ts +45 -0
- package/dist/observability/cost-taxonomy.js +34 -0
- package/dist/observability/logger.d.ts +1 -0
- package/dist/observability/logger.js +6 -0
- package/dist/observability/metrics.d.ts +13 -0
- package/dist/observability/metrics.js +63 -0
- package/dist/observability/otel-exporter.d.ts +9 -0
- package/dist/observability/otel-exporter.js +11 -3
- package/dist/observability/principal-context.d.ts +9 -0
- package/dist/observability/principal-context.js +9 -0
- package/dist/observability/prompt-manifest.d.ts +37 -0
- package/dist/observability/prompt-manifest.js +35 -1
- package/dist/observability/rate-limit.d.ts +10 -0
- package/dist/observability/rate-limit.js +1 -0
- package/dist/observability/tool-trace.d.ts +24 -0
- package/dist/observability/tool-trace.js +41 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
- package/dist/orchestration/hardened-vm-runner.js +119 -4
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
- package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
- package/dist/orchestration/hardened-vm-worker.js +27 -0
- package/dist/orchestration/subagent-steer.d.ts +44 -0
- package/dist/orchestration/subagent-steer.js +45 -1
- package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
- package/dist/orchestration/workflow-agent-steer.js +80 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
- package/dist/orchestration/workflow-completion-inbox.js +283 -32
- package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
- package/dist/orchestration/workflow-notify-journal.js +187 -13
- package/dist/parked-decide.d.ts +61 -0
- package/dist/parked-decide.js +58 -1
- package/dist/per-task-image.d.ts +54 -0
- package/dist/per-task-image.js +41 -0
- package/dist/plan-cache-probe.d.ts +35 -0
- package/dist/plan-cache-probe.js +18 -3
- package/dist/plugins/approval-exemption-store.d.ts +7 -0
- package/dist/plugins/approval-exemption-store.js +28 -2
- package/dist/plugins/approval-store-sql.d.ts +64 -0
- package/dist/plugins/approval-store-sql.js +32 -0
- package/dist/plugins/background-agent-store-sql.d.ts +55 -0
- package/dist/plugins/background-agent-store-sql.js +91 -4
- package/dist/plugins/background-shell-support.d.ts +98 -0
- package/dist/plugins/background-shell-support.js +117 -13
- package/dist/plugins/blob-backend.d.ts +104 -0
- package/dist/plugins/blob-backend.js +163 -6
- package/dist/plugins/breaker-state-sql.d.ts +65 -1
- package/dist/plugins/breaker-state-sql.js +46 -8
- package/dist/plugins/caching-session-store.d.ts +42 -0
- package/dist/plugins/caching-session-store.js +63 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
- package/dist/plugins/checkpoint-store-sql.js +239 -11
- package/dist/plugins/file-outcome-sink.d.ts +4 -0
- package/dist/plugins/file-outcome-sink.js +9 -0
- package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
- package/dist/plugins/file-resume-anchor-store.js +43 -4
- package/dist/plugins/file-run-store.d.ts +90 -0
- package/dist/plugins/file-run-store.js +145 -13
- package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
- package/dist/plugins/file-snapshot-store-sql.js +178 -10
- package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
- package/dist/plugins/file-workflow-journal-store.js +10 -0
- package/dist/plugins/fork-routing-session-store.d.ts +47 -0
- package/dist/plugins/fork-routing-session-store.js +51 -3
- package/dist/plugins/host-platform.d.ts +69 -0
- package/dist/plugins/host-platform.js +81 -2
- package/dist/plugins/image-bake-store-sql.d.ts +136 -1
- package/dist/plugins/image-bake-store-sql.js +241 -7
- package/dist/plugins/image-index-sql.d.ts +46 -0
- package/dist/plugins/image-index-sql.js +113 -4
- package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
- package/dist/plugins/k8s-bg-scripts.js +88 -4
- package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
- package/dist/plugins/k8s-exec-protocol.js +41 -0
- package/dist/plugins/local-checkpoint-store.d.ts +40 -0
- package/dist/plugins/local-checkpoint-store.js +86 -7
- package/dist/plugins/local-session-store.d.ts +157 -0
- package/dist/plugins/local-session-store.js +289 -34
- package/dist/plugins/local-task-attachment-store.js +14 -2
- package/dist/plugins/mailbox-store-sql.d.ts +38 -0
- package/dist/plugins/mailbox-store-sql.js +39 -6
- package/dist/plugins/memory-engine-pg.d.ts +30 -0
- package/dist/plugins/memory-engine-pg.js +122 -4
- package/dist/plugins/memory-engine-tidb.d.ts +26 -0
- package/dist/plugins/memory-engine-tidb.js +115 -5
- package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
- package/dist/plugins/memory-engine-vector-util.js +5 -0
- package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
- package/dist/plugins/memory-resume-anchor-store.js +17 -0
- package/dist/plugins/memory-run-store.d.ts +63 -0
- package/dist/plugins/memory-run-store.js +73 -8
- package/dist/plugins/memory-session-policy-store.d.ts +17 -0
- package/dist/plugins/memory-session-policy-store.js +17 -0
- package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
- package/dist/plugins/memory-sync-store-pg.js +45 -2
- package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
- package/dist/plugins/memory-sync-store-tidb.js +31 -1
- package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
- package/dist/plugins/outcome-ledger-sql.js +97 -3
- package/dist/plugins/pg-approval-store.d.ts +7 -0
- package/dist/plugins/pg-approval-store.js +7 -0
- package/dist/plugins/pg-breaker-state.d.ts +6 -0
- package/dist/plugins/pg-breaker-state.js +6 -0
- package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
- package/dist/plugins/pg-checkpoint-store.js +8 -0
- package/dist/plugins/pg-cost-quota.d.ts +17 -0
- package/dist/plugins/pg-cost-quota.js +6 -0
- package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/pg-file-snapshot-store.js +6 -0
- package/dist/plugins/pg-image-bake.d.ts +9 -0
- package/dist/plugins/pg-image-bake.js +9 -0
- package/dist/plugins/pg-image-index.d.ts +9 -0
- package/dist/plugins/pg-image-index.js +9 -0
- package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
- package/dist/plugins/pg-outcome-ledger.js +9 -0
- package/dist/plugins/pg-pool.d.ts +50 -0
- package/dist/plugins/pg-pool.js +78 -0
- package/dist/plugins/pg-query.d.ts +11 -0
- package/dist/plugins/pg-rate-limiter.d.ts +23 -0
- package/dist/plugins/pg-rate-limiter.js +12 -2
- package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/pg-resume-anchor-store.js +5 -0
- package/dist/plugins/pg-run-store.d.ts +7 -0
- package/dist/plugins/pg-run-store.js +7 -0
- package/dist/plugins/pg-safe-json.d.ts +13 -0
- package/dist/plugins/pg-safe-json.js +40 -4
- package/dist/plugins/pg-session-policy-store.d.ts +5 -0
- package/dist/plugins/pg-session-policy-store.js +5 -0
- package/dist/plugins/pg-session-storage.d.ts +72 -0
- package/dist/plugins/pg-session-storage.js +152 -20
- package/dist/plugins/pg-session-store.d.ts +10 -0
- package/dist/plugins/pg-session-store.js +10 -0
- package/dist/plugins/pg-tool-result-store.d.ts +7 -0
- package/dist/plugins/pg-tool-result-store.js +7 -0
- package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-journal-store.js +7 -0
- package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-run-store.js +7 -0
- package/dist/plugins/posix-shell-fs.d.ts +3 -0
- package/dist/plugins/posix-shell-fs.js +31 -1
- package/dist/plugins/remote-env-adb.d.ts +25 -0
- package/dist/plugins/remote-env-adb.js +95 -12
- package/dist/plugins/remote-env-e2b.d.ts +146 -0
- package/dist/plugins/remote-env-e2b.js +371 -40
- package/dist/plugins/remote-env-file-error.d.ts +34 -0
- package/dist/plugins/remote-env-file-error.js +37 -0
- package/dist/plugins/remote-env-host.d.ts +151 -0
- package/dist/plugins/remote-env-host.js +468 -70
- package/dist/plugins/remote-env-k8s.d.ts +135 -0
- package/dist/plugins/remote-env-k8s.js +318 -32
- package/dist/plugins/remote-env-local-docker.d.ts +65 -0
- package/dist/plugins/remote-env-local-docker.js +149 -24
- package/dist/plugins/remote-env-ssh.d.ts +35 -0
- package/dist/plugins/remote-env-ssh.js +117 -20
- package/dist/plugins/remote-scratchpad.d.ts +38 -0
- package/dist/plugins/remote-scratchpad.js +32 -2
- package/dist/plugins/remote-shell.d.ts +22 -0
- package/dist/plugins/remote-shell.js +27 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
- package/dist/plugins/resume-anchor-store-sql.js +11 -0
- package/dist/plugins/roster-store-sql.d.ts +27 -0
- package/dist/plugins/roster-store-sql.js +54 -0
- package/dist/plugins/run-store-sql.d.ts +194 -0
- package/dist/plugins/run-store-sql.js +210 -9
- package/dist/plugins/s3-presign.d.ts +20 -0
- package/dist/plugins/s3-presign.js +49 -2
- package/dist/plugins/scheduler-support.d.ts +12 -0
- package/dist/plugins/scheduler-support.js +75 -3
- package/dist/plugins/send-file-ledger.d.ts +15 -0
- package/dist/plugins/send-file-ledger.js +53 -4
- package/dist/plugins/send-user-file.d.ts +77 -0
- package/dist/plugins/send-user-file.js +92 -4
- package/dist/plugins/session-policy-store-sql.d.ts +15 -0
- package/dist/plugins/session-policy-store-sql.js +75 -3
- package/dist/plugins/session-store.d.ts +45 -0
- package/dist/plugins/session-store.js +51 -0
- package/dist/plugins/sql-driver.d.ts +77 -0
- package/dist/plugins/sql-driver.js +4 -0
- package/dist/plugins/sql-escape.d.ts +8 -0
- package/dist/plugins/sql-escape.js +8 -0
- package/dist/plugins/sql-row-helpers.d.ts +25 -0
- package/dist/plugins/sql-row-helpers.js +25 -0
- package/dist/plugins/store-backend.d.ts +103 -0
- package/dist/plugins/store-backend.js +120 -27
- package/dist/plugins/store-contracts.d.ts +62 -0
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +60 -0
- package/dist/plugins/task-attachment-store.js +49 -3
- package/dist/plugins/task-list-store-sql.d.ts +25 -0
- package/dist/plugins/task-list-store-sql.js +21 -0
- package/dist/plugins/tidb-approval-store.d.ts +6 -0
- package/dist/plugins/tidb-approval-store.js +6 -0
- package/dist/plugins/tidb-breaker-state.d.ts +5 -0
- package/dist/plugins/tidb-breaker-state.js +5 -0
- package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
- package/dist/plugins/tidb-checkpoint-store.js +7 -0
- package/dist/plugins/tidb-cost-quota.d.ts +6 -0
- package/dist/plugins/tidb-cost-quota.js +1 -0
- package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/tidb-file-snapshot-store.js +6 -0
- package/dist/plugins/tidb-image-bake.d.ts +8 -0
- package/dist/plugins/tidb-image-bake.js +8 -0
- package/dist/plugins/tidb-image-index.d.ts +8 -0
- package/dist/plugins/tidb-image-index.js +8 -0
- package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
- package/dist/plugins/tidb-outcome-ledger.js +10 -0
- package/dist/plugins/tidb-pool.d.ts +56 -0
- package/dist/plugins/tidb-pool.js +181 -1
- package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
- package/dist/plugins/tidb-rate-limiter.js +5 -2
- package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/tidb-resume-anchor-store.js +5 -0
- package/dist/plugins/tidb-run-store.d.ts +7 -0
- package/dist/plugins/tidb-run-store.js +7 -0
- package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
- package/dist/plugins/tidb-session-policy-store.js +5 -0
- package/dist/plugins/tidb-session-storage.d.ts +43 -0
- package/dist/plugins/tidb-session-storage.js +62 -3
- package/dist/plugins/tidb-session-store.d.ts +142 -0
- package/dist/plugins/tidb-session-store.js +264 -16
- package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
- package/dist/plugins/tidb-tool-result-store.js +7 -0
- package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/tidb-workflow-journal-store.js +7 -0
- package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
- package/dist/plugins/tidb-workflow-run-store.js +8 -0
- package/dist/plugins/tool-result-store-sql.d.ts +58 -0
- package/dist/plugins/tool-result-store-sql.js +38 -2
- package/dist/plugins/web-search.d.ts +35 -0
- package/dist/plugins/web-search.js +45 -9
- package/dist/plugins/workflow-journal-limits.d.ts +10 -0
- package/dist/plugins/workflow-journal-limits.js +10 -0
- package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
- package/dist/plugins/workflow-journal-store-sql.js +58 -2
- package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
- package/dist/plugins/workflow-run-store-sql.js +84 -6
- package/dist/plugins/worktree-isolation.d.ts +45 -0
- package/dist/plugins/worktree-isolation.js +105 -6
- package/dist/plugins/write-behind-counter.d.ts +56 -1
- package/dist/plugins/write-behind-counter.js +53 -14
- package/dist/principal-jwt.d.ts +24 -0
- package/dist/principal-jwt.js +60 -5
- package/dist/project-memory.d.ts +22 -0
- package/dist/project-memory.js +144 -15
- package/dist/prompts-domain-validate.d.ts +28 -0
- package/dist/prompts-domain-validate.js +42 -1
- package/dist/question.d.ts +33 -0
- package/dist/question.js +69 -2
- package/dist/resource-suspend.d.ts +21 -0
- package/dist/resource-suspend.js +16 -0
- package/dist/router/route-orchestration.d.ts +78 -0
- package/dist/router/route-orchestration.js +77 -0
- package/dist/run-local.d.ts +32 -0
- package/dist/run-local.js +172 -8
- package/dist/runs.d.ts +189 -4
- package/dist/runs.js +465 -24
- package/dist/runtime-caps-resolver.d.ts +106 -0
- package/dist/runtime-caps-resolver.js +89 -4
- package/dist/runtime-governance.d.ts +84 -0
- package/dist/runtime-governance.js +127 -1
- package/dist/sandbox-pkg-source.d.ts +23 -0
- package/dist/sandbox-pkg-source.js +37 -0
- package/dist/sealed-key.d.ts +54 -0
- package/dist/sealed-key.js +68 -3
- package/dist/security.d.ts +108 -0
- package/dist/security.js +145 -6
- package/dist/sema-registry.d.ts +21 -0
- package/dist/sema-registry.js +21 -0
- package/dist/session-leaf-bus.d.ts +31 -0
- package/dist/session-leaf-bus.js +32 -0
- package/dist/session-sync-content.d.ts +46 -0
- package/dist/session-sync-content.js +47 -1
- package/dist/session-sync-kernel.d.ts +89 -0
- package/dist/session-sync-kernel.js +48 -3
- package/dist/session-sync.d.ts +125 -0
- package/dist/session-sync.js +181 -8
- package/dist/session-titler.d.ts +26 -0
- package/dist/session-titler.js +41 -7
- package/dist/session-watch.d.ts +53 -1
- package/dist/session-watch.js +73 -9
- package/dist/sighup-idle.d.ts +30 -0
- package/dist/sighup-idle.js +12 -1
- package/dist/spec-fields.d.ts +91 -3
- package/dist/spec-fields.js +116 -4
- package/dist/task-cwd.d.ts +50 -0
- package/dist/task-cwd.js +68 -1
- package/dist/task-mcp.d.ts +47 -0
- package/dist/task-mcp.js +29 -0
- package/dist/task-settings.d.ts +175 -0
- package/dist/task-settings.js +226 -11
- package/dist/task-workflow.d.ts +67 -0
- package/dist/task-workflow.js +75 -8
- package/dist/tool-approval.d.ts +91 -0
- package/dist/tool-approval.js +215 -0
- package/dist/trace/artifacts.d.ts +9 -0
- package/dist/trace/artifacts.js +30 -5
- package/dist/trace/core-keyset-guard.d.ts +18 -0
- package/dist/trace/ledger-sink.d.ts +43 -0
- package/dist/trace/ledger-sink.js +64 -5
- package/dist/trace/project.d.ts +133 -0
- package/dist/trace/project.js +189 -2
- package/dist/trace/redact.d.ts +19 -0
- package/dist/trace/redact.js +66 -9
- package/dist/usage-analytics.d.ts +26 -0
- package/dist/usage-analytics.js +26 -3
- package/package.json +1 -1
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC B5/B4 抽象点② (docs/design/ENV-SELECT-AND-REGION-SOURCE.md): the deployment-region package-source →
|
|
3
|
+
* sandbox env derivation. ENV-FIRST: pod/sandbox env OVERRIDES the image's baked `ENV` (k8s container env wins
|
|
4
|
+
* over image config and is visible to every exec'd process; e2b sandboxEnv likewise) — so the env-overridable
|
|
5
|
+
* ecosystem pieces (pip/uv/npm/corepack/go/rustup/flutter/playwright/nuget) switch region on EXISTING images,
|
|
6
|
+
* no rebake needed. Only the file-bound pieces (apt sources, /etc/gemrc, composer global config, cargo
|
|
7
|
+
* config.toml) still need the in-image `pkg-source.sh` hook (rebaked images; bake prep chowns those files).
|
|
8
|
+
*
|
|
9
|
+
* Profiles:
|
|
10
|
+
* cn → inject only the SEMA_PKG_SOURCE marker (the pool's images bake the CN set as their defaults).
|
|
11
|
+
* global → official endpoints for every env-overridable ecosystem (overrides the baked CN ENV values).
|
|
12
|
+
* custom → SEMA_* explicit URLs (from the service process env) forwarded verbatim + mapped onto the same
|
|
13
|
+
* ecosystem variables where a mapping is unambiguous (apt has no env form — hook-only).
|
|
14
|
+
*
|
|
15
|
+
* The marker `SEMA_PKG_SOURCE` always rides along: the image's pkg-source.sh hook (pod-start / profile.d)
|
|
16
|
+
* materializes the file-bound pieces from it; images without the hook simply ignore it.
|
|
17
|
+
*/
|
|
18
|
+
/** Explicit URLs for `custom` (RFC B: 极端情况出口). Read from the service process env (operator-trusted). */
|
|
1
19
|
export interface CustomPkgSource {
|
|
2
20
|
aptMirror?: string;
|
|
3
21
|
pipIndex?: string;
|
|
@@ -6,6 +24,11 @@ export interface CustomPkgSource {
|
|
|
6
24
|
npmRegistry?: string;
|
|
7
25
|
nodeMirror?: string;
|
|
8
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Derive the operator-trusted sandbox env for a package-source profile. Returns `{}` for an unknown/empty
|
|
29
|
+
* profile (unset = byte-identical sandbox — the B5 backward-compat contract).
|
|
30
|
+
*/
|
|
9
31
|
export declare function derivePkgSourceEnv(profile: string | undefined, custom?: CustomPkgSource): Record<string, string>;
|
|
32
|
+
/** Read the `custom` explicit-URL set from the service process env (operator-trusted deployment config). */
|
|
10
33
|
export declare function customPkgSourceFromEnv(env?: NodeJS.ProcessEnv): CustomPkgSource;
|
|
11
34
|
//# sourceMappingURL=sandbox-pkg-source.d.ts.map
|
|
@@ -1,23 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC B5/B4 抽象点② (docs/design/ENV-SELECT-AND-REGION-SOURCE.md): the deployment-region package-source →
|
|
3
|
+
* sandbox env derivation. ENV-FIRST: pod/sandbox env OVERRIDES the image's baked `ENV` (k8s container env wins
|
|
4
|
+
* over image config and is visible to every exec'd process; e2b sandboxEnv likewise) — so the env-overridable
|
|
5
|
+
* ecosystem pieces (pip/uv/npm/corepack/go/rustup/flutter/playwright/nuget) switch region on EXISTING images,
|
|
6
|
+
* no rebake needed. Only the file-bound pieces (apt sources, /etc/gemrc, composer global config, cargo
|
|
7
|
+
* config.toml) still need the in-image `pkg-source.sh` hook (rebaked images; bake prep chowns those files).
|
|
8
|
+
*
|
|
9
|
+
* Profiles:
|
|
10
|
+
* cn → inject only the SEMA_PKG_SOURCE marker (the pool's images bake the CN set as their defaults).
|
|
11
|
+
* global → official endpoints for every env-overridable ecosystem (overrides the baked CN ENV values).
|
|
12
|
+
* custom → SEMA_* explicit URLs (from the service process env) forwarded verbatim + mapped onto the same
|
|
13
|
+
* ecosystem variables where a mapping is unambiguous (apt has no env form — hook-only).
|
|
14
|
+
*
|
|
15
|
+
* The marker `SEMA_PKG_SOURCE` always rides along: the image's pkg-source.sh hook (pod-start / profile.d)
|
|
16
|
+
* materializes the file-bound pieces from it; images without the hook simply ignore it.
|
|
17
|
+
*/
|
|
18
|
+
/** The official (`global`) endpoint set — overrides the pool images' baked CN ENV values. */
|
|
1
19
|
const GLOBAL_ENV = {
|
|
20
|
+
// python: pip + uv (uv does NOT read pip's variables). The python band bakes the deprecated
|
|
21
|
+
// UV_INDEX_URL alias; override BOTH aliases to the same value so whichever uv reads, it reads official.
|
|
2
22
|
PIP_INDEX_URL: "https://pypi.org/simple",
|
|
3
23
|
UV_DEFAULT_INDEX: "https://pypi.org/simple",
|
|
4
24
|
UV_INDEX_URL: "https://pypi.org/simple",
|
|
25
|
+
// node: npm env config beats npmrc files; corepack has its own baked ENV (node band).
|
|
5
26
|
NPM_CONFIG_REGISTRY: "https://registry.npmjs.org",
|
|
6
27
|
COREPACK_NPM_REGISTRY: "https://registry.npmjs.org",
|
|
28
|
+
// go band bakes goproxy.cn + sum.golang.google.cn
|
|
7
29
|
GOPROXY: "https://proxy.golang.org,direct",
|
|
8
30
|
GOSUMDB: "sum.golang.org",
|
|
31
|
+
// rust band bakes rsproxy.cn (rustup); the crates registry file (cargo config.toml) is hook territory.
|
|
9
32
|
RUSTUP_DIST_SERVER: "https://static.rust-lang.org",
|
|
10
33
|
RUSTUP_UPDATE_ROOT: "https://static.rust-lang.org/rustup",
|
|
34
|
+
// flutter band bakes flutter-io.cn
|
|
11
35
|
FLUTTER_STORAGE_BASE_URL: "https://storage.googleapis.com",
|
|
12
36
|
PUB_HOSTED_URL: "https://pub.dev",
|
|
37
|
+
// browser/python bands bake the npmmirror playwright host; empty string falls through playwright's `||` to
|
|
38
|
+
// its official CDN (playwright treats a falsy env as unset).
|
|
13
39
|
PLAYWRIGHT_DOWNLOAD_HOST: "",
|
|
40
|
+
// dotnet band's informational feed pointer
|
|
14
41
|
NUGET_FEED: "https://api.nuget.org/v3/index.json",
|
|
15
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* Derive the operator-trusted sandbox env for a package-source profile. Returns `{}` for an unknown/empty
|
|
45
|
+
* profile (unset = byte-identical sandbox — the B5 backward-compat contract).
|
|
46
|
+
*/
|
|
16
47
|
export function derivePkgSourceEnv(profile, custom) {
|
|
17
48
|
if (!profile)
|
|
18
49
|
return {};
|
|
19
50
|
switch (profile) {
|
|
20
51
|
case "cn":
|
|
52
|
+
// the images bake the CN set as their defaults — only the marker (hook re-materializes apt, idempotent).
|
|
21
53
|
return { SEMA_PKG_SOURCE: "cn" };
|
|
22
54
|
case "global":
|
|
23
55
|
return { SEMA_PKG_SOURCE: "global", ...GLOBAL_ENV };
|
|
@@ -26,12 +58,14 @@ export function derivePkgSourceEnv(profile, custom) {
|
|
|
26
58
|
const uvIndex = c.uvIndex ?? c.pipIndex;
|
|
27
59
|
return {
|
|
28
60
|
SEMA_PKG_SOURCE: "custom",
|
|
61
|
+
// SEMA_* verbatim for the in-image hook (file-bound pieces: apt/gem/composer/cargo)
|
|
29
62
|
...(c.aptMirror ? { SEMA_APT_MIRROR: c.aptMirror } : {}),
|
|
30
63
|
...(c.pipIndex ? { SEMA_PIP_INDEX: c.pipIndex } : {}),
|
|
31
64
|
...(uvIndex ? { SEMA_UV_INDEX: uvIndex } : {}),
|
|
32
65
|
...(c.uvPyMirror ? { SEMA_UV_PY_MIRROR: c.uvPyMirror } : {}),
|
|
33
66
|
...(c.npmRegistry ? { SEMA_NPM_REGISTRY: c.npmRegistry } : {}),
|
|
34
67
|
...(c.nodeMirror ? { SEMA_NODE_MIRROR: c.nodeMirror } : {}),
|
|
68
|
+
// and the unambiguous env-first mappings (work on existing images, no hook needed)
|
|
35
69
|
...(c.pipIndex ? { PIP_INDEX_URL: c.pipIndex } : {}),
|
|
36
70
|
...(uvIndex ? { UV_DEFAULT_INDEX: uvIndex, UV_INDEX_URL: uvIndex } : {}),
|
|
37
71
|
...(c.uvPyMirror ? { UV_PYTHON_INSTALL_MIRROR: c.uvPyMirror } : {}),
|
|
@@ -40,9 +74,12 @@ export function derivePkgSourceEnv(profile, custom) {
|
|
|
40
74
|
};
|
|
41
75
|
}
|
|
42
76
|
default:
|
|
77
|
+
// unknown profile — inject only the marker; the in-image hook logs + no-ops on it (fail-safe, not fail-closed:
|
|
78
|
+
// a typo'd region must not silently flip a deployment to another region's sources).
|
|
43
79
|
return { SEMA_PKG_SOURCE: profile };
|
|
44
80
|
}
|
|
45
81
|
}
|
|
82
|
+
/** Read the `custom` explicit-URL set from the service process env (operator-trusted deployment config). */
|
|
46
83
|
export function customPkgSourceFromEnv(env = process.env) {
|
|
47
84
|
return {
|
|
48
85
|
...(env.SEMA_APT_MIRROR ? { aptMirror: env.SEMA_APT_MIRROR } : {}),
|
package/dist/sealed-key.d.ts
CHANGED
|
@@ -1,37 +1,90 @@
|
|
|
1
1
|
import type { Logger } from "./observability/logger.js";
|
|
2
|
+
/** Algorithm tag — MUST equal registry-core's `SEALED_BOX_ALG` (v1 sole value; a different alg on
|
|
3
|
+
* the wire is a loud per-model rejection in applyEffective, never a guess). */
|
|
2
4
|
export declare const SEALED_KEY_ALG = "libsodium-sealedbox-x25519";
|
|
5
|
+
/** The subset applyEffective needs (keeps sema-registry decoupled from fs/boot concerns). */
|
|
3
6
|
export interface SealedKeyOpener {
|
|
4
7
|
has(publicKeyId: string): boolean;
|
|
8
|
+
/** All private-key ids this host holds (surfaces in the no-private-key warn for operator triage). */
|
|
5
9
|
ids(): string[];
|
|
10
|
+
/** Unseal a base64 `crypto_box_seal` ciphertext with the EXACT keypair registered under
|
|
11
|
+
* `publicKeyId`. Returns the plaintext (utf-8). THROWS on unknown id / malformed base64 /
|
|
12
|
+
* MAC failure — fail-loud is the contract; the caller decides what "loud" looks like.
|
|
13
|
+
* 🔴 The returned plaintext is a live secret: memory-only, never log it, never persist it. */
|
|
6
14
|
open(ciphertextB64: string, publicKeyId: string): string;
|
|
7
15
|
}
|
|
8
16
|
export interface SealedKeyStore extends SealedKeyOpener {
|
|
17
|
+
/** The keypair NEW ciphertexts should be sealed against (max `createdAt`, ties broken by id) —
|
|
18
|
+
* this is the key we report/print for center registration. `publicKey` is base64 (32 raw bytes,
|
|
19
|
+
* 44 chars): public by definition, safe to log. */
|
|
9
20
|
latest: {
|
|
10
21
|
publicKeyId: string;
|
|
11
22
|
publicKey: string;
|
|
12
23
|
createdAt: string;
|
|
13
24
|
};
|
|
14
25
|
}
|
|
26
|
+
/** Why a model's sealed key could not be unsealed (the poison-pill diagnosis, see SealedKeyPoison). */
|
|
15
27
|
export type SealedKeyPoisonReason = "sealed_decrypt_failed" | "stale_ciphertext" | "unsupported_alg" | "no_key_store";
|
|
28
|
+
/**
|
|
29
|
+
* Poison-pill entry for the per-model key map (`config.modelApiKeys`): planted by applyEffective when
|
|
30
|
+
* a model CARRIES `sealedApiKey` but the ciphertext cannot be unsealed. We deliberately do NOT drop
|
|
31
|
+
* the model from the map — dropping made "sealed key broken" indistinguishable from "no per-model key
|
|
32
|
+
* configured", and when the deployment also has a gateway MODEL_API_KEY the model's tasks silently
|
|
33
|
+
* fell back onto the shared account (the exact hole the no-apiKeyEnv-fallback contract exists to
|
|
34
|
+
* close). createKeyResolver turns this marker into a task-level `SealedKeyPoisonedError` — never
|
|
35
|
+
* `undefined`, because undefined IS the "use the gateway key" semantic. Carries DIAGNOSIS only:
|
|
36
|
+
* never the ciphertext, never any plaintext.
|
|
37
|
+
*/
|
|
16
38
|
export interface SealedKeyPoison {
|
|
17
39
|
readonly sealedKeyPoison: true;
|
|
18
40
|
readonly publicKeyId: string;
|
|
19
41
|
readonly reason: SealedKeyPoisonReason;
|
|
42
|
+
/** Error CLASS of the unseal failure (e.g. "Error") — never the message (message text is logged
|
|
43
|
+
* at plant time; keeping the object minimal keeps every serialization face trivially secret-free). */
|
|
20
44
|
readonly errKind?: string;
|
|
45
|
+
/** ISO timestamp of the apply that detected the failure. */
|
|
21
46
|
readonly at: string;
|
|
22
47
|
}
|
|
23
48
|
export declare function sealedKeyPoison(publicKeyId: string, reason: SealedKeyPoisonReason, errKind?: string): SealedKeyPoison;
|
|
24
49
|
export declare function isSealedKeyPoison(v: unknown): v is SealedKeyPoison;
|
|
50
|
+
/**
|
|
51
|
+
* The task-level fail-loud face of a poison pill: thrown by the key resolver on EVERY brain call that
|
|
52
|
+
* would otherwise authenticate this model, so a broken sealed key fails the task visibly (same family
|
|
53
|
+
* as a rotation-leg auth failure) instead of silently burning the gateway account. Message carries the
|
|
54
|
+
* sealed-failure marker (reason + publicKeyId + detection time) plus the operator fix — and nothing
|
|
55
|
+
* secret (no ciphertext, no plaintext, by construction of SealedKeyPoison).
|
|
56
|
+
*/
|
|
25
57
|
export declare class SealedKeyPoisonedError extends Error {
|
|
26
58
|
readonly publicKeyId: string;
|
|
27
59
|
readonly reason: SealedKeyPoisonReason;
|
|
28
60
|
readonly at: string;
|
|
29
61
|
constructor(modelName: string, poison: SealedKeyPoison);
|
|
30
62
|
}
|
|
63
|
+
/** Default id = fingerprint of the RAW public-key bytes: `exec-<sha256(pk)[0..12) hex>`.
|
|
64
|
+
* Deterministic → regenerating the id from the same key file is stable across boots. */
|
|
31
65
|
export declare function deriveKeyId(publicKeyRaw: Uint8Array): string;
|
|
66
|
+
/**
|
|
67
|
+
* Load every keypair under `dir` (creating dir + ONE fresh keypair when none exist) and return the
|
|
68
|
+
* custody store. Invalid/corrupt files are skipped with a warn (they may be an OLD format or a
|
|
69
|
+
* half-write — deleting operator key material on a parse error would destroy decryptability, so we
|
|
70
|
+
* never do; we just don't serve them). Throws only when the store cannot exist at all (fs errors,
|
|
71
|
+
* zero loadable keys AND generation failed).
|
|
72
|
+
*/
|
|
32
73
|
export declare function ensureSealedKeyStore(dir: string, logger?: Logger): Promise<SealedKeyStore>;
|
|
74
|
+
/**
|
|
75
|
+
* Best-effort public-key registration with the sema-registry (`POST /api/config/execution-keys`).
|
|
76
|
+
*
|
|
77
|
+
* HONESTY over fake automation: that endpoint is ADMIN-gated, and a fleet worker only holds
|
|
78
|
+
* SERVICE_PULL_TOKEN — so automatic registration works ONLY when the operator deliberately provides
|
|
79
|
+
* an admin token (SEMA_REGISTRY_ADMIN_TOKEN / REGISTRY_ADMIN_TOKEN in this service's env). Without
|
|
80
|
+
* one we do the next-best REAL thing: print the FULL public key + id at boot (a public key is not a
|
|
81
|
+
* secret) with the exact registration instructions, and warn that the web "paste key" face stays
|
|
82
|
+
* dark for this host until an admin registers it. Never throws (fire-and-forget from boot).
|
|
83
|
+
*/
|
|
33
84
|
export declare function reportExecutionPublicKey(opts: {
|
|
85
|
+
/** sema-registry base URL (config.configCenter.baseUrl). Absent = no center → manual print only. */
|
|
34
86
|
baseUrl?: string;
|
|
87
|
+
/** Admin bearer for the center's config write face. Absent = manual print (see above). */
|
|
35
88
|
adminToken?: string;
|
|
36
89
|
key: {
|
|
37
90
|
publicKeyId: string;
|
|
@@ -40,6 +93,7 @@ export declare function reportExecutionPublicKey(opts: {
|
|
|
40
93
|
};
|
|
41
94
|
notes?: string;
|
|
42
95
|
logger?: Logger;
|
|
96
|
+
/** Test seam. */
|
|
43
97
|
fetchImpl?: typeof fetch;
|
|
44
98
|
}): Promise<void>;
|
|
45
99
|
//# sourceMappingURL=sealed-key.d.ts.map
|
package/dist/sealed-key.js
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sealed-box key custody — the EXECUTION-SIDE half (registry-core 0.10.5/0.10.6):
|
|
3
|
+
* the user pastes a model API key in the web UI, the BROWSER seals it against this host's X25519
|
|
4
|
+
* public key (libsodium `crypto_box_seal`), the center stores ONLY the ciphertext
|
|
5
|
+
* (`ModelEntry.sealedApiKey`, write-only face), and THIS module unseals it at apply time so the
|
|
6
|
+
* plaintext exists nowhere but this process's memory (`config.modelApiKeys` → getApiKeyAndHeaders).
|
|
7
|
+
*
|
|
8
|
+
* Custody layout: `<localDataRoot>/sealed-key/<publicKeyId>.json` — ONE FILE PER KEYPAIR (0600,
|
|
9
|
+
* dir 0700). Several keypairs MAY coexist: rotation registers a NEW public key with the center
|
|
10
|
+
* (new ciphertexts are sealed against the newest `createdAt`) while OLD ciphertexts still carry
|
|
11
|
+
* their old `publicKeyId` — they stay decryptable exactly as long as the operator keeps the old
|
|
12
|
+
* private-key file around (the registry-core contract: "旧密文可解性=执行侧留存旧私钥决定").
|
|
13
|
+
* Selection is EXACT by `publicKeyId` — no try-every-key scanning: an id with no file is a loud
|
|
14
|
+
* per-model failure upstream (applyEffective), never a silent fallback.
|
|
15
|
+
*
|
|
16
|
+
* Crypto choice: sealed box (`crypto_box_seal`) is a libsodium-specific construction (ephemeral
|
|
17
|
+
* X25519 keypair + XSalsa20-Poly1305, nonce = BLAKE2b(epk‖rpk)) — node:crypto has no BLAKE2b and
|
|
18
|
+
* no sealed box, and tweetnacl (already in the tree via ssh2) lacks BLAKE2b too, so we depend on
|
|
19
|
+
* `libsodium-wrappers` (pure JS + WASM: no native build step, CI/cross-arch friendly, and the
|
|
20
|
+
* same library the browser side uses — byte-compatible by construction).
|
|
21
|
+
*/
|
|
1
22
|
import { createHash } from "node:crypto";
|
|
2
23
|
import { chmod, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
24
|
import { join } from "node:path";
|
|
4
25
|
import _sodium from "libsodium-wrappers";
|
|
26
|
+
/** Algorithm tag — MUST equal registry-core's `SEALED_BOX_ALG` (v1 sole value; a different alg on
|
|
27
|
+
* the wire is a loud per-model rejection in applyEffective, never a guess). */
|
|
5
28
|
export const SEALED_KEY_ALG = "libsodium-sealedbox-x25519";
|
|
29
|
+
/** crypto_box_seal overhead: 32B ephemeral pk + 16B MAC. Anything shorter cannot be a sealed box. */
|
|
6
30
|
const SEAL_OVERHEAD_BYTES = 48;
|
|
31
|
+
/** Strict base64 shape (standard alphabet, optional padding) — `Buffer.from(b64)` is lenient and
|
|
32
|
+
* would silently swallow garbage, turning "corrupt ciphertext" into a misleading MAC failure. */
|
|
7
33
|
const BASE64_STRICT = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
8
34
|
export function sealedKeyPoison(publicKeyId, reason, errKind) {
|
|
9
35
|
return { sealedKeyPoison: true, publicKeyId, reason, ...(errKind ? { errKind } : {}), at: new Date().toISOString() };
|
|
@@ -11,6 +37,13 @@ export function sealedKeyPoison(publicKeyId, reason, errKind) {
|
|
|
11
37
|
export function isSealedKeyPoison(v) {
|
|
12
38
|
return typeof v === "object" && v !== null && v.sealedKeyPoison === true;
|
|
13
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* The task-level fail-loud face of a poison pill: thrown by the key resolver on EVERY brain call that
|
|
42
|
+
* would otherwise authenticate this model, so a broken sealed key fails the task visibly (same family
|
|
43
|
+
* as a rotation-leg auth failure) instead of silently burning the gateway account. Message carries the
|
|
44
|
+
* sealed-failure marker (reason + publicKeyId + detection time) plus the operator fix — and nothing
|
|
45
|
+
* secret (no ciphertext, no plaintext, by construction of SealedKeyPoison).
|
|
46
|
+
*/
|
|
14
47
|
export class SealedKeyPoisonedError extends Error {
|
|
15
48
|
publicKeyId;
|
|
16
49
|
reason;
|
|
@@ -25,6 +58,8 @@ export class SealedKeyPoisonedError extends Error {
|
|
|
25
58
|
this.at = poison.at;
|
|
26
59
|
}
|
|
27
60
|
}
|
|
61
|
+
/** Default id = fingerprint of the RAW public-key bytes: `exec-<sha256(pk)[0..12) hex>`.
|
|
62
|
+
* Deterministic → regenerating the id from the same key file is stable across boots. */
|
|
28
63
|
export function deriveKeyId(publicKeyRaw) {
|
|
29
64
|
return `exec-${createHash("sha256").update(publicKeyRaw).digest("hex").slice(0, 12)}`;
|
|
30
65
|
}
|
|
@@ -33,11 +68,18 @@ function b64ToBytes(b64, what) {
|
|
|
33
68
|
throw new Error(`${what}: not valid base64`);
|
|
34
69
|
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
35
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Load every keypair under `dir` (creating dir + ONE fresh keypair when none exist) and return the
|
|
73
|
+
* custody store. Invalid/corrupt files are skipped with a warn (they may be an OLD format or a
|
|
74
|
+
* half-write — deleting operator key material on a parse error would destroy decryptability, so we
|
|
75
|
+
* never do; we just don't serve them). Throws only when the store cannot exist at all (fs errors,
|
|
76
|
+
* zero loadable keys AND generation failed).
|
|
77
|
+
*/
|
|
36
78
|
export async function ensureSealedKeyStore(dir, logger) {
|
|
37
79
|
await _sodium.ready;
|
|
38
80
|
const sodium = _sodium;
|
|
39
81
|
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
40
|
-
await chmod(dir, 0o700);
|
|
82
|
+
await chmod(dir, 0o700); // mkdir's mode is ignored when the dir pre-exists — enforce anyway
|
|
41
83
|
const keys = new Map();
|
|
42
84
|
for (const name of (await readdir(dir)).filter((n) => n.endsWith(".json")).sort()) {
|
|
43
85
|
const path = join(dir, name);
|
|
@@ -50,6 +92,8 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
50
92
|
const privateKey = b64ToBytes(raw.privateKey, "privateKey");
|
|
51
93
|
if (publicKey.length !== sodium.crypto_box_PUBLICKEYBYTES || privateKey.length !== sodium.crypto_box_SECRETKEYBYTES)
|
|
52
94
|
throw new Error("bad key length");
|
|
95
|
+
// The file's OWN publicKeyId is authoritative (operators may hand-register custom ids with the
|
|
96
|
+
// center); a filename drift is only cosmetic — warn, honor the content.
|
|
53
97
|
if (name !== `${raw.publicKeyId}.json`)
|
|
54
98
|
logger?.warn("sealed_key_filename_drift", { file: name, publicKeyId: raw.publicKeyId, note: "content publicKeyId wins; rename the file to silence this" });
|
|
55
99
|
if (keys.has(raw.publicKeyId)) {
|
|
@@ -59,6 +103,10 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
59
103
|
keys.set(raw.publicKeyId, { publicKey, privateKey, publicKeyB64: raw.publicKey, createdAt: typeof raw.createdAt === "string" ? raw.createdAt : "" });
|
|
60
104
|
}
|
|
61
105
|
catch (err) {
|
|
106
|
+
// Never delete: could be operator key material in an older/foreign format — unreadable here ≠ worthless.
|
|
107
|
+
// 🔴 审计 #4 LOW: JSON.parse's SyntaxError EMBEDS ~20 chars of the offending input — a file corrupted
|
|
108
|
+
// near the `privateKey` field would leak a base64 fragment of the secret into the log. Record only
|
|
109
|
+
// the error CLASS (err.name), never the message.
|
|
62
110
|
logger?.warn("sealed_key_file_unreadable", { file: path, errKind: err instanceof Error ? err.name : "unknown", note: "skipped (NOT deleted) — ciphertexts sealed for this key will fail loud per-model" });
|
|
63
111
|
}
|
|
64
112
|
}
|
|
@@ -75,10 +123,11 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
75
123
|
};
|
|
76
124
|
const path = join(dir, `${record.publicKeyId}.json`);
|
|
77
125
|
await writeFile(path, JSON.stringify(record, null, 2) + "\n", { mode: 0o600 });
|
|
78
|
-
await chmod(path, 0o600);
|
|
126
|
+
await chmod(path, 0o600); // writeFile mode is masked by umask — enforce the exact custody mode
|
|
79
127
|
keys.set(record.publicKeyId, { publicKey: kp.publicKey, privateKey: kp.privateKey, publicKeyB64, createdAt: record.createdAt });
|
|
80
128
|
logger?.info("sealed_key_generated", { publicKeyId: record.publicKeyId, publicKey: publicKeyB64, dir, note: "new X25519 sealed-box keypair — register the PUBLIC key with the registry (see sealed_key_public_key)" });
|
|
81
129
|
}
|
|
130
|
+
// Newest createdAt = the key new ciphertexts must target (registry contract); ties → lexicographic id.
|
|
82
131
|
const latestEntry = [...keys.entries()].sort((a, b) => (a[1].createdAt < b[1].createdAt ? 1 : a[1].createdAt > b[1].createdAt ? -1 : a[0] < b[0] ? -1 : 1))[0];
|
|
83
132
|
return {
|
|
84
133
|
latest: { publicKeyId: latestEntry[0], publicKey: latestEntry[1].publicKeyB64, createdAt: latestEntry[1].createdAt },
|
|
@@ -91,13 +140,25 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
91
140
|
const ciphertext = b64ToBytes(ciphertextB64, "ciphertext");
|
|
92
141
|
if (ciphertext.length < SEAL_OVERHEAD_BYTES)
|
|
93
142
|
throw new Error(`ciphertext too short (${ciphertext.length}B < sealed-box ${SEAL_OVERHEAD_BYTES}B overhead)`);
|
|
143
|
+
// Throws on MAC failure (wrong key / corrupt ciphertext) — exactly the loudness we want.
|
|
94
144
|
return sodium.to_string(sodium.crypto_box_seal_open(ciphertext, key.publicKey, key.privateKey));
|
|
95
145
|
},
|
|
96
146
|
};
|
|
97
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Best-effort public-key registration with the sema-registry (`POST /api/config/execution-keys`).
|
|
150
|
+
*
|
|
151
|
+
* HONESTY over fake automation: that endpoint is ADMIN-gated, and a fleet worker only holds
|
|
152
|
+
* SERVICE_PULL_TOKEN — so automatic registration works ONLY when the operator deliberately provides
|
|
153
|
+
* an admin token (SEMA_REGISTRY_ADMIN_TOKEN / REGISTRY_ADMIN_TOKEN in this service's env). Without
|
|
154
|
+
* one we do the next-best REAL thing: print the FULL public key + id at boot (a public key is not a
|
|
155
|
+
* secret) with the exact registration instructions, and warn that the web "paste key" face stays
|
|
156
|
+
* dark for this host until an admin registers it. Never throws (fire-and-forget from boot).
|
|
157
|
+
*/
|
|
98
158
|
export async function reportExecutionPublicKey(opts) {
|
|
99
159
|
const { baseUrl, adminToken, key, notes, logger } = opts;
|
|
100
160
|
const manual = (why) => {
|
|
161
|
+
// Full key on purpose: the OPERATOR completes registration by hand. publicKey is public material.
|
|
101
162
|
logger?.warn("sealed_key_public_key", {
|
|
102
163
|
publicKeyId: key.publicKeyId,
|
|
103
164
|
publicKey: key.publicKey,
|
|
@@ -121,17 +182,21 @@ export async function reportExecutionPublicKey(opts) {
|
|
|
121
182
|
signal: AbortSignal.timeout(10_000),
|
|
122
183
|
});
|
|
123
184
|
if (res.ok) {
|
|
185
|
+
// center 幂等语义:同 id 同 key 重复上报 = 200 {ok,key,idempotent:true}(boot 重报常态)。
|
|
124
186
|
let idempotent = false;
|
|
125
187
|
try {
|
|
126
188
|
idempotent = (await res.json())?.idempotent === true;
|
|
127
189
|
}
|
|
128
|
-
catch { }
|
|
190
|
+
catch { /* body 非 JSON 也算 reported */ }
|
|
129
191
|
logger?.info(idempotent ? "sealed_key_already_registered" : "sealed_key_reported", { publicKeyId: key.publicKeyId, status: res.status });
|
|
130
192
|
}
|
|
131
193
|
else if (res.status === 409) {
|
|
194
|
+
// 409 = 并发写 CAS 冲突(retry 语义,非「已注册」)。boot 是一次性上报,不循环重试——
|
|
195
|
+
// 下次 boot 自然重报;这里降级为 manual 面(诚实姿势:本次没写成)。
|
|
132
196
|
manual("registry returned 409 (concurrent write; will re-report on next boot)");
|
|
133
197
|
}
|
|
134
198
|
else {
|
|
199
|
+
// 400 同 id 异 key = 指纹碰撞或密钥文件被改,绝不静默——manual 面带上下文。
|
|
135
200
|
manual(`registry rejected the report (HTTP ${res.status})`);
|
|
136
201
|
}
|
|
137
202
|
}
|
package/dist/security.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import type { TaskRequestBody } from "./http/wire-types.js";
|
|
|
5
5
|
import type { StagingHandle } from "./session-sync-kernel.js";
|
|
6
6
|
export { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
7
7
|
export type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
|
|
8
|
+
/** One row of the session-list projection (CC /resume picker) — the durable session abstraction's enumeration
|
|
9
|
+
* output (§0.5). Mirrors {@link RunStore}'s shipped `SessionSummary` shape so the wire response is unchanged. */
|
|
8
10
|
export interface SessionListItem {
|
|
9
11
|
sessionId: string;
|
|
10
12
|
owner: string | null;
|
|
@@ -13,12 +15,18 @@ export interface SessionListItem {
|
|
|
13
15
|
runCount: number;
|
|
14
16
|
objectivePreview: string | null;
|
|
15
17
|
lastStatus: string;
|
|
18
|
+
/** K-5c (shell §K): the latest run's task_id — the shell's one-hop live-tail re-attach anchor on resume. */
|
|
16
19
|
lastRunId: string | null;
|
|
20
|
+
/** Auto-generated session title (null = untitled / lister face has no session_meta). */
|
|
17
21
|
title: string | null;
|
|
18
22
|
}
|
|
23
|
+
/** A SessionStore that may additionally expose tenant-ownership ops (the TiDB store does) AND the
|
|
24
|
+
* `SessionRepo` enumeration/lifecycle seam (§0.5: list/fork/delete homed on the session abstraction's own
|
|
25
|
+
* tables, not the `task_run` runs ledger). All optional — an in-memory dev store implements none. */
|
|
19
26
|
export type OwnerAwareSessionStore = SessionStore & {
|
|
20
27
|
ownerOf?: (sessionId: string) => Promise<string | null | undefined>;
|
|
21
28
|
register?: (sessionId: string, owner: string | null) => Promise<void>;
|
|
29
|
+
/** E16 — enumerate the caller's sessions (owner-filtered on the session store's OWN owner column). */
|
|
22
30
|
listSessions?: (opts: {
|
|
23
31
|
owner?: string;
|
|
24
32
|
cursor?: {
|
|
@@ -28,27 +36,73 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
28
36
|
limit: number;
|
|
29
37
|
q?: string;
|
|
30
38
|
}) => Promise<SessionListItem[]>;
|
|
39
|
+
/** E17 — fork a session's whole history to a NEW session owned by `owner`; null if the source is unknown. */
|
|
31
40
|
fork?: (sourceId: string, owner: string | null) => Promise<string | null>;
|
|
41
|
+
/** E18 — the session's current leaf `SessionTreeEntry.id` (a cache-bypassing single read), so the resume-at
|
|
42
|
+
* turn-capture can pair it with the turn's message eventId. null when the session has no leaf / does not exist. */
|
|
32
43
|
getLeafId?: (sessionId: string) => Promise<string | null>;
|
|
44
|
+
/** [1196] 六轮复审:owner+leafId 单行原子快照(SSE watch 探针租户围栏读;两独立读在 delete/reclaim
|
|
45
|
+
* 缝里可拼出混世代组合)。undefined=无此会话。 */
|
|
33
46
|
getHead?: (sessionId: string) => Promise<{
|
|
34
47
|
owner: string | null;
|
|
35
48
|
leafId: string | null;
|
|
36
49
|
} | undefined>;
|
|
50
|
+
/** E21 — purge a session's conversation history (session_meta/session_event); idempotent (false if absent).
|
|
51
|
+
* `owner` is the single-DB-fleet null-safe SQL owner guard on `session_meta.owner` (defense-in-depth — the
|
|
52
|
+
* route already owner-gates; this pins the DELETE to the authenticated tenant so even a buggy gate can't purge
|
|
53
|
+
* another tenant's history). */
|
|
37
54
|
deleteSession?: (sessionId: string, owner: string | null) => Promise<boolean>;
|
|
55
|
+
/** 2c session-sync — EXPORT a session's full durable entry log (compaction floor bypassed) for
|
|
56
|
+
* cross-backend migration; `null` when the source is unknown (the read half of fork, as `SessionTreeEntry[]`). */
|
|
38
57
|
exportEntries?: (sessionId: string) => Promise<SessionTreeEntry[] | null>;
|
|
58
|
+
/** 2c session-sync P1d-α (PULL streaming) — the IDS-ONLY projection of a session's full durable log, oldest-first
|
|
59
|
+
* (`SELECT entry_id … ORDER BY seq ASC`). `null` when the source is unknown (mirrors {@link exportEntries}' null).
|
|
60
|
+
* Small even for a huge session (no payloads) → the PULL `GET /sync/manifest` carries this instead of the entries,
|
|
61
|
+
* and the local peer feeds it to `classifySyncRelationshipByIds` to decide fast-forward / fork before pulling. */
|
|
39
62
|
listEntryIds?: (sessionId: string) => Promise<string[] | null>;
|
|
63
|
+
/** 2c session-sync P1d-α (PULL streaming) — STREAM a session's full durable entry log (compaction floor bypassed),
|
|
64
|
+
* oldest-first, as an async iterable of {@link SessionTreeEntry} so the `GET /sync/entries` NDJSON route holds
|
|
65
|
+
* BOUNDED memory regardless of session size (mysql2/pg buffer a plain SELECT → this KEYSET-pages internally,
|
|
66
|
+
* `WHERE seq > cursor … LIMIT batchSize`, advancing the cursor each batch, ONE pooled query per batch — a slow
|
|
67
|
+
* consumer never pins a connection). `opts.afterSeq` resumes after a given 0-based dense seq (default -1 = from 0);
|
|
68
|
+
* `opts.batchSize` is the page size (default 500). Resolves to `null` (NOT an empty iterable) when the session does
|
|
69
|
+
* not exist (the existence probe is async — `session_meta` first, like {@link exportEntries} — so the method returns
|
|
70
|
+
* a Promise of the iterable-or-null; the iterable itself then pages lazily). The read half of exportEntries, paged. */
|
|
40
71
|
exportEntriesStream?: (sessionId: string, opts?: {
|
|
41
72
|
afterSeq?: number;
|
|
42
73
|
batchSize?: number;
|
|
43
74
|
}) => Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
75
|
+
/** 2c session-sync — IMPORT a verbatim entry log into `sessionId`, re-stamping `owner` to the
|
|
76
|
+
* authenticated importing principal (never the bundle's). The log is passed through core's
|
|
77
|
+
* `validateEntriesForImport` (the single fail-closed invariant gate) before any write. */
|
|
44
78
|
importEntries?: (sessionId: string, owner: string | null, entries: SessionTreeEntry[]) => Promise<void>;
|
|
79
|
+
/** 2c session-sync (§7/§8) — IDEMPOTENT replace: atomically purge any existing conversation log for `sessionId`
|
|
80
|
+
* then import `entries` verbatim under `owner`. Unlike importEntries (plain INSERT, fresh-only) this is safe to
|
|
81
|
+
* re-run / apply over an existing session (fast-forward, retry). owner-guarded delete (defense-in-depth). */
|
|
45
82
|
replaceEntries?: (sessionId: string, owner: string | null, entries: SessionTreeEntry[]) => Promise<void>;
|
|
83
|
+
/** 2c session-sync P1d-β (PUSH streaming) — begin a STAGED import into `realSessionId` under a shadow id
|
|
84
|
+
* `${realSessionId}#stg-${token}` (the route mints the uuidv7 `token`). Returns a {@link StagingHandle} the NDJSON
|
|
85
|
+
* Phase-B route streams batches into (`appendBatch`) then commits (`commit`, the atomic swap) / aborts. The shadow
|
|
86
|
+
* rows have NO session_meta → invisible to wake until commit writes meta LAST = the sole commit point. */
|
|
46
87
|
beginImportStaging?: (realSessionId: string, token: string) => StagingHandle;
|
|
88
|
+
/** 2c session-sync P1d-β (staged-row inspection) — read the rows STAGED under a `${realSessionId}#stg-${token}` id
|
|
89
|
+
* (NO session_meta probe — `exportEntries` returns null for an unregistered id), oldest-first. The import gate is now
|
|
90
|
+
* the per-line `StreamingImportValidator` (core 1.143.0) driven during the stream, so this is no longer the
|
|
91
|
+
* validation path; it remains the staged-row inspection seam (idempotency/dedup tests, diagnostics). Returns `[]` for
|
|
92
|
+
* an empty/unknown staging id. */
|
|
47
93
|
readStagedEntries?: (stagingId: string) => Promise<SessionTreeEntry[]>;
|
|
94
|
+
/** 2c session-sync P1d-β (§4) — reaper for ABANDONED staging sessions: drop staging-id session_event rows with NO
|
|
95
|
+
* session_meta whose oldest row is older than the grace window (an in-flight stream stays fresh → never reaped).
|
|
96
|
+
* Returns the affected row count. Durable twins only (local stages in memory → no durable rows to reap → absent). */
|
|
48
97
|
sweepStagingSessions?: () => Promise<number>;
|
|
49
98
|
};
|
|
99
|
+
/** True iff `s` matches the canonical uuidv7 shape core mints (see {@link UUIDV7_RE}). */
|
|
50
100
|
export declare function isUuidV7(s: string): boolean;
|
|
51
101
|
export declare function isUuidShape(s: string): boolean;
|
|
102
|
+
/** An HTTP error the server maps to a status code (instead of a generic 500). `code` (optional) is a stable
|
|
103
|
+
* machine-readable identifier the HTTP layer echoes as `{code}` beside the human `{error}` message — the
|
|
104
|
+
* "typed rejection" posture (structured code on the wire, prose stays with the shell/web).
|
|
105
|
+
* `extra` (optional) is folded into the error body verbatim (e.g. the scenario allowlist on a reject). */
|
|
52
106
|
export declare class HttpError extends Error {
|
|
53
107
|
readonly status: number;
|
|
54
108
|
readonly code?: string;
|
|
@@ -58,21 +112,75 @@ export declare class HttpError extends Error {
|
|
|
58
112
|
extra?: Record<string, unknown>;
|
|
59
113
|
});
|
|
60
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Authorization context resolved per request, BEFORE building the TaskSpec. The service owns this —
|
|
117
|
+
* identity and tenant scope come from the authenticated channel, **never from the request body**.
|
|
118
|
+
*/
|
|
61
119
|
export interface AuthContext {
|
|
120
|
+
/** Authenticated principal, e.g. `user:42` / `org:7`. Undefined when principal auth is off (dev). */
|
|
62
121
|
principal?: string;
|
|
122
|
+
/** The session to run against (resolved + ownership-checked here, then returned to the caller). */
|
|
63
123
|
sessionId: string;
|
|
124
|
+
/** Long-term memory scope, derived from the principal (not the body). Undefined disables memory. */
|
|
64
125
|
memoryScope?: string;
|
|
126
|
+
/** 142-S4:the request's SHAPE-VALIDATED projectId (body.projectId 过 PROJECT_ID_REGEX 门后回传)。
|
|
127
|
+
* 身份半场(scope 的 tenant 段)永远来自 verified principal — projectId 只选「哪个项目盘/哪条登记」
|
|
128
|
+
* (config.projects 查表键 + proj: 键的 projectId 段),不是 capability。main.ts 拿它查 defaultScopes。 */
|
|
65
129
|
resolvedProjectId?: string;
|
|
66
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* S6 — close the "sessionId / scope are bearer capabilities" hole.
|
|
133
|
+
*
|
|
134
|
+
* The principal is read from a trusted header set by the authenticated caller (e.g. the OA backend
|
|
135
|
+
* that already holds the service token). It is NOT taken from the request body, so a caller cannot
|
|
136
|
+
* forge identity by passing `scope`/`sessionId` for another tenant.
|
|
137
|
+
*
|
|
138
|
+
* Then:
|
|
139
|
+
* - a supplied `sessionId` is ownership-checked against `session_meta.owner` (403 on mismatch);
|
|
140
|
+
* an unknown id is claimed for this principal; a missing id mints a fresh owned session;
|
|
141
|
+
* - the memory scope is derived from the principal.
|
|
142
|
+
*
|
|
143
|
+
* Returns a function shaped for `ServiceDeps.authorize`. When `sessionStore` is not the TiDB store
|
|
144
|
+
* (e.g. in-memory dev backend) ownership can't be enforced, so it only derives principal + sessionId.
|
|
145
|
+
*/
|
|
67
146
|
export declare function createAuthorizer(config: ServiceConfig, sessionStore: OwnerAwareSessionStore): (ctx: {
|
|
68
147
|
req: IncomingMessage;
|
|
69
148
|
body: TaskRequestBody;
|
|
70
149
|
}) => Promise<AuthContext>;
|
|
150
|
+
/** F1/F3 (codex scope-ledger audit 2026-07-14) — the auth-boundary principal SHAPE gate, applied to every
|
|
151
|
+
* verified identity source (trusted header, SSO-bridge sub, direct-door JWT sub) so no downstream consumer
|
|
152
|
+
* ever sees an ambiguous or over-wide principal:
|
|
153
|
+
* - RESERVED internal identifiers are REJECTED (修1, 三路复审 A 组 HIGH — see {@link RESERVED_PRINCIPALS} /
|
|
154
|
+
* {@link RESERVED_PRINCIPAL_PREFIXES} below): a REAL tenant whose principal string-equals an internal scope
|
|
155
|
+
* sentinel would pass the plain string-compare owner/scope gates downstream and merge with internal rows —
|
|
156
|
+
* e.g. `"_"` merges with the anonymous scope family (the checkpoint scope column `auth?.principal ?? "_"`
|
|
157
|
+
* at suspend, and the decide owner-gate treats `cp.scope === "_"` as anonymous-OPEN, server.ts ~L3710; the
|
|
158
|
+
* SendUserFile ledger scope + the /v1/sendfile-links fleet-wide default; the resource-suspend isolation
|
|
159
|
+
* key), `"_leader"` merges with the leader durable-approval owner scope (a tenant so named could list/
|
|
160
|
+
* decide internal leader approvals), `"_leader-…"` with the leader resource-suspend scope family, and
|
|
161
|
+
* `"__none__"` with the missing-principal placeholder scope on the decide/pending gates.
|
|
162
|
+
* - length > 190 is REJECTED: every scope/owner column the principal lands in VERBATIM is VARCHAR(190)
|
|
163
|
+
* (sendfile_link.scope, approval.owner/scope, memory-engine scope, rate-limit keys, …) — an over-long
|
|
164
|
+
* principal would truncate/500 at the INSERT and split one identity into two.
|
|
165
|
+
* Throws a typed 400 `HttpError` (the HTTP layer maps it); the message names the rule (a reserved identifier /
|
|
166
|
+
* the length cap), never a secret and never the internal scope's semantics. */
|
|
71
167
|
export declare const PRINCIPAL_MAX_LENGTH = 190;
|
|
168
|
+
/** 修1 — the SINGLE registry of internal sentinel/scope identifiers a tenant principal must never equal.
|
|
169
|
+
* 🔴 新增内部 sentinel scope 必须在此登记(精确值加 RESERVED_PRINCIPALS,前缀族加
|
|
170
|
+
* RESERVED_PRINCIPAL_PREFIXES),否则 assertPrincipalShape 会放行同名租户 = 与内部 scope 行合流的越权面。
|
|
171
|
+
* Current entries (where each is minted): `"_"` = single-user/anonymous sentinel (checkpoint/sendfile/
|
|
172
|
+
* resource-suspend scope family); `"__none__"` = missing-principal placeholder on the decide/pending gates
|
|
173
|
+
* (http/server.ts `principal ?? "__none__"`); `"_leader"` = leader durable-approval scope
|
|
174
|
+
* (src/leader/wire.ts); prefix `"_leader-"` = the leader resource-suspend scope family
|
|
175
|
+
* (`_leader-resource-<workerId>`, src/leader/wire.ts). NB the prefix REQUIRES the hyphen — a tenant named
|
|
176
|
+
* `_leaderX` collides with nothing internal and stays valid (boundary pinned by test). */
|
|
72
177
|
export declare const RESERVED_PRINCIPALS: readonly string[];
|
|
73
178
|
export declare const RESERVED_PRINCIPAL_PREFIXES: readonly string[];
|
|
74
179
|
export declare function assertPrincipalShape(principal: string): void;
|
|
180
|
+
/** Read the authenticated principal from the trusted header. Never from the body. */
|
|
75
181
|
export declare function principalFrom(req: IncomingMessage, config: ServiceConfig): string | undefined;
|
|
182
|
+
/** Header carrying the crypto-verified principal JWT on a direct-door worker (the issuer signs it; the worker only
|
|
183
|
+
* verifies). The trusted twin of `config.principalHeader` (the latter is client-spoofable on a direct door). */
|
|
76
184
|
export declare const PRINCIPAL_TOKEN_HEADER = "x-approval-principal-token";
|
|
77
185
|
export declare function setSsoPrincipal(req: IncomingMessage, principal: string): void;
|
|
78
186
|
export declare function ssoVerifiedPrincipal(req: IncomingMessage): string | undefined;
|