@sema-agent/server 7.43.0 → 7.44.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/USAGE.md +18 -0
- package/dist/adoption/plan.js +31 -192
- package/dist/adoption/quiesce.js +3 -86
- package/dist/adoption/runner.js +3 -140
- package/dist/adoption/sql.js +0 -74
- package/dist/adoption/wire.js +0 -80
- package/dist/approval-ask-machine.js +0 -75
- package/dist/approval-card.js +0 -323
- package/dist/approval-deny-reasons.js +0 -42
- package/dist/approval-hmac.js +0 -35
- package/dist/approval-reconciler.js +8 -166
- package/dist/approval.js +4 -67
- package/dist/audit.js +1 -44
- package/dist/auth-bridge.js +4 -47
- package/dist/auth-keys.js +0 -23
- package/dist/bake-runner/main.js +4 -65
- package/dist/bake-runner/protocol.js +3 -58
- package/dist/bake-runner/runner.js +5 -91
- package/dist/bench/l8/artifact.js +2 -61
- package/dist/bench/l8/escape.js +0 -25
- package/dist/bench/l8/index.js +0 -14
- package/dist/bench/l8/probes.js +0 -60
- package/dist/bench/l8/run-probes.js +2 -45
- package/dist/bench/s1/arms.js +14 -189
- package/dist/bench/s1/live-deps.js +11 -253
- package/dist/bench/s1/oracle.js +1 -36
- package/dist/bench/s1/repair-oracle-adapter.js +0 -30
- package/dist/bench/s1/reviewer.js +0 -34
- package/dist/bench/s1/row.js +0 -62
- package/dist/bench/s1/run-firm.js +4 -70
- package/dist/bench/s1/runner-ctx.js +0 -40
- package/dist/bench/s1/tasks.js +0 -115
- package/dist/boot/adoption.js +0 -20
- package/dist/boot/budget-tracing.js +3 -55
- package/dist/boot/config-center.js +43 -551
- package/dist/boot/coordinators.js +1 -69
- package/dist/boot/crash-last.js +0 -18
- package/dist/boot/deferred-sandbox-path-env.js +3 -119
- package/dist/boot/execution-env.js +5 -171
- package/dist/boot/governance-seams.js +0 -92
- package/dist/boot/leader.js +0 -69
- package/dist/boot/limit-sync.js +0 -2
- package/dist/boot/memory-boundary.js +3 -91
- package/dist/boot/org-memory.js +1 -25
- package/dist/boot/parked-revive-gate.js +0 -150
- package/dist/boot/permission-rules-audit.js +1 -56
- package/dist/boot/reapers.js +15 -273
- package/dist/boot/resolve-spec.js +9 -768
- package/dist/boot/retention-lane.js +4 -87
- package/dist/boot/runner-deps.js +3 -297
- package/dist/boot/runtime-caps.js +0 -40
- package/dist/boot/session-faces.js +2 -133
- package/dist/boot/shutdown.js +9 -83
- package/dist/boot/side-query-lane.js +2 -137
- package/dist/boot/stores.js +15 -215
- package/dist/boot/task-list-lane.js +0 -18
- package/dist/boot/webfetch-summarize-lane.js +0 -47
- package/dist/boot/workflow-orchestration.js +3 -99
- package/dist/boot-reclaim.js +0 -20
- package/dist/bounded-session-map.js +0 -19
- package/dist/brain.js +2 -139
- package/dist/budget.js +9 -244
- package/dist/capabilities/builtin-tools.js +0 -3
- package/dist/capabilities/center-plugins.js +6 -51
- package/dist/capabilities/center-prompts.js +6 -71
- package/dist/capabilities/code-review-council.js +7 -40
- package/dist/capabilities/collab-workflows.js +1 -44
- package/dist/capabilities/hands-lane.js +0 -65
- package/dist/capabilities/memory-notice.js +0 -70
- package/dist/capabilities/prompt.js +0 -14
- package/dist/capabilities/prompts/code-review.js +0 -14
- package/dist/capabilities/prompts/identity.js +0 -6
- package/dist/capabilities/prompts/team.js +0 -4
- package/dist/capabilities/repo-tools.js +0 -34
- package/dist/capabilities/sandbox-file-send.js +3 -92
- package/dist/capabilities/scenarios.d.ts +0 -1
- package/dist/capabilities/scenarios.js +18 -279
- package/dist/capabilities/select-environment-tool.js +0 -32
- package/dist/capabilities/send-user-file-tool.js +2 -66
- package/dist/capabilities/skills.d.ts +1 -2
- package/dist/capabilities/skills.js +3 -21
- package/dist/capabilities/team.d.ts +3 -11
- package/dist/capabilities/team.js +3 -51
- package/dist/capabilities/tool-defer.js +0 -3
- package/dist/config-center/apply-effective.js +15 -330
- package/dist/config-center/apply-ledger.js +5 -38
- package/dist/config-center/facade.js +0 -41
- package/dist/config-center/hot-keys-registry.js +0 -20
- package/dist/config-center/http-client.js +2 -125
- package/dist/config-center/mcp-revocation.js +2 -34
- package/dist/config-center/read-face.js +0 -59
- package/dist/config-center/restart-signal.js +1 -85
- package/dist/config-center/skills-mcp.d.ts +1 -1
- package/dist/config-center/skills-mcp.js +9 -76
- package/dist/config-center/stage-limits.js +8 -35
- package/dist/config-invariants.js +0 -16
- package/dist/config-lkg.js +0 -42
- package/dist/config-provider.js +3 -186
- package/dist/config-types.js +0 -5
- package/dist/config.js +107 -1145
- package/dist/degenerate-instrument.js +3 -67
- package/dist/deployment-governance.js +0 -124
- package/dist/digest-form.js +0 -12
- package/dist/elicitation.js +3 -86
- package/dist/env-facts.js +7 -75
- package/dist/fleet/fleet-bus.js +34 -507
- package/dist/fleet/fleet-reconciler.js +9 -149
- package/dist/fleet/fleet-terminal-window.js +10 -178
- package/dist/fleet/subagent-tail-bus.js +3 -72
- package/dist/fleet-client.js +10 -70
- package/dist/fleet-lease.js +5 -79
- package/dist/git-api-kind.js +0 -3
- package/dist/governance-ask-marks.js +2 -78
- package/dist/hooks/branch-transcript.js +0 -74
- package/dist/hooks/cc-agent-hook-prompt.js +0 -29
- package/dist/hooks/cc-stop-prompt.js +1 -46
- package/dist/hooks/hook-llm.js +1 -53
- package/dist/hooks/hook-runner.js +20 -414
- package/dist/http/active-run-conflict.js +4 -129
- package/dist/http/cursor-fingerprint.d.ts +5 -0
- package/dist/http/cursor-fingerprint.js +5 -0
- package/dist/http/idempotency.js +0 -37
- package/dist/http/principal-gate.js +3 -40
- package/dist/http/route-ctx.js +0 -9
- package/dist/http/routes/a2a-serve.js +7 -319
- package/dist/http/routes/admin-config-refresh.js +0 -4
- package/dist/http/routes/admin-drain.js +0 -10
- package/dist/http/routes/adoption.js +1 -29
- package/dist/http/routes/agents-roster.js +1 -47
- package/dist/http/routes/approvals-assistant.js +32 -395
- package/dist/http/routes/attachments.js +4 -22
- package/dist/http/routes/capabilities.js +3 -420
- package/dist/http/routes/diagnostics.js +1 -81
- package/dist/http/routes/fleet.js +9 -185
- package/dist/http/routes/images.js +14 -239
- package/dist/http/routes/leader.js +0 -13
- package/dist/http/routes/memory-bundle.js +1 -61
- package/dist/http/routes/memory-policy.js +9 -99
- package/dist/http/routes/notify-wake.js +3 -37
- package/dist/http/routes/observability.js +2 -19
- package/dist/http/routes/retention-ops.js +2 -34
- package/dist/http/routes/rules.js +1 -93
- package/dist/http/routes/runs.js +64 -873
- package/dist/http/routes/session-sync.js +19 -258
- package/dist/http/routes/sessions-list.js +17 -43
- package/dist/http/routes/sessions.js +34 -226
- package/dist/http/routes/shared-memory.js +5 -36
- package/dist/http/routes/side-query.js +1 -87
- package/dist/http/routes/tasks.js +52 -722
- package/dist/http/routes/trace-usage.js +32 -195
- package/dist/http/routes/workflows.js +19 -195
- package/dist/http/run-meta.js +0 -6
- package/dist/http/send.js +0 -32
- package/dist/http/server.js +92 -1597
- package/dist/http/sse-lifecycle.js +2 -13
- package/dist/http/sse-log.js +3 -48
- package/dist/http/tar.js +5 -21
- package/dist/http/verify-rounds.js +0 -5
- package/dist/http/wire-gate.js +0 -9
- package/dist/http/workspace-content.js +0 -10
- package/dist/images/bake-validate.js +1 -70
- package/dist/images/manifest.js +1 -6
- package/dist/index.js +0 -21
- package/dist/key-resolver.js +2 -17
- package/dist/leader/diffout.js +1 -20
- package/dist/leader/diffup.js +0 -47
- package/dist/leader/endpoint.js +2 -57
- package/dist/leader/fanout.js +3 -45
- package/dist/leader/grader-env-factory.js +3 -72
- package/dist/leader/leader.js +5 -156
- package/dist/leader/merge.js +8 -115
- package/dist/leader/planner.js +3 -54
- package/dist/leader/repair-oracle.js +1 -60
- package/dist/leader/repair-wire.js +2 -79
- package/dist/leader/wire.js +8 -307
- package/dist/lsp/e2b-bridge.js +4 -64
- package/dist/lsp/e2b-manager.js +6 -94
- package/dist/lsp/lsp-frames.js +0 -12
- package/dist/lsp/manager.js +4 -96
- package/dist/lsp/ws-transport.js +5 -55
- package/dist/lsp-evict.js +1 -15
- package/dist/main.js +57 -765
- package/dist/memory-bundle-engine.js +0 -55
- package/dist/memory-export.js +0 -4
- package/dist/memory-posture.js +1 -15
- package/dist/memory-scope.js +11 -148
- package/dist/memory-sync-client.js +2 -44
- package/dist/memory-sync.js +1 -80
- package/dist/model-select.js +3 -80
- package/dist/observability/cost-quota.js +1 -17
- package/dist/observability/cost-taxonomy.js +0 -34
- package/dist/observability/fail-open.js +7 -86
- package/dist/observability/logger.js +0 -6
- package/dist/observability/metrics.js +0 -94
- package/dist/observability/otel-exporter.js +3 -13
- package/dist/observability/principal-context.js +0 -9
- package/dist/observability/prompt-manifest.js +1 -37
- package/dist/observability/rate-limit.js +0 -4
- package/dist/observability/secret-env-scrub.js +2 -56
- package/dist/observability/tool-trace.js +1 -70
- package/dist/orchestration/hardened-vm-runner.js +4 -118
- package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
- package/dist/orchestration/hardened-vm-worker.js +0 -27
- package/dist/orchestration/subagent-steer.js +1 -45
- package/dist/orchestration/workflow-agent-steer.js +1 -80
- package/dist/orchestration/workflow-completion-inbox.js +32 -285
- package/dist/orchestration/workflow-notify-journal.js +16 -259
- package/dist/org-memory-admission.js +3 -47
- package/dist/parent-watch.js +2 -48
- package/dist/parked-decide.js +1 -109
- package/dist/per-task-image.js +0 -57
- package/dist/plan-cache-probe.js +3 -27
- package/dist/plugins/adoption-log-sql.js +2 -119
- package/dist/plugins/approval-ask-store-memory.js +3 -38
- package/dist/plugins/approval-ask-store-sql.js +6 -188
- package/dist/plugins/approval-exemption-store.js +2 -28
- package/dist/plugins/background-agent-store-sql.js +4 -105
- package/dist/plugins/background-shell-support.js +14 -122
- package/dist/plugins/blob-backend.js +6 -169
- package/dist/plugins/breaker-state-sql.js +8 -46
- package/dist/plugins/caching-session-store.js +4 -106
- package/dist/plugins/checkpoint-store-sql.js +18 -505
- package/dist/plugins/e2b-orphan-reclaim.js +0 -45
- package/dist/plugins/file-outcome-sink.js +0 -9
- package/dist/plugins/file-resume-anchor-store.js +4 -43
- package/dist/plugins/file-run-store.js +26 -364
- package/dist/plugins/file-snapshot-store-sql.js +10 -181
- package/dist/plugins/fork-routing-session-store.js +8 -111
- package/dist/plugins/host-platform.js +2 -91
- package/dist/plugins/image-bake-store-sql.js +7 -250
- package/dist/plugins/image-index-sql.js +4 -123
- package/dist/plugins/k8s-bg-scripts.js +4 -88
- package/dist/plugins/k8s-exec-protocol.js +0 -41
- package/dist/plugins/leader-run-store-sql.js +0 -101
- package/dist/plugins/local-checkpoint-store.js +8 -128
- package/dist/plugins/local-session-store.js +34 -296
- package/dist/plugins/local-task-attachment-store.js +2 -16
- package/dist/plugins/mailbox-store-sql.js +8 -65
- package/dist/plugins/memory-embedder-fingerprint.js +5 -166
- package/dist/plugins/memory-embedder.js +4 -70
- package/dist/plugins/memory-engine-pg.js +6 -170
- package/dist/plugins/memory-engine-tidb.js +7 -155
- package/dist/plugins/memory-engine-vector-util.js +0 -10
- package/dist/plugins/memory-key-guards.js +0 -34
- package/dist/plugins/memory-origin-law.js +0 -187
- package/dist/plugins/memory-resume-anchor-store.js +0 -17
- package/dist/plugins/memory-run-store.js +12 -89
- package/dist/plugins/memory-session-policy-store.js +0 -17
- package/dist/plugins/memory-sync-store-pg.js +4 -49
- package/dist/plugins/memory-sync-store-tidb.js +3 -35
- package/dist/plugins/outcome-ledger-sql.js +3 -97
- package/dist/plugins/permission-rule-store-file.js +5 -133
- package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
- package/dist/plugins/permission-rule-store-sql.js +50 -307
- package/dist/plugins/pg-cost-quota.js +0 -7
- package/dist/plugins/pg-pool.js +0 -92
- package/dist/plugins/pg-rate-limiter.js +2 -13
- package/dist/plugins/pg-safe-json.js +4 -40
- package/dist/plugins/pg-session-storage.js +25 -189
- package/dist/plugins/posix-shell-fs.js +1 -31
- package/dist/plugins/remote-env-adb.js +12 -101
- package/dist/plugins/remote-env-e2b.js +40 -371
- package/dist/plugins/remote-env-file-error.js +0 -37
- package/dist/plugins/remote-env-host.js +63 -483
- package/dist/plugins/remote-env-k8s.js +32 -326
- package/dist/plugins/remote-env-local-docker.js +24 -157
- package/dist/plugins/remote-env-ssh.js +20 -128
- package/dist/plugins/remote-scratchpad.js +2 -32
- package/dist/plugins/remote-shell.js +1 -32
- package/dist/plugins/resume-anchor-store-sql.js +0 -11
- package/dist/plugins/retention-lane-store-sql.js +0 -108
- package/dist/plugins/retention-store-sql.js +4 -383
- package/dist/plugins/roster-store-sql.js +0 -55
- package/dist/plugins/run-store-sql.js +14 -251
- package/dist/plugins/s3-presign.js +2 -49
- package/dist/plugins/scheduler-support.js +3 -80
- package/dist/plugins/send-file-ledger.js +4 -53
- package/dist/plugins/send-user-file.js +4 -94
- package/dist/plugins/session-placement.js +1 -89
- package/dist/plugins/session-policy-store-sql.js +3 -81
- package/dist/plugins/session-store.js +0 -57
- package/dist/plugins/shared-memory-store-sql.js +4 -167
- package/dist/plugins/sql-driver.js +0 -17
- package/dist/plugins/sql-errors.js +0 -7
- package/dist/plugins/sql-escape.js +0 -8
- package/dist/plugins/sql-row-helpers.js +0 -25
- package/dist/plugins/store-backend.js +42 -222
- package/dist/plugins/store-contracts.js +2 -46
- package/dist/plugins/task-attachment-store.js +3 -49
- package/dist/plugins/task-list-store-sql.js +0 -79
- package/dist/plugins/tidb-cost-quota.js +1 -4
- package/dist/plugins/tidb-pool.js +1 -207
- package/dist/plugins/tidb-rate-limiter.js +3 -9
- package/dist/plugins/tidb-session-storage.js +4 -70
- package/dist/plugins/tidb-session-store.js +19 -341
- package/dist/plugins/tool-result-store-sql.js +4 -179
- package/dist/plugins/usage-window-store-sql.js +0 -8
- package/dist/plugins/web-search.js +10 -132
- package/dist/plugins/workflow-journal-store-sql.js +2 -58
- package/dist/plugins/workflow-run-store-sql.js +6 -91
- package/dist/plugins/worktree-isolation.js +6 -126
- package/dist/plugins/write-behind-counter.js +16 -75
- package/dist/principal-jwt.js +5 -60
- package/dist/project-memory.js +15 -146
- package/dist/prompts-domain-validate.js +1 -51
- package/dist/question.js +2 -111
- package/dist/resource-suspend.js +0 -18
- package/dist/router/route-orchestration.js +0 -77
- package/dist/rules-consent.d.ts +44 -5
- package/dist/rules-consent.js +75 -215
- package/dist/run-local.js +14 -381
- package/dist/runs.js +29 -617
- package/dist/runtime-caps-resolver.js +6 -132
- package/dist/runtime-governance.js +1 -232
- package/dist/sandbox-pkg-source.js +0 -37
- package/dist/sealed-key.js +3 -68
- package/dist/security.js +6 -291
- package/dist/session-leaf-bus.js +0 -32
- package/dist/session-sync-content.js +1 -69
- package/dist/session-sync-kernel.js +3 -60
- package/dist/session-sync.js +3 -66
- package/dist/session-titler.js +7 -41
- package/dist/session-watch.js +9 -73
- package/dist/shared-memory-scope-authorizer.js +0 -18
- package/dist/sighup-idle.js +1 -12
- package/dist/spec-fields.js +4 -143
- package/dist/store-live-probe.js +3 -49
- package/dist/task-a2a.js +1 -126
- package/dist/task-cwd.js +1 -103
- package/dist/task-mcp.js +1 -89
- package/dist/task-settings.js +10 -300
- package/dist/task-workflow.js +8 -75
- package/dist/tool-approval.d.ts +28 -1
- package/dist/tool-approval.js +70 -1430
- package/dist/trace/artifacts.js +5 -20
- package/dist/trace/engine-notice-wire.js +6 -138
- package/dist/trace/ledger-sink.js +7 -96
- package/dist/trace/project.js +4 -448
- package/dist/trace/redact.js +9 -77
- package/dist/turn-activity.js +1 -27
- package/dist/usage-analytics.js +4 -34
- package/dist/wall-clock-jump-guard.js +1 -68
- package/package.json +3 -3
- package/dist/capabilities/scenario-alias.d.ts +0 -27
- package/dist/capabilities/scenario-alias.js +0 -61
|
@@ -1,55 +1,23 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RFC B5/B4 抽象点② (sema-internal server/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. */
|
|
19
1
|
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.
|
|
22
2
|
PIP_INDEX_URL: "https://pypi.org/simple",
|
|
23
3
|
UV_DEFAULT_INDEX: "https://pypi.org/simple",
|
|
24
4
|
UV_INDEX_URL: "https://pypi.org/simple",
|
|
25
|
-
// node: npm env config beats npmrc files; corepack has its own baked ENV (node band).
|
|
26
5
|
NPM_CONFIG_REGISTRY: "https://registry.npmjs.org",
|
|
27
6
|
COREPACK_NPM_REGISTRY: "https://registry.npmjs.org",
|
|
28
|
-
// go band bakes goproxy.cn + sum.golang.google.cn
|
|
29
7
|
GOPROXY: "https://proxy.golang.org,direct",
|
|
30
8
|
GOSUMDB: "sum.golang.org",
|
|
31
|
-
// rust band bakes rsproxy.cn (rustup); the crates registry file (cargo config.toml) is hook territory.
|
|
32
9
|
RUSTUP_DIST_SERVER: "https://static.rust-lang.org",
|
|
33
10
|
RUSTUP_UPDATE_ROOT: "https://static.rust-lang.org/rustup",
|
|
34
|
-
// flutter band bakes flutter-io.cn
|
|
35
11
|
FLUTTER_STORAGE_BASE_URL: "https://storage.googleapis.com",
|
|
36
12
|
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).
|
|
39
13
|
PLAYWRIGHT_DOWNLOAD_HOST: "",
|
|
40
|
-
// dotnet band's informational feed pointer
|
|
41
14
|
NUGET_FEED: "https://api.nuget.org/v3/index.json",
|
|
42
15
|
};
|
|
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
|
-
*/
|
|
47
16
|
export function derivePkgSourceEnv(profile, custom) {
|
|
48
17
|
if (!profile)
|
|
49
18
|
return {};
|
|
50
19
|
switch (profile) {
|
|
51
20
|
case "cn":
|
|
52
|
-
// the images bake the CN set as their defaults — only the marker (hook re-materializes apt, idempotent).
|
|
53
21
|
return { SEMA_PKG_SOURCE: "cn" };
|
|
54
22
|
case "global":
|
|
55
23
|
return { SEMA_PKG_SOURCE: "global", ...GLOBAL_ENV };
|
|
@@ -58,14 +26,12 @@ export function derivePkgSourceEnv(profile, custom) {
|
|
|
58
26
|
const uvIndex = c.uvIndex ?? c.pipIndex;
|
|
59
27
|
return {
|
|
60
28
|
SEMA_PKG_SOURCE: "custom",
|
|
61
|
-
// SEMA_* verbatim for the in-image hook (file-bound pieces: apt/gem/composer/cargo)
|
|
62
29
|
...(c.aptMirror ? { SEMA_APT_MIRROR: c.aptMirror } : {}),
|
|
63
30
|
...(c.pipIndex ? { SEMA_PIP_INDEX: c.pipIndex } : {}),
|
|
64
31
|
...(uvIndex ? { SEMA_UV_INDEX: uvIndex } : {}),
|
|
65
32
|
...(c.uvPyMirror ? { SEMA_UV_PY_MIRROR: c.uvPyMirror } : {}),
|
|
66
33
|
...(c.npmRegistry ? { SEMA_NPM_REGISTRY: c.npmRegistry } : {}),
|
|
67
34
|
...(c.nodeMirror ? { SEMA_NODE_MIRROR: c.nodeMirror } : {}),
|
|
68
|
-
// and the unambiguous env-first mappings (work on existing images, no hook needed)
|
|
69
35
|
...(c.pipIndex ? { PIP_INDEX_URL: c.pipIndex } : {}),
|
|
70
36
|
...(uvIndex ? { UV_DEFAULT_INDEX: uvIndex, UV_INDEX_URL: uvIndex } : {}),
|
|
71
37
|
...(c.uvPyMirror ? { UV_PYTHON_INSTALL_MIRROR: c.uvPyMirror } : {}),
|
|
@@ -74,12 +40,9 @@ export function derivePkgSourceEnv(profile, custom) {
|
|
|
74
40
|
};
|
|
75
41
|
}
|
|
76
42
|
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).
|
|
79
43
|
return { SEMA_PKG_SOURCE: profile };
|
|
80
44
|
}
|
|
81
45
|
}
|
|
82
|
-
/** Read the `custom` explicit-URL set from the service process env (operator-trusted deployment config). */
|
|
83
46
|
export function customPkgSourceFromEnv(env = process.env) {
|
|
84
47
|
return {
|
|
85
48
|
...(env.SEMA_APT_MIRROR ? { aptMirror: env.SEMA_APT_MIRROR } : {}),
|
package/dist/sealed-key.js
CHANGED
|
@@ -1,35 +1,9 @@
|
|
|
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
|
-
*/
|
|
22
1
|
import { createHash } from "node:crypto";
|
|
23
2
|
import { chmod, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
24
3
|
import { join } from "node:path";
|
|
25
4
|
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). */
|
|
28
5
|
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. */
|
|
30
6
|
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. */
|
|
33
7
|
const BASE64_STRICT = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
34
8
|
export function sealedKeyPoison(publicKeyId, reason, errKind) {
|
|
35
9
|
return { sealedKeyPoison: true, publicKeyId, reason, ...(errKind ? { errKind } : {}), at: new Date().toISOString() };
|
|
@@ -37,13 +11,6 @@ export function sealedKeyPoison(publicKeyId, reason, errKind) {
|
|
|
37
11
|
export function isSealedKeyPoison(v) {
|
|
38
12
|
return typeof v === "object" && v !== null && v.sealedKeyPoison === true;
|
|
39
13
|
}
|
|
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
|
-
*/
|
|
47
14
|
export class SealedKeyPoisonedError extends Error {
|
|
48
15
|
publicKeyId;
|
|
49
16
|
reason;
|
|
@@ -58,8 +25,6 @@ export class SealedKeyPoisonedError extends Error {
|
|
|
58
25
|
this.at = poison.at;
|
|
59
26
|
}
|
|
60
27
|
}
|
|
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. */
|
|
63
28
|
export function deriveKeyId(publicKeyRaw) {
|
|
64
29
|
return `exec-${createHash("sha256").update(publicKeyRaw).digest("hex").slice(0, 12)}`;
|
|
65
30
|
}
|
|
@@ -68,18 +33,11 @@ function b64ToBytes(b64, what) {
|
|
|
68
33
|
throw new Error(`${what}: not valid base64`);
|
|
69
34
|
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
70
35
|
}
|
|
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
|
-
*/
|
|
78
36
|
export async function ensureSealedKeyStore(dir, logger) {
|
|
79
37
|
await _sodium.ready;
|
|
80
38
|
const sodium = _sodium;
|
|
81
39
|
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
82
|
-
await chmod(dir, 0o700);
|
|
40
|
+
await chmod(dir, 0o700);
|
|
83
41
|
const keys = new Map();
|
|
84
42
|
for (const name of (await readdir(dir)).filter((n) => n.endsWith(".json")).sort()) {
|
|
85
43
|
const path = join(dir, name);
|
|
@@ -92,8 +50,6 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
92
50
|
const privateKey = b64ToBytes(raw.privateKey, "privateKey");
|
|
93
51
|
if (publicKey.length !== sodium.crypto_box_PUBLICKEYBYTES || privateKey.length !== sodium.crypto_box_SECRETKEYBYTES)
|
|
94
52
|
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.
|
|
97
53
|
if (name !== `${raw.publicKeyId}.json`)
|
|
98
54
|
logger?.warn("sealed_key_filename_drift", { file: name, publicKeyId: raw.publicKeyId, note: "content publicKeyId wins; rename the file to silence this" });
|
|
99
55
|
if (keys.has(raw.publicKeyId)) {
|
|
@@ -103,10 +59,6 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
103
59
|
keys.set(raw.publicKeyId, { publicKey, privateKey, publicKeyB64: raw.publicKey, createdAt: typeof raw.createdAt === "string" ? raw.createdAt : "" });
|
|
104
60
|
}
|
|
105
61
|
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.
|
|
110
62
|
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" });
|
|
111
63
|
}
|
|
112
64
|
}
|
|
@@ -123,11 +75,10 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
123
75
|
};
|
|
124
76
|
const path = join(dir, `${record.publicKeyId}.json`);
|
|
125
77
|
await writeFile(path, JSON.stringify(record, null, 2) + "\n", { mode: 0o600 });
|
|
126
|
-
await chmod(path, 0o600);
|
|
78
|
+
await chmod(path, 0o600);
|
|
127
79
|
keys.set(record.publicKeyId, { publicKey: kp.publicKey, privateKey: kp.privateKey, publicKeyB64, createdAt: record.createdAt });
|
|
128
80
|
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)" });
|
|
129
81
|
}
|
|
130
|
-
// Newest createdAt = the key new ciphertexts must target (registry contract); ties → lexicographic id.
|
|
131
82
|
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];
|
|
132
83
|
return {
|
|
133
84
|
latest: { publicKeyId: latestEntry[0], publicKey: latestEntry[1].publicKeyB64, createdAt: latestEntry[1].createdAt },
|
|
@@ -140,25 +91,13 @@ export async function ensureSealedKeyStore(dir, logger) {
|
|
|
140
91
|
const ciphertext = b64ToBytes(ciphertextB64, "ciphertext");
|
|
141
92
|
if (ciphertext.length < SEAL_OVERHEAD_BYTES)
|
|
142
93
|
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.
|
|
144
94
|
return sodium.to_string(sodium.crypto_box_seal_open(ciphertext, key.publicKey, key.privateKey));
|
|
145
95
|
},
|
|
146
96
|
};
|
|
147
97
|
}
|
|
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 in this service's env; the REGISTRY_ADMIN_TOKEN alias was tombstoned in 5.0.0). 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
|
-
*/
|
|
158
98
|
export async function reportExecutionPublicKey(opts) {
|
|
159
99
|
const { baseUrl, adminToken, key, notes, logger } = opts;
|
|
160
100
|
const manual = (why) => {
|
|
161
|
-
// Full key on purpose: the OPERATOR completes registration by hand. publicKey is public material.
|
|
162
101
|
logger?.warn("sealed_key_public_key", {
|
|
163
102
|
publicKeyId: key.publicKeyId,
|
|
164
103
|
publicKey: key.publicKey,
|
|
@@ -182,21 +121,17 @@ export async function reportExecutionPublicKey(opts) {
|
|
|
182
121
|
signal: AbortSignal.timeout(10_000),
|
|
183
122
|
});
|
|
184
123
|
if (res.ok) {
|
|
185
|
-
// center 幂等语义:同 id 同 key 重复上报 = 200 {ok,key,idempotent:true}(boot 重报常态)。
|
|
186
124
|
let idempotent = false;
|
|
187
125
|
try {
|
|
188
126
|
idempotent = (await res.json())?.idempotent === true;
|
|
189
127
|
}
|
|
190
|
-
catch {
|
|
128
|
+
catch { }
|
|
191
129
|
logger?.info(idempotent ? "sealed_key_already_registered" : "sealed_key_reported", { publicKeyId: key.publicKeyId, status: res.status });
|
|
192
130
|
}
|
|
193
131
|
else if (res.status === 409) {
|
|
194
|
-
// 409 = 并发写 CAS 冲突(retry 语义,非「已注册」)。boot 是一次性上报,不循环重试——
|
|
195
|
-
// 下次 boot 自然重报;这里降级为 manual 面(诚实姿势:本次没写成)。
|
|
196
132
|
manual("registry returned 409 (concurrent write; will re-report on next boot)");
|
|
197
133
|
}
|
|
198
134
|
else {
|
|
199
|
-
// 400 同 id 异 key = 指纹碰撞或密钥文件被改,绝不静默——manual 面带上下文。
|
|
200
135
|
manual(`registry rejected the report (HTTP ${res.status})`);
|
|
201
136
|
}
|
|
202
137
|
}
|