@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.
Files changed (345) hide show
  1. package/USAGE.md +18 -0
  2. package/dist/adoption/plan.js +31 -192
  3. package/dist/adoption/quiesce.js +3 -86
  4. package/dist/adoption/runner.js +3 -140
  5. package/dist/adoption/sql.js +0 -74
  6. package/dist/adoption/wire.js +0 -80
  7. package/dist/approval-ask-machine.js +0 -75
  8. package/dist/approval-card.js +0 -323
  9. package/dist/approval-deny-reasons.js +0 -42
  10. package/dist/approval-hmac.js +0 -35
  11. package/dist/approval-reconciler.js +8 -166
  12. package/dist/approval.js +4 -67
  13. package/dist/audit.js +1 -44
  14. package/dist/auth-bridge.js +4 -47
  15. package/dist/auth-keys.js +0 -23
  16. package/dist/bake-runner/main.js +4 -65
  17. package/dist/bake-runner/protocol.js +3 -58
  18. package/dist/bake-runner/runner.js +5 -91
  19. package/dist/bench/l8/artifact.js +2 -61
  20. package/dist/bench/l8/escape.js +0 -25
  21. package/dist/bench/l8/index.js +0 -14
  22. package/dist/bench/l8/probes.js +0 -60
  23. package/dist/bench/l8/run-probes.js +2 -45
  24. package/dist/bench/s1/arms.js +14 -189
  25. package/dist/bench/s1/live-deps.js +11 -253
  26. package/dist/bench/s1/oracle.js +1 -36
  27. package/dist/bench/s1/repair-oracle-adapter.js +0 -30
  28. package/dist/bench/s1/reviewer.js +0 -34
  29. package/dist/bench/s1/row.js +0 -62
  30. package/dist/bench/s1/run-firm.js +4 -70
  31. package/dist/bench/s1/runner-ctx.js +0 -40
  32. package/dist/bench/s1/tasks.js +0 -115
  33. package/dist/boot/adoption.js +0 -20
  34. package/dist/boot/budget-tracing.js +3 -55
  35. package/dist/boot/config-center.js +43 -551
  36. package/dist/boot/coordinators.js +1 -69
  37. package/dist/boot/crash-last.js +0 -18
  38. package/dist/boot/deferred-sandbox-path-env.js +3 -119
  39. package/dist/boot/execution-env.js +5 -171
  40. package/dist/boot/governance-seams.js +0 -92
  41. package/dist/boot/leader.js +0 -69
  42. package/dist/boot/limit-sync.js +0 -2
  43. package/dist/boot/memory-boundary.js +3 -91
  44. package/dist/boot/org-memory.js +1 -25
  45. package/dist/boot/parked-revive-gate.js +0 -150
  46. package/dist/boot/permission-rules-audit.js +1 -56
  47. package/dist/boot/reapers.js +15 -273
  48. package/dist/boot/resolve-spec.js +9 -768
  49. package/dist/boot/retention-lane.js +4 -87
  50. package/dist/boot/runner-deps.js +3 -297
  51. package/dist/boot/runtime-caps.js +0 -40
  52. package/dist/boot/session-faces.js +2 -133
  53. package/dist/boot/shutdown.js +9 -83
  54. package/dist/boot/side-query-lane.js +2 -137
  55. package/dist/boot/stores.js +15 -215
  56. package/dist/boot/task-list-lane.js +0 -18
  57. package/dist/boot/webfetch-summarize-lane.js +0 -47
  58. package/dist/boot/workflow-orchestration.js +3 -99
  59. package/dist/boot-reclaim.js +0 -20
  60. package/dist/bounded-session-map.js +0 -19
  61. package/dist/brain.js +2 -139
  62. package/dist/budget.js +9 -244
  63. package/dist/capabilities/builtin-tools.js +0 -3
  64. package/dist/capabilities/center-plugins.js +6 -51
  65. package/dist/capabilities/center-prompts.js +6 -71
  66. package/dist/capabilities/code-review-council.js +7 -40
  67. package/dist/capabilities/collab-workflows.js +1 -44
  68. package/dist/capabilities/hands-lane.js +0 -65
  69. package/dist/capabilities/memory-notice.js +0 -70
  70. package/dist/capabilities/prompt.js +0 -14
  71. package/dist/capabilities/prompts/code-review.js +0 -14
  72. package/dist/capabilities/prompts/identity.js +0 -6
  73. package/dist/capabilities/prompts/team.js +0 -4
  74. package/dist/capabilities/repo-tools.js +0 -34
  75. package/dist/capabilities/sandbox-file-send.js +3 -92
  76. package/dist/capabilities/scenarios.d.ts +0 -1
  77. package/dist/capabilities/scenarios.js +18 -279
  78. package/dist/capabilities/select-environment-tool.js +0 -32
  79. package/dist/capabilities/send-user-file-tool.js +2 -66
  80. package/dist/capabilities/skills.d.ts +1 -2
  81. package/dist/capabilities/skills.js +3 -21
  82. package/dist/capabilities/team.d.ts +3 -11
  83. package/dist/capabilities/team.js +3 -51
  84. package/dist/capabilities/tool-defer.js +0 -3
  85. package/dist/config-center/apply-effective.js +15 -330
  86. package/dist/config-center/apply-ledger.js +5 -38
  87. package/dist/config-center/facade.js +0 -41
  88. package/dist/config-center/hot-keys-registry.js +0 -20
  89. package/dist/config-center/http-client.js +2 -125
  90. package/dist/config-center/mcp-revocation.js +2 -34
  91. package/dist/config-center/read-face.js +0 -59
  92. package/dist/config-center/restart-signal.js +1 -85
  93. package/dist/config-center/skills-mcp.d.ts +1 -1
  94. package/dist/config-center/skills-mcp.js +9 -76
  95. package/dist/config-center/stage-limits.js +8 -35
  96. package/dist/config-invariants.js +0 -16
  97. package/dist/config-lkg.js +0 -42
  98. package/dist/config-provider.js +3 -186
  99. package/dist/config-types.js +0 -5
  100. package/dist/config.js +107 -1145
  101. package/dist/degenerate-instrument.js +3 -67
  102. package/dist/deployment-governance.js +0 -124
  103. package/dist/digest-form.js +0 -12
  104. package/dist/elicitation.js +3 -86
  105. package/dist/env-facts.js +7 -75
  106. package/dist/fleet/fleet-bus.js +34 -507
  107. package/dist/fleet/fleet-reconciler.js +9 -149
  108. package/dist/fleet/fleet-terminal-window.js +10 -178
  109. package/dist/fleet/subagent-tail-bus.js +3 -72
  110. package/dist/fleet-client.js +10 -70
  111. package/dist/fleet-lease.js +5 -79
  112. package/dist/git-api-kind.js +0 -3
  113. package/dist/governance-ask-marks.js +2 -78
  114. package/dist/hooks/branch-transcript.js +0 -74
  115. package/dist/hooks/cc-agent-hook-prompt.js +0 -29
  116. package/dist/hooks/cc-stop-prompt.js +1 -46
  117. package/dist/hooks/hook-llm.js +1 -53
  118. package/dist/hooks/hook-runner.js +20 -414
  119. package/dist/http/active-run-conflict.js +4 -129
  120. package/dist/http/cursor-fingerprint.d.ts +5 -0
  121. package/dist/http/cursor-fingerprint.js +5 -0
  122. package/dist/http/idempotency.js +0 -37
  123. package/dist/http/principal-gate.js +3 -40
  124. package/dist/http/route-ctx.js +0 -9
  125. package/dist/http/routes/a2a-serve.js +7 -319
  126. package/dist/http/routes/admin-config-refresh.js +0 -4
  127. package/dist/http/routes/admin-drain.js +0 -10
  128. package/dist/http/routes/adoption.js +1 -29
  129. package/dist/http/routes/agents-roster.js +1 -47
  130. package/dist/http/routes/approvals-assistant.js +32 -395
  131. package/dist/http/routes/attachments.js +4 -22
  132. package/dist/http/routes/capabilities.js +3 -420
  133. package/dist/http/routes/diagnostics.js +1 -81
  134. package/dist/http/routes/fleet.js +9 -185
  135. package/dist/http/routes/images.js +14 -239
  136. package/dist/http/routes/leader.js +0 -13
  137. package/dist/http/routes/memory-bundle.js +1 -61
  138. package/dist/http/routes/memory-policy.js +9 -99
  139. package/dist/http/routes/notify-wake.js +3 -37
  140. package/dist/http/routes/observability.js +2 -19
  141. package/dist/http/routes/retention-ops.js +2 -34
  142. package/dist/http/routes/rules.js +1 -93
  143. package/dist/http/routes/runs.js +64 -873
  144. package/dist/http/routes/session-sync.js +19 -258
  145. package/dist/http/routes/sessions-list.js +17 -43
  146. package/dist/http/routes/sessions.js +34 -226
  147. package/dist/http/routes/shared-memory.js +5 -36
  148. package/dist/http/routes/side-query.js +1 -87
  149. package/dist/http/routes/tasks.js +52 -722
  150. package/dist/http/routes/trace-usage.js +32 -195
  151. package/dist/http/routes/workflows.js +19 -195
  152. package/dist/http/run-meta.js +0 -6
  153. package/dist/http/send.js +0 -32
  154. package/dist/http/server.js +92 -1597
  155. package/dist/http/sse-lifecycle.js +2 -13
  156. package/dist/http/sse-log.js +3 -48
  157. package/dist/http/tar.js +5 -21
  158. package/dist/http/verify-rounds.js +0 -5
  159. package/dist/http/wire-gate.js +0 -9
  160. package/dist/http/workspace-content.js +0 -10
  161. package/dist/images/bake-validate.js +1 -70
  162. package/dist/images/manifest.js +1 -6
  163. package/dist/index.js +0 -21
  164. package/dist/key-resolver.js +2 -17
  165. package/dist/leader/diffout.js +1 -20
  166. package/dist/leader/diffup.js +0 -47
  167. package/dist/leader/endpoint.js +2 -57
  168. package/dist/leader/fanout.js +3 -45
  169. package/dist/leader/grader-env-factory.js +3 -72
  170. package/dist/leader/leader.js +5 -156
  171. package/dist/leader/merge.js +8 -115
  172. package/dist/leader/planner.js +3 -54
  173. package/dist/leader/repair-oracle.js +1 -60
  174. package/dist/leader/repair-wire.js +2 -79
  175. package/dist/leader/wire.js +8 -307
  176. package/dist/lsp/e2b-bridge.js +4 -64
  177. package/dist/lsp/e2b-manager.js +6 -94
  178. package/dist/lsp/lsp-frames.js +0 -12
  179. package/dist/lsp/manager.js +4 -96
  180. package/dist/lsp/ws-transport.js +5 -55
  181. package/dist/lsp-evict.js +1 -15
  182. package/dist/main.js +57 -765
  183. package/dist/memory-bundle-engine.js +0 -55
  184. package/dist/memory-export.js +0 -4
  185. package/dist/memory-posture.js +1 -15
  186. package/dist/memory-scope.js +11 -148
  187. package/dist/memory-sync-client.js +2 -44
  188. package/dist/memory-sync.js +1 -80
  189. package/dist/model-select.js +3 -80
  190. package/dist/observability/cost-quota.js +1 -17
  191. package/dist/observability/cost-taxonomy.js +0 -34
  192. package/dist/observability/fail-open.js +7 -86
  193. package/dist/observability/logger.js +0 -6
  194. package/dist/observability/metrics.js +0 -94
  195. package/dist/observability/otel-exporter.js +3 -13
  196. package/dist/observability/principal-context.js +0 -9
  197. package/dist/observability/prompt-manifest.js +1 -37
  198. package/dist/observability/rate-limit.js +0 -4
  199. package/dist/observability/secret-env-scrub.js +2 -56
  200. package/dist/observability/tool-trace.js +1 -70
  201. package/dist/orchestration/hardened-vm-runner.js +4 -118
  202. package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
  203. package/dist/orchestration/hardened-vm-worker.js +0 -27
  204. package/dist/orchestration/subagent-steer.js +1 -45
  205. package/dist/orchestration/workflow-agent-steer.js +1 -80
  206. package/dist/orchestration/workflow-completion-inbox.js +32 -285
  207. package/dist/orchestration/workflow-notify-journal.js +16 -259
  208. package/dist/org-memory-admission.js +3 -47
  209. package/dist/parent-watch.js +2 -48
  210. package/dist/parked-decide.js +1 -109
  211. package/dist/per-task-image.js +0 -57
  212. package/dist/plan-cache-probe.js +3 -27
  213. package/dist/plugins/adoption-log-sql.js +2 -119
  214. package/dist/plugins/approval-ask-store-memory.js +3 -38
  215. package/dist/plugins/approval-ask-store-sql.js +6 -188
  216. package/dist/plugins/approval-exemption-store.js +2 -28
  217. package/dist/plugins/background-agent-store-sql.js +4 -105
  218. package/dist/plugins/background-shell-support.js +14 -122
  219. package/dist/plugins/blob-backend.js +6 -169
  220. package/dist/plugins/breaker-state-sql.js +8 -46
  221. package/dist/plugins/caching-session-store.js +4 -106
  222. package/dist/plugins/checkpoint-store-sql.js +18 -505
  223. package/dist/plugins/e2b-orphan-reclaim.js +0 -45
  224. package/dist/plugins/file-outcome-sink.js +0 -9
  225. package/dist/plugins/file-resume-anchor-store.js +4 -43
  226. package/dist/plugins/file-run-store.js +26 -364
  227. package/dist/plugins/file-snapshot-store-sql.js +10 -181
  228. package/dist/plugins/fork-routing-session-store.js +8 -111
  229. package/dist/plugins/host-platform.js +2 -91
  230. package/dist/plugins/image-bake-store-sql.js +7 -250
  231. package/dist/plugins/image-index-sql.js +4 -123
  232. package/dist/plugins/k8s-bg-scripts.js +4 -88
  233. package/dist/plugins/k8s-exec-protocol.js +0 -41
  234. package/dist/plugins/leader-run-store-sql.js +0 -101
  235. package/dist/plugins/local-checkpoint-store.js +8 -128
  236. package/dist/plugins/local-session-store.js +34 -296
  237. package/dist/plugins/local-task-attachment-store.js +2 -16
  238. package/dist/plugins/mailbox-store-sql.js +8 -65
  239. package/dist/plugins/memory-embedder-fingerprint.js +5 -166
  240. package/dist/plugins/memory-embedder.js +4 -70
  241. package/dist/plugins/memory-engine-pg.js +6 -170
  242. package/dist/plugins/memory-engine-tidb.js +7 -155
  243. package/dist/plugins/memory-engine-vector-util.js +0 -10
  244. package/dist/plugins/memory-key-guards.js +0 -34
  245. package/dist/plugins/memory-origin-law.js +0 -187
  246. package/dist/plugins/memory-resume-anchor-store.js +0 -17
  247. package/dist/plugins/memory-run-store.js +12 -89
  248. package/dist/plugins/memory-session-policy-store.js +0 -17
  249. package/dist/plugins/memory-sync-store-pg.js +4 -49
  250. package/dist/plugins/memory-sync-store-tidb.js +3 -35
  251. package/dist/plugins/outcome-ledger-sql.js +3 -97
  252. package/dist/plugins/permission-rule-store-file.js +5 -133
  253. package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
  254. package/dist/plugins/permission-rule-store-sql.js +50 -307
  255. package/dist/plugins/pg-cost-quota.js +0 -7
  256. package/dist/plugins/pg-pool.js +0 -92
  257. package/dist/plugins/pg-rate-limiter.js +2 -13
  258. package/dist/plugins/pg-safe-json.js +4 -40
  259. package/dist/plugins/pg-session-storage.js +25 -189
  260. package/dist/plugins/posix-shell-fs.js +1 -31
  261. package/dist/plugins/remote-env-adb.js +12 -101
  262. package/dist/plugins/remote-env-e2b.js +40 -371
  263. package/dist/plugins/remote-env-file-error.js +0 -37
  264. package/dist/plugins/remote-env-host.js +63 -483
  265. package/dist/plugins/remote-env-k8s.js +32 -326
  266. package/dist/plugins/remote-env-local-docker.js +24 -157
  267. package/dist/plugins/remote-env-ssh.js +20 -128
  268. package/dist/plugins/remote-scratchpad.js +2 -32
  269. package/dist/plugins/remote-shell.js +1 -32
  270. package/dist/plugins/resume-anchor-store-sql.js +0 -11
  271. package/dist/plugins/retention-lane-store-sql.js +0 -108
  272. package/dist/plugins/retention-store-sql.js +4 -383
  273. package/dist/plugins/roster-store-sql.js +0 -55
  274. package/dist/plugins/run-store-sql.js +14 -251
  275. package/dist/plugins/s3-presign.js +2 -49
  276. package/dist/plugins/scheduler-support.js +3 -80
  277. package/dist/plugins/send-file-ledger.js +4 -53
  278. package/dist/plugins/send-user-file.js +4 -94
  279. package/dist/plugins/session-placement.js +1 -89
  280. package/dist/plugins/session-policy-store-sql.js +3 -81
  281. package/dist/plugins/session-store.js +0 -57
  282. package/dist/plugins/shared-memory-store-sql.js +4 -167
  283. package/dist/plugins/sql-driver.js +0 -17
  284. package/dist/plugins/sql-errors.js +0 -7
  285. package/dist/plugins/sql-escape.js +0 -8
  286. package/dist/plugins/sql-row-helpers.js +0 -25
  287. package/dist/plugins/store-backend.js +42 -222
  288. package/dist/plugins/store-contracts.js +2 -46
  289. package/dist/plugins/task-attachment-store.js +3 -49
  290. package/dist/plugins/task-list-store-sql.js +0 -79
  291. package/dist/plugins/tidb-cost-quota.js +1 -4
  292. package/dist/plugins/tidb-pool.js +1 -207
  293. package/dist/plugins/tidb-rate-limiter.js +3 -9
  294. package/dist/plugins/tidb-session-storage.js +4 -70
  295. package/dist/plugins/tidb-session-store.js +19 -341
  296. package/dist/plugins/tool-result-store-sql.js +4 -179
  297. package/dist/plugins/usage-window-store-sql.js +0 -8
  298. package/dist/plugins/web-search.js +10 -132
  299. package/dist/plugins/workflow-journal-store-sql.js +2 -58
  300. package/dist/plugins/workflow-run-store-sql.js +6 -91
  301. package/dist/plugins/worktree-isolation.js +6 -126
  302. package/dist/plugins/write-behind-counter.js +16 -75
  303. package/dist/principal-jwt.js +5 -60
  304. package/dist/project-memory.js +15 -146
  305. package/dist/prompts-domain-validate.js +1 -51
  306. package/dist/question.js +2 -111
  307. package/dist/resource-suspend.js +0 -18
  308. package/dist/router/route-orchestration.js +0 -77
  309. package/dist/rules-consent.d.ts +44 -5
  310. package/dist/rules-consent.js +75 -215
  311. package/dist/run-local.js +14 -381
  312. package/dist/runs.js +29 -617
  313. package/dist/runtime-caps-resolver.js +6 -132
  314. package/dist/runtime-governance.js +1 -232
  315. package/dist/sandbox-pkg-source.js +0 -37
  316. package/dist/sealed-key.js +3 -68
  317. package/dist/security.js +6 -291
  318. package/dist/session-leaf-bus.js +0 -32
  319. package/dist/session-sync-content.js +1 -69
  320. package/dist/session-sync-kernel.js +3 -60
  321. package/dist/session-sync.js +3 -66
  322. package/dist/session-titler.js +7 -41
  323. package/dist/session-watch.js +9 -73
  324. package/dist/shared-memory-scope-authorizer.js +0 -18
  325. package/dist/sighup-idle.js +1 -12
  326. package/dist/spec-fields.js +4 -143
  327. package/dist/store-live-probe.js +3 -49
  328. package/dist/task-a2a.js +1 -126
  329. package/dist/task-cwd.js +1 -103
  330. package/dist/task-mcp.js +1 -89
  331. package/dist/task-settings.js +10 -300
  332. package/dist/task-workflow.js +8 -75
  333. package/dist/tool-approval.d.ts +28 -1
  334. package/dist/tool-approval.js +70 -1430
  335. package/dist/trace/artifacts.js +5 -20
  336. package/dist/trace/engine-notice-wire.js +6 -138
  337. package/dist/trace/ledger-sink.js +7 -96
  338. package/dist/trace/project.js +4 -448
  339. package/dist/trace/redact.js +9 -77
  340. package/dist/turn-activity.js +1 -27
  341. package/dist/usage-analytics.js +4 -34
  342. package/dist/wall-clock-jump-guard.js +1 -68
  343. package/package.json +3 -3
  344. package/dist/capabilities/scenario-alias.d.ts +0 -27
  345. 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 } : {}),
@@ -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); // mkdir's mode is ignored when the dir pre-exists — enforce anyway
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); // writeFile mode is masked by umask — enforce the exact custody mode
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 { /* body 非 JSON 也算 reported */ }
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
  }