@sema-agent/server 7.131.0 → 7.133.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 (509) hide show
  1. package/MIGRATION.md +575 -0
  2. package/README.md +12 -9
  3. package/README.zh-CN.md +9 -6
  4. package/USAGE.md +326 -98
  5. package/deploy/sema-up/README.md +19 -1
  6. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
  7. package/deploy/sema-up/chart/templates/server.yaml +5 -2
  8. package/deploy/sema-up/stack/compose.yaml +3 -0
  9. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  10. package/dist/adoption/plan.d.ts +3 -2
  11. package/dist/adoption/plan.js +7 -5
  12. package/dist/adoption/runner.js +3 -10
  13. package/dist/adoption/sql.d.ts +3 -2
  14. package/dist/adoption/sql.js +3 -5
  15. package/dist/adoption/wire.d.ts +4 -1
  16. package/dist/adoption/wire.js +1 -0
  17. package/dist/approval-ask-audit-store.d.ts +31 -13
  18. package/dist/approval-ask-audit-store.js +272 -74
  19. package/dist/approval-ask-machine.d.ts +15 -0
  20. package/dist/approval-ask-machine.js +6 -0
  21. package/dist/approval-ask-retention.d.ts +136 -0
  22. package/dist/approval-ask-retention.js +102 -0
  23. package/dist/approval-card.d.ts +82 -20
  24. package/dist/approval-card.js +46 -16
  25. package/dist/approval-deny-reasons.d.ts +1 -1
  26. package/dist/approval.d.ts +9 -0
  27. package/dist/approval.js +24 -3
  28. package/dist/audit.d.ts +33 -19
  29. package/dist/audit.js +12 -16
  30. package/dist/auth-bridge.d.ts +4 -0
  31. package/dist/auth-bridge.js +10 -11
  32. package/dist/bake-runner/main.js +3 -2
  33. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  34. package/dist/boot/deployment-mods.d.ts +31 -0
  35. package/dist/boot/deployment-mods.js +26 -0
  36. package/dist/boot/execution-env.d.ts +1 -1
  37. package/dist/boot/execution-env.js +27 -12
  38. package/dist/boot/execution-lane.js +11 -0
  39. package/dist/boot/leader.js +2 -0
  40. package/dist/boot/memory-boundary.d.ts +2 -2
  41. package/dist/boot/memory-boundary.js +2 -2
  42. package/dist/boot/memory-consolidation.d.ts +5 -4
  43. package/dist/boot/memory-consolidation.js +7 -6
  44. package/dist/boot/org-delivery.d.ts +28 -0
  45. package/dist/boot/org-delivery.js +20 -0
  46. package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
  47. package/dist/boot/read-deny-anchor-audit.js +36 -0
  48. package/dist/boot/reapers.d.ts +3 -0
  49. package/dist/boot/reapers.js +21 -1
  50. package/dist/boot/resolve-spec.d.ts +4 -5
  51. package/dist/boot/resolve-spec.js +74 -123
  52. package/dist/boot/runner-deps.d.ts +19 -8
  53. package/dist/boot/runner-deps.js +15 -2
  54. package/dist/boot/session-faces.d.ts +2 -7
  55. package/dist/boot/session-faces.js +4 -2
  56. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  57. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  58. package/dist/boot/stage-03-store-backend.js +2 -2
  59. package/dist/boot/stage-04-stores.d.ts +1 -1
  60. package/dist/boot/stage-05-execution-env.d.ts +4 -4
  61. package/dist/boot/stage-05-execution-env.js +7 -10
  62. package/dist/boot/stage-06-runners.d.ts +4 -2
  63. package/dist/boot/stage-06-runners.js +11 -7
  64. package/dist/boot/stage-07-capability-layer.d.ts +4 -2
  65. package/dist/boot/stage-07-capability-layer.js +27 -6
  66. package/dist/boot/stage-08-reapers.d.ts +4 -2
  67. package/dist/boot/stage-08-reapers.js +2 -2
  68. package/dist/boot/stage-09-leader.d.ts +6 -9
  69. package/dist/boot/stage-10-http-server.d.ts +6 -9
  70. package/dist/boot/stage-10-http-server.js +7 -9
  71. package/dist/boot/stores.d.ts +1 -1
  72. package/dist/boot/stores.js +7 -8
  73. package/dist/boot/web-admin.d.ts +4 -3
  74. package/dist/boot/web-admin.js +186 -98
  75. package/dist/boot/workflow-orchestration.d.ts +2 -0
  76. package/dist/boot/workflow-orchestration.js +2 -1
  77. package/dist/brain.js +25 -25
  78. package/dist/breaker-key.d.ts +6 -0
  79. package/dist/breaker-key.js +29 -0
  80. package/dist/budget.js +5 -4
  81. package/dist/caller-text-echo.d.ts +23 -0
  82. package/dist/caller-text-echo.js +21 -0
  83. package/dist/capabilities/brand-identity.d.ts +26 -0
  84. package/dist/capabilities/brand-identity.js +27 -0
  85. package/dist/capabilities/center-plugins.d.ts +7 -0
  86. package/dist/capabilities/center-plugins.js +1 -1
  87. package/dist/capabilities/center-prompts.d.ts +32 -59
  88. package/dist/capabilities/center-prompts.js +18 -32
  89. package/dist/capabilities/composite-members.d.ts +1 -1
  90. package/dist/capabilities/composite-members.js +1 -1
  91. package/dist/capabilities/engine-capabilities.js +2 -1
  92. package/dist/capabilities/execution-lane.js +2 -2
  93. package/dist/capabilities/hands-lane.d.ts +30 -6
  94. package/dist/capabilities/hands-lane.js +11 -1
  95. package/dist/capabilities/mcp-probe.d.ts +48 -3
  96. package/dist/capabilities/mcp-probe.js +47 -135
  97. package/dist/capabilities/scenarios.d.ts +95 -45
  98. package/dist/capabilities/scenarios.js +53 -38
  99. package/dist/capabilities/skills.d.ts +19 -4
  100. package/dist/capabilities/skills.js +30 -10
  101. package/dist/capability-facts.d.ts +34 -4
  102. package/dist/capability-facts.js +28 -2
  103. package/dist/center-config-tier.d.ts +69 -0
  104. package/dist/center-config-tier.js +42 -0
  105. package/dist/checkpoint-identity.d.ts +16 -0
  106. package/dist/checkpoint-identity.js +19 -0
  107. package/dist/config-catalog.d.ts +17 -10
  108. package/dist/config-catalog.js +47 -32
  109. package/dist/config-d-migration.d.ts +3 -1
  110. package/dist/config-d-migration.js +2 -2
  111. package/dist/config-dir-trust.d.ts +114 -0
  112. package/dist/config-dir-trust.js +388 -0
  113. package/dist/config-invariants.d.ts +18 -5
  114. package/dist/config-invariants.js +35 -3
  115. package/dist/config-lkg.d.ts +9 -9
  116. package/dist/config-lkg.js +20 -4
  117. package/dist/config-provider.d.ts +9 -2
  118. package/dist/config-provider.js +18 -6
  119. package/dist/config-types.d.ts +75 -20
  120. package/dist/config-types.js +8 -0
  121. package/dist/config.d.ts +13 -0
  122. package/dist/config.js +137 -62
  123. package/dist/delegated-session-owner.d.ts +185 -0
  124. package/dist/delegated-session-owner.js +119 -0
  125. package/dist/device-protocol.d.ts +5 -3
  126. package/dist/device-protocol.js +1 -1
  127. package/dist/device-ws-hub.js +21 -2
  128. package/dist/device-ws-protocol.d.ts +70 -6
  129. package/dist/device-ws-protocol.js +50 -22
  130. package/dist/elicitation.js +3 -2
  131. package/dist/entry-problems.d.ts +34 -0
  132. package/dist/entry-problems.js +14 -0
  133. package/dist/env-name-allowlist-knobs.d.ts +12 -2
  134. package/dist/env-name-allowlist-knobs.js +5 -4
  135. package/dist/exec-bounds.d.ts +15 -3
  136. package/dist/exec-bounds.js +4 -0
  137. package/dist/execution-lane-caps.d.ts +56 -10
  138. package/dist/execution-lane-caps.js +50 -0
  139. package/dist/field-conflict.d.ts +43 -0
  140. package/dist/field-conflict.js +20 -0
  141. package/dist/fleet/fleet-bus.d.ts +80 -6
  142. package/dist/fleet/fleet-bus.js +41 -9
  143. package/dist/hooks/classic-stations.d.ts +91 -0
  144. package/dist/hooks/classic-stations.js +27 -0
  145. package/dist/hooks/command-spawn.d.ts +57 -0
  146. package/dist/hooks/command-spawn.js +139 -0
  147. package/dist/hooks/hook-llm.d.ts +8 -5
  148. package/dist/hooks/hook-llm.js +79 -36
  149. package/dist/hooks/hook-runner.d.ts +349 -95
  150. package/dist/hooks/hook-runner.js +855 -568
  151. package/dist/hooks/hook-source.d.ts +44 -0
  152. package/dist/hooks/hook-source.js +40 -0
  153. package/dist/http/active-run-conflict.d.ts +5 -13
  154. package/dist/http/active-run-conflict.js +17 -27
  155. package/dist/http/admission.d.ts +8 -2
  156. package/dist/http/admission.js +188 -101
  157. package/dist/http/approval-sweeps.js +99 -21
  158. package/dist/http/caller-trust.d.ts +77 -0
  159. package/dist/http/caller-trust.js +143 -0
  160. package/dist/http/checkpoint-ctx.d.ts +41 -24
  161. package/dist/http/checkpoint-ctx.js +23 -16
  162. package/dist/http/claimed-run.d.ts +14 -0
  163. package/dist/http/claimed-run.js +15 -0
  164. package/dist/http/device-placement.d.ts +2 -4
  165. package/dist/http/device-placement.js +7 -11
  166. package/dist/http/dispatch.d.ts +0 -4
  167. package/dist/http/dispatch.js +15 -13
  168. package/dist/http/durable-run-leg.d.ts +6 -33
  169. package/dist/http/durable-run-leg.js +36 -10
  170. package/dist/http/health-self-report.d.ts +7 -5
  171. package/dist/http/health-self-report.js +4 -18
  172. package/dist/http/owner-access.d.ts +56 -0
  173. package/dist/http/owner-access.js +42 -0
  174. package/dist/http/principal-gate.d.ts +70 -28
  175. package/dist/http/principal-gate.js +61 -15
  176. package/dist/http/readiness.d.ts +11 -5
  177. package/dist/http/readiness.js +10 -3
  178. package/dist/http/refusal-body.d.ts +21 -0
  179. package/dist/http/refusal-body.js +4 -0
  180. package/dist/http/request-guards.d.ts +43 -23
  181. package/dist/http/request-guards.js +53 -17
  182. package/dist/http/resume-ctx-read.d.ts +2 -5
  183. package/dist/http/resume-ctx-read.js +7 -4
  184. package/dist/http/resume-legs.d.ts +28 -4
  185. package/dist/http/resume-legs.js +169 -91
  186. package/dist/http/retired-service-deps.d.ts +43 -0
  187. package/dist/http/retired-service-deps.js +18 -0
  188. package/dist/http/route-ctx.d.ts +44 -28
  189. package/dist/http/route-ctx.js +4 -0
  190. package/dist/http/route-table.js +2 -0
  191. package/dist/http/routes/a2a-serve.js +3 -4
  192. package/dist/http/routes/admin-config-refresh.js +1 -1
  193. package/dist/http/routes/admin-drain.js +1 -1
  194. package/dist/http/routes/admin-memory-optout.js +5 -1
  195. package/dist/http/routes/adoption.js +2 -9
  196. package/dist/http/routes/approvals-assistant.js +49 -48
  197. package/dist/http/routes/background.js +3 -2
  198. package/dist/http/routes/capabilities.js +21 -5
  199. package/dist/http/routes/config-catalog.d.ts +3 -3
  200. package/dist/http/routes/config-catalog.js +1 -1
  201. package/dist/http/routes/devices.js +3 -17
  202. package/dist/http/routes/diagnostics.js +6 -2
  203. package/dist/http/routes/images.js +6 -7
  204. package/dist/http/routes/leader.js +1 -8
  205. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  206. package/dist/http/routes/mcp-reconnect.js +3 -2
  207. package/dist/http/routes/memory-bundle.js +1 -1
  208. package/dist/http/routes/memory-compliance.js +1 -1
  209. package/dist/http/routes/memory-consolidation.js +1 -1
  210. package/dist/http/routes/memory-origin.js +1 -1
  211. package/dist/http/routes/memory-policy.d.ts +1 -1
  212. package/dist/http/routes/memory-policy.js +3 -2
  213. package/dist/http/routes/notify-wake.js +8 -21
  214. package/dist/http/routes/observability.js +2 -2
  215. package/dist/http/routes/principal-inbox.d.ts +39 -0
  216. package/dist/http/routes/principal-inbox.js +76 -0
  217. package/dist/http/routes/retention-ops.js +2 -9
  218. package/dist/http/routes/rules.js +5 -18
  219. package/dist/http/routes/runs.d.ts +5 -0
  220. package/dist/http/routes/runs.js +34 -107
  221. package/dist/http/routes/session-sync.js +15 -26
  222. package/dist/http/routes/sessions.js +30 -40
  223. package/dist/http/routes/shared-memory.js +2 -13
  224. package/dist/http/routes/side-query.js +8 -7
  225. package/dist/http/routes/tasks.js +67 -21
  226. package/dist/http/routes/workflows.d.ts +351 -0
  227. package/dist/http/routes/workflows.js +153 -119
  228. package/dist/http/send.d.ts +33 -10
  229. package/dist/http/send.js +21 -4
  230. package/dist/http/server.d.ts +27 -18
  231. package/dist/http/server.js +34 -6
  232. package/dist/http/stored-body-replay.js +17 -4
  233. package/dist/http/submit-ctx.d.ts +25 -0
  234. package/dist/http/submit-ctx.js +40 -0
  235. package/dist/http/submit-replay.d.ts +4 -3
  236. package/dist/http/submit-replay.js +5 -4
  237. package/dist/http/wire-types.d.ts +11 -8
  238. package/dist/index.d.ts +2 -2
  239. package/dist/index.js +1 -2
  240. package/dist/lane-home-probe.d.ts +112 -0
  241. package/dist/lane-home-probe.js +101 -0
  242. package/dist/leader/endpoint.d.ts +4 -1
  243. package/dist/leader/endpoint.js +11 -10
  244. package/dist/limit-refusal.d.ts +59 -0
  245. package/dist/limit-refusal.js +15 -0
  246. package/dist/main.js +1 -1
  247. package/dist/mcp-assertion-header.d.ts +32 -19
  248. package/dist/mcp-assertion-header.js +10 -9
  249. package/dist/mcp-tool-faces.d.ts +5 -0
  250. package/dist/mcp-tool-faces.js +6 -4
  251. package/dist/memory-project-layer.d.ts +37 -0
  252. package/dist/memory-project-layer.js +46 -0
  253. package/dist/memory-scope.d.ts +24 -17
  254. package/dist/memory-scope.js +24 -8
  255. package/dist/memory-sync-client.d.ts +27 -13
  256. package/dist/memory-sync-client.js +107 -18
  257. package/dist/model-entry-refusal.d.ts +9 -1
  258. package/dist/model-entry-refusal.js +6 -1
  259. package/dist/model-plane-face.d.ts +51 -0
  260. package/dist/model-plane-face.js +24 -0
  261. package/dist/model-provider.d.ts +44 -12
  262. package/dist/model-provider.js +21 -2
  263. package/dist/model-route-endpoint.d.ts +9 -12
  264. package/dist/model-route-endpoint.js +8 -11
  265. package/dist/model-route-env.d.ts +22 -0
  266. package/dist/model-route-env.js +2 -0
  267. package/dist/model-route-gap.d.ts +60 -30
  268. package/dist/model-route-gap.js +21 -15
  269. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  270. package/dist/observability/corrupt-read-seat.js +9 -0
  271. package/dist/observability/cost-taxonomy.d.ts +7 -7
  272. package/dist/observability/err-text.d.ts +6 -0
  273. package/dist/observability/err-text.js +18 -4
  274. package/dist/observability/fail-open.d.ts +76 -14
  275. package/dist/observability/fail-open.js +76 -14
  276. package/dist/observability/metrics.js +4 -1
  277. package/dist/observability/prompt-manifest.d.ts +33 -82
  278. package/dist/observability/prompt-manifest.js +122 -17
  279. package/dist/observability/run-terminal.js +14 -6
  280. package/dist/observability/secret-env-scrub.d.ts +13 -1
  281. package/dist/observability/secret-env-scrub.js +13 -1
  282. package/dist/observability/tool-trace.d.ts +16 -21
  283. package/dist/observability/tool-trace.js +58 -49
  284. package/dist/operator-ask.d.ts +10 -0
  285. package/dist/operator-ask.js +3 -0
  286. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  287. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  288. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  289. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  290. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  291. package/dist/orchestration/workflow-notify-journal.js +27 -34
  292. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  293. package/dist/orchestration/workflow-park-decision.js +118 -0
  294. package/dist/org-delivery-gate.d.ts +81 -0
  295. package/dist/org-delivery-gate.js +59 -0
  296. package/dist/panel-tool-names.d.ts +23 -0
  297. package/dist/panel-tool-names.js +8 -0
  298. package/dist/parked-decide.d.ts +39 -6
  299. package/dist/parked-decide.js +98 -51
  300. package/dist/parked-revive-surface.d.ts +9 -2
  301. package/dist/parked-revive-surface.js +11 -8
  302. package/dist/per-task-image.d.ts +7 -1
  303. package/dist/per-task-image.js +3 -3
  304. package/dist/permission-rule-list.d.ts +1 -1
  305. package/dist/permission-rule-list.js +2 -2
  306. package/dist/plain-string-record.d.ts +25 -0
  307. package/dist/plain-string-record.js +32 -0
  308. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  309. package/dist/plugins/approval-ask-store-file.js +21 -0
  310. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  311. package/dist/plugins/approval-ask-store-memory.js +34 -2
  312. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  313. package/dist/plugins/approval-ask-store-sql.js +37 -1
  314. package/dist/plugins/blob-backend.d.ts +83 -15
  315. package/dist/plugins/blob-backend.js +68 -15
  316. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  317. package/dist/plugins/breaker-state-sql.js +4 -4
  318. package/dist/plugins/caching-session-store.d.ts +3 -0
  319. package/dist/plugins/caching-session-store.js +3 -0
  320. package/dist/plugins/checkpoint-store-sql.d.ts +28 -4
  321. package/dist/plugins/checkpoint-store-sql.js +59 -28
  322. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  323. package/dist/plugins/file-history-store-sql.js +3 -1
  324. package/dist/plugins/file-run-store.d.ts +5 -13
  325. package/dist/plugins/file-run-store.js +9 -0
  326. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  327. package/dist/plugins/fork-routing-session-store.js +12 -1
  328. package/dist/plugins/host-platform.d.ts +2 -0
  329. package/dist/plugins/host-platform.js +2 -1
  330. package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
  331. package/dist/plugins/k8s-bg-scripts.js +22 -0
  332. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  333. package/dist/plugins/local-checkpoint-store.js +11 -3
  334. package/dist/plugins/local-session-store.d.ts +1 -1
  335. package/dist/plugins/local-session-store.js +1 -1
  336. package/dist/plugins/local-session-window.d.ts +39 -0
  337. package/dist/plugins/local-session-window.js +54 -0
  338. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  339. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  340. package/dist/plugins/mailbox-store-sql.js +77 -52
  341. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  342. package/dist/plugins/memory-run-store.d.ts +5 -13
  343. package/dist/plugins/memory-run-store.js +8 -0
  344. package/dist/plugins/one-time-migrations.d.ts +245 -93
  345. package/dist/plugins/one-time-migrations.js +668 -207
  346. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  347. package/dist/plugins/org-delivery-quota-store.js +228 -0
  348. package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
  349. package/dist/plugins/permission-rule-store-sql.js +4 -18
  350. package/dist/plugins/pg-pool.js +39 -7
  351. package/dist/plugins/pg-session-storage.d.ts +20 -8
  352. package/dist/plugins/pg-session-storage.js +34 -21
  353. package/dist/plugins/remote-env-adb.d.ts +12 -12
  354. package/dist/plugins/remote-env-adb.js +21 -6
  355. package/dist/plugins/remote-env-device.js +3 -0
  356. package/dist/plugins/remote-env-e2b.d.ts +1 -1
  357. package/dist/plugins/remote-env-e2b.js +21 -9
  358. package/dist/plugins/remote-env-host.d.ts +9 -9
  359. package/dist/plugins/remote-env-host.js +10 -32
  360. package/dist/plugins/remote-env-k8s.d.ts +103 -38
  361. package/dist/plugins/remote-env-k8s.js +288 -95
  362. package/dist/plugins/remote-env-local-docker.d.ts +27 -13
  363. package/dist/plugins/remote-env-local-docker.js +82 -11
  364. package/dist/plugins/remote-env-ssh.d.ts +21 -12
  365. package/dist/plugins/remote-env-ssh.js +117 -5
  366. package/dist/plugins/remote-shell.d.ts +0 -1
  367. package/dist/plugins/remote-shell.js +1 -2
  368. package/dist/plugins/retention-store-sql.js +6 -2
  369. package/dist/plugins/run-store-sql.d.ts +16 -14
  370. package/dist/plugins/run-store-sql.js +22 -2
  371. package/dist/plugins/schema-consistency.d.ts +54 -0
  372. package/dist/plugins/schema-consistency.js +52 -0
  373. package/dist/plugins/schema-indexes.js +2 -0
  374. package/dist/plugins/send-user-file.js +2 -2
  375. package/dist/plugins/session-epoch-anchor.d.ts +39 -0
  376. package/dist/plugins/session-epoch-anchor.js +22 -0
  377. package/dist/plugins/session-store.d.ts +18 -8
  378. package/dist/plugins/session-store.js +15 -4
  379. package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
  380. package/dist/plugins/shared-memory-store-sql.js +5 -16
  381. package/dist/plugins/sql-driver.d.ts +205 -1
  382. package/dist/plugins/sql-driver.js +325 -13
  383. package/dist/plugins/sql-errors.d.ts +64 -0
  384. package/dist/plugins/sql-errors.js +57 -0
  385. package/dist/plugins/store-backend.d.ts +36 -1
  386. package/dist/plugins/store-backend.js +42 -15
  387. package/dist/plugins/store-contracts.d.ts +42 -0
  388. package/dist/plugins/store-contracts.js +1 -0
  389. package/dist/plugins/tidb-pool.d.ts +6 -1
  390. package/dist/plugins/tidb-pool.js +44 -10
  391. package/dist/plugins/tidb-session-storage.d.ts +8 -11
  392. package/dist/plugins/tidb-session-storage.js +6 -16
  393. package/dist/plugins/tidb-session-store.d.ts +24 -4
  394. package/dist/plugins/tidb-session-store.js +29 -5
  395. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  396. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  397. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  398. package/dist/plugins/workflow-run-store-sql.js +50 -9
  399. package/dist/posture-source.d.ts +18 -10
  400. package/dist/posture-source.js +4 -1
  401. package/dist/project-identity.d.ts +45 -6
  402. package/dist/project-identity.js +162 -8
  403. package/dist/project-layer-key.d.ts +28 -0
  404. package/dist/project-layer-key.js +29 -0
  405. package/dist/prompts-domain-validate.d.ts +17 -61
  406. package/dist/prompts-domain-validate.js +9 -119
  407. package/dist/question.js +3 -2
  408. package/dist/read-deny-entry.d.ts +25 -0
  409. package/dist/read-deny-entry.js +12 -0
  410. package/dist/read-face-posture.d.ts +37 -11
  411. package/dist/read-face-posture.js +32 -3
  412. package/dist/request-key-closure.d.ts +9 -2
  413. package/dist/request-key-closure.js +11 -5
  414. package/dist/request-value-closure.d.ts +5 -0
  415. package/dist/request-value-closure.js +11 -3
  416. package/dist/rule-entry-list.d.ts +38 -11
  417. package/dist/rule-entry-list.js +106 -30
  418. package/dist/rules-consent.js +3 -4
  419. package/dist/run-acceptance.d.ts +19 -3
  420. package/dist/run-acceptance.js +13 -1
  421. package/dist/run-local.js +54 -24
  422. package/dist/runs.d.ts +15 -8
  423. package/dist/runs.js +35 -1
  424. package/dist/runtime-caps-resolver.d.ts +16 -6
  425. package/dist/runtime-caps-resolver.js +18 -5
  426. package/dist/sandbox-pkg-source.d.ts +19 -1
  427. package/dist/sandbox-pkg-source.js +29 -7
  428. package/dist/security.d.ts +87 -9
  429. package/dist/security.js +52 -9
  430. package/dist/server-secret-env.d.ts +44 -18
  431. package/dist/server-secret-env.js +49 -8
  432. package/dist/session-error-wire.d.ts +19 -2
  433. package/dist/session-error-wire.js +5 -1
  434. package/dist/session-incarnation.d.ts +15 -5
  435. package/dist/session-incarnation.js +16 -9
  436. package/dist/session-titled-frame.d.ts +33 -0
  437. package/dist/session-titled-frame.js +4 -0
  438. package/dist/session-titler.d.ts +9 -1
  439. package/dist/session-titler.js +27 -6
  440. package/dist/spec-fields.d.ts +28 -16
  441. package/dist/spec-fields.js +66 -54
  442. package/dist/sql-engine-posture.d.ts +31 -4
  443. package/dist/sql-engine-posture.js +36 -1
  444. package/dist/stored-request-tool-axes-m19.d.ts +19 -4
  445. package/dist/stored-request-tool-axes-m19.js +30 -2
  446. package/dist/task-a2a.d.ts +9 -1
  447. package/dist/task-a2a.js +73 -47
  448. package/dist/task-cwd.d.ts +1 -1
  449. package/dist/task-mcp.d.ts +46 -58
  450. package/dist/task-mcp.js +82 -107
  451. package/dist/task-settings.d.ts +95 -108
  452. package/dist/task-settings.js +77 -98
  453. package/dist/text-bidi.d.ts +1 -48
  454. package/dist/text-bidi.js +3 -5
  455. package/dist/tighten-only-seats.d.ts +150 -0
  456. package/dist/tighten-only-seats.js +196 -0
  457. package/dist/tool-approval.d.ts +304 -88
  458. package/dist/tool-approval.js +623 -239
  459. package/dist/trace/core-keyset-guard.d.ts +122 -20
  460. package/dist/trace/engine-notice-wire.d.ts +11 -3
  461. package/dist/trace/engine-notice-wire.js +8 -1
  462. package/dist/trace/exit-seat.d.ts +28 -0
  463. package/dist/trace/exit-seat.js +76 -0
  464. package/dist/trace/ledger-events.d.ts +6 -3
  465. package/dist/trace/ledger-sink.js +4 -1
  466. package/dist/trace/model-segment.js +1 -1
  467. package/dist/trace/project.d.ts +98 -17
  468. package/dist/trace/project.js +98 -50
  469. package/dist/trace/projection-table.d.ts +100 -0
  470. package/dist/trace/projection-table.js +130 -0
  471. package/dist/trace/redact.d.ts +54 -0
  472. package/dist/trace/redact.js +778 -152
  473. package/dist/trace/self-minted-wire.d.ts +345 -1
  474. package/dist/trace/self-minted-wire.js +117 -1
  475. package/dist/trace/wire-projection-faces.d.ts +377 -3
  476. package/dist/trace/wire-projection-faces.js +164 -1
  477. package/dist/url-refusal.js +2 -0
  478. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  479. package/dist/web-admin-client/apply-effective.js +56 -5
  480. package/dist/web-admin-client/candidate-gate.d.ts +6 -6
  481. package/dist/web-admin-client/candidate-gate.js +3 -3
  482. package/dist/web-admin-client/facade.d.ts +1 -1
  483. package/dist/web-admin-client/facade.js +1 -1
  484. package/dist/web-admin-client/http-client.js +0 -6
  485. package/dist/web-admin-client/read-face.js +5 -9
  486. package/dist/web-admin-client/read-warnings.d.ts +13 -0
  487. package/dist/web-admin-client/read-warnings.js +10 -0
  488. package/dist/web-admin-client/skills-mcp.d.ts +3 -0
  489. package/dist/web-admin-client/skills-mcp.js +11 -9
  490. package/dist/web-admin-client/types.d.ts +2 -3
  491. package/dist/workspace-cache.d.ts +35 -0
  492. package/dist/workspace-cache.js +36 -0
  493. package/dist/workspace-space.d.ts +3 -2
  494. package/dist/workspace-space.js +2 -0
  495. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
  496. package/package.json +8 -4
  497. package/scripts/drain-check-local.mjs +34 -1
  498. package/scripts/drain-check.mysql.sql +30 -2
  499. package/scripts/drain-check.pg.sql +29 -2
  500. package/dist/capabilities/memory-notice.d.ts +0 -138
  501. package/dist/capabilities/memory-notice.js +0 -64
  502. package/dist/capabilities/prompt.d.ts +0 -17
  503. package/dist/capabilities/prompt.js +0 -6
  504. package/dist/mcp-content-origin.d.ts +0 -34
  505. package/dist/mcp-content-origin.js +0 -10
  506. package/dist/tool-axis-words.d.ts +0 -27
  507. package/dist/tool-axis-words.js +0 -9
  508. package/dist/wire-name-bound.d.ts +0 -14
  509. package/dist/wire-name-bound.js +0 -13
@@ -1,10 +1,11 @@
1
1
  import type { IncomingMessage } from "node:http";
2
- import { type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
2
+ import { type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
3
3
  import type { ServiceConfig } from "./config-types.js";
4
4
  import type { TaskRequestBody } from "./http/wire-types.js";
5
5
  import type { StagingHandle } from "./session-sync-kernel.js";
6
6
  import type { SessionFace, SessionFaceReader } from "./session-incarnation.js";
7
7
  import type { SessionRowPatch } from "./session-row.js";
8
+ import { type OwnerlessClaim } from "./delegated-session-owner.js";
8
9
  /** One row of the session-list projection (CC /resume picker) — the durable session abstraction's enumeration
9
10
  * output (§0.5). Mirrors {@link RunStore}'s shipped `SessionSummary` shape so the wire response is unchanged. */
10
11
  export interface SessionListItem {
@@ -51,6 +52,54 @@ export interface SessionListItem {
51
52
  * 不含读面,也不含 `POST /v1/tasks` 那条提交腿 —— 它有自己的同族门(别重复拦,双拦会让错误归因变糊)。
52
53
  */
53
54
  export declare function isDestructiveSessionWrite(method: string, url: string): boolean;
55
+ declare const principalBrand: unique symbol;
56
+ declare const durableOwnerKeyBrand: unique symbol;
57
+ /**
58
+ * 🔴 **两个 owner 不是同一个东西**(S-487 RH-3,类型事实):
59
+ * · {@link Principal} —— **这次请求**验过的调用方身份。铸点闭集:`http/principal-gate.ts` 的 `gatedPrincipal`(验身份的那一只),以及属主存取器
60
+ * (`http/owner-access.ts`)里一只「上游已验」的适配口(调用方身份经一只纯串结构转手过来的腿 —— 第二期随那只结构带品牌而删);
61
+ * · {@link DurableOwnerKey} —— **行上 / 存储键里**落下的属主(run 行、会话行的 `owner` 列)。铸点闭集:属主存取器读行处与 {@link sessionOwnerCellOf}。
62
+ * 两者互不可赋、裸 `string` 两者都不可赋;「这个调用方读得到这一行吗」的判官(`runOwnerReadable`)签名两参各带一个品牌,对调即编译红。
63
+ * 铸点按文件计数钉在 `test/owner-gate-single-owner.test.ts` 的品牌铸点普查格里:多一处铸点 = 门红。
64
+ */
65
+ export type Principal = string & {
66
+ readonly [principalBrand]: true;
67
+ };
68
+ export type DurableOwnerKey = string & {
69
+ readonly [durableOwnerKeyBrand]: true;
70
+ };
71
+ /** {@link Principal} 的铸造口(只在铸点闭集里调,见上)。 */
72
+ export declare function mintPrincipal(verified: string): Principal;
73
+ /** {@link DurableOwnerKey} 的铸造口(只在铸点闭集里调,见上)。 */
74
+ export declare function mintDurableOwnerKey(persisted: string): DurableOwnerKey;
75
+ /**
76
+ * 会话行属主门读的那一格(S-1770):有主的行只有属主;**无主的行**另带「它是不是委派子代的 placed 行」(店的 `placementOf` 答,{@link sessionOwnerCellOf} 读;
77
+ * 不实现 placement 的店没有 placed 行)。`placed` 只在无主时存在 —— 有主的行属主门不看它。
78
+ */
79
+ export type SessionOwnerCell = {
80
+ readonly owner: DurableOwnerKey;
81
+ } | {
82
+ readonly owner: null;
83
+ readonly placed: boolean;
84
+ };
85
+ /** 会话行属主门的调用方:验过的主体(`gatedPrincipal`)+ 它是不是 **fleet 调用方**(dev-open 部署上的任何调用方,或出示了这台部署的 service 凭据、
86
+ * 不报主体的调用方)。唯一铸点 `http/principal-gate.ts` 的 `sessionCallerOf`。 */
87
+ export interface SessionCaller {
88
+ readonly principal: Principal | undefined;
89
+ readonly fleet: boolean;
90
+ }
91
+ /**
92
+ * 🔴 **会话行属主门上「无主行放行」臂的唯一判据**(S-1770 读面律;会话面谓词 `sessionOwnerReadable`、fork / 删除的存量互认臂 {@link legacyUnownedSessionOk}、
93
+ * 审批豁免面、notify 面的无主臂都经它,不各写一份):
94
+ * · 无主的**普通**会话行 ⇒ 成立(各臂照它自己的其余条件);
95
+ * · 无主的 **placed** 行(委派子代:属主 = 委派树根的属主,`delegated-session-owner.ts`)⇒ 只对 **fleet 调用方**成立({@link SessionCaller}:dev-open 部署上的任何调用方,
96
+ * 或出示了 service 凭据、不报主体的调用方 —— 只配 token 的单用户部署、BFF 的系统调用)。任何具名主体(含经 BFF 代发的)与没有 service 凭据的无身份调用方都不成立:
97
+ * 这一行要么属于一棵无身份调用方的树,要么属主还没定下(升级前写下、回填还没判出 / 判断时来源还没有属主)—— 后者把它当公共行,就是把别人那棵树的子代转录交给拿到 id 的人。
98
+ * · 有主的行 ⇒ 不在本臂。
99
+ */
100
+ export declare function ownerlessRowOpen(cell: SessionOwnerCell, caller: SessionCaller): boolean;
101
+ /** 读一只会话行的 {@link SessionOwnerCell}:无主时问一次店的 `placementOf`(既有读口;店不交它 = 不实现 placement = 没有 placed 行)。`owner` = 调用点那一读。 */
102
+ export declare function sessionOwnerCellOf(store: Pick<OwnerAwareSessionStore, "placementOf"> | undefined, sessionId: string, owner: string | null): Promise<SessionOwnerCell>;
54
103
  /** [ref] 窄互认第二臂的租户键字面量 —— 单机形下 core 写侧 `spec.principal ?? "default"` 铸出的那一个,
55
104
  * 也是壳 [ref]G1 翻面后随请求带的那一个。**不是哨兵**([ref] 措辞):它是单机形的真租户键。 */
56
105
  export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
@@ -66,7 +115,7 @@ export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
66
115
  *
67
116
  * 🔒 **三条件缺一不放行**(与第一臂同源,不是兼容臂):
68
117
  * ① 单机形 `!requirePrincipal` —— 多租部署本臂**死路**(header 必到、键必具名);
69
- * ② 存量行恰为无主 `owner === null` —— 任何具名 owner 的行不受影响;
118
+ * ② 存量行恰为无主 `owner === null`、且不是委派子代的 placed 行(无主臂的唯一判据 {@link ownerlessRowOpen})—— 任何具名 owner 的行不受影响;
70
119
  * ③ 调用方恰为 `default` 主 —— 非 default 的具名主对无主行仍走原门(404 / deleted:false)。
71
120
  * 反向风险有界:①限定的单机形本就单用户,把无主行判给 default 主不产生跨租外泄。
72
121
  *
@@ -87,10 +136,10 @@ export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
87
136
  * 写面族超出裁定射程 —— 要做另立一次表态,不在本臂里顺手带过。
88
137
  *
89
138
  * @param requirePrincipal `config.requirePrincipal`(条件①)
90
- * @param gateOwner `sessionOwnerScope(ForWrite)` 判出的**已验证**主(条件③;fleet-wide 面不经本臂)
91
- * @param owner 存量行的 owner 列(条件②)
139
+ * @param caller 调用方(条件③ 读它验过的主体;fleet-wide 面不经本臂)
140
+ * @param cell 存量行那一格(条件②:无主,且经无主臂的唯一判据 {@link ownerlessRowOpen} —— 无主的委派子代 placed 行不在本臂,S-1770)
92
141
  */
93
- export declare function legacyUnownedSessionOk(requirePrincipal: boolean, gateOwner: string | null, owner: string | null): boolean;
142
+ export declare function legacyUnownedSessionOk(requirePrincipal: boolean, caller: SessionCaller, cell: SessionOwnerCell): boolean;
94
143
  /**
95
144
  * {@link legacyUnownedSessionOk} 的**条件①③**半支 —— 只判「这个部署形 × 这个调用方」是否落在窄臂辖域内。
96
145
  *
@@ -106,6 +155,13 @@ export type OwnerAwareSessionStore = SessionStore & {
106
155
  * 是 `src/session-incarnation.ts`。只关心属主的消费点照旧读 `ownerOf`;判「这还是不是同一位住客」的读它。 */
107
156
  sessionFaceOf?: SessionFaceReader;
108
157
  register?: (sessionId: string, owner: string | null) => Promise<void>;
158
+ /** S-1770 委派继承律的**认领口** —— 只在记录委派树的店上(SQL 两店,只命中 placed 行;local 店没有):判断时读到的那一位住客仍是无主的 placed 行 ⇒ 写 `owner`,
159
+ * 返回是否写成(只 CAS 子行自己)。唯一调用方 = 停驻挂点的 `settleDelegatedOwner`(`delegated-session-owner.ts`;M23 走同一句 SQL);规则写在那个模块。 */
160
+ claimOwnerless?: OwnerlessClaim;
161
+ /** [ref] placed 分区的元组读口(店的既有读口,一行 PK 读;`undefined` = 普通会话或无此行)。店不交它 = 不实现 placement = 没有 placed 行(local 店)。两个读者:
162
+ * ① 会话面的属主门只在属主为 NULL 时读它一次(无主的 placed 行不是公共行,`http/principal-gate.ts` 的 `sessionOwnerCellOf`);
163
+ * ② 会话视图读它投影体顶层 `agent` 键(`audit.ts` 的 `sessionAgentOf`,只在视图读上付):店没有这一面 ⇒ 键缺席,读面不凭别处另铸子代身份。 */
164
+ placementOf?: (sessionId: string) => Promise<SessionPlacementRecord | undefined>;
109
165
  /** E16 — enumerate the caller's sessions (owner-filtered on the session store's OWN owner column).
110
166
  * `includeUnowned` = [ref] 窄互认第二臂的**第三条件**(`owner IS NULL`)的 SQL 承载位:置真时
111
167
  * 谓词放宽为 `owner = ? OR owner IS NULL`。只在 `owner` 在场时有意义(路由已判①③);`owner` 缺席
@@ -269,24 +325,39 @@ export declare function createAuthorizer(config: ServiceConfig, sessionStore: Ow
269
325
  * SendUserFile ledger scope + the /v1/sendfile-links fleet-wide default; the resource-suspend isolation
270
326
  * key), `"_leader"` merges with the leader durable-approval owner scope (a tenant so named could list/
271
327
  * decide internal leader approvals), `"_leader-…"` with the leader resource-suspend scope family, and
272
- * `"__none__"` with the missing-principal placeholder scope on the decide/pending gates.
328
+ * `"__none__"` with the missing-principal read placeholder of the approval queue faces (≤ 7.132.x replicas).
273
329
  * - length > 190 is REJECTED: every scope/owner column the principal lands in VERBATIM is VARCHAR(190)
274
330
  * (sendfile_link.scope, approval.owner/scope, memory-engine scope, rate-limit keys, …) — an over-long
275
331
  * principal would truncate/500 at the INSERT and split one identity into two.
276
332
  * Throws a typed 400 `HttpError` (the HTTP layer maps it); the message names the rule (a reserved identifier /
277
333
  * the length cap), never a secret and never the internal scope's semantics. */
278
334
  export declare const PRINCIPAL_MAX_LENGTH = 190;
335
+ /**
336
+ * 一个被受理的主体串最多占多少个 UTF-8 字节 —— 按**字节**计宽的身份列(TiDB `VARBINARY(n)`)的列宽**唯一来源**(派生,不手抄第二个数)。
337
+ * {@link PRINCIPAL_MAX_LENGTH} 数的是 UTF-16 码元(`string.length`),一个码元最坏落 3 个 UTF-8 字节:BMP 字符 3 字节;代理对 4 字节 / 2 码元;
338
+ * 孤代理按 U+FFFD 编,3 字节。按**字符**计宽的列(`VARCHAR(n)`:TiDB utf8mb4 / PG 都数码点)直接用 {@link PRINCIPAL_MAX_LENGTH} —— 码点数 ≤ 码元数。
339
+ */
340
+ export declare const PRINCIPAL_MAX_UTF8_BYTES: number;
279
341
  /** 修1 — the SINGLE registry of internal sentinel/scope identifiers a tenant principal must never equal.
280
342
  * 🔴 新增内部 sentinel scope 必须在此登记(精确值加 RESERVED_PRINCIPALS,前缀族加
281
343
  * RESERVED_PRINCIPAL_PREFIXES),否则 assertPrincipalShape 会放行同名租户 = 与内部 scope 行合流的超范围面。
282
344
  * Current entries (where each is minted): `"_"` = single-user/anonymous sentinel (checkpoint/sendfile/
283
- * resource-suspend scope family); `"__none__"` = missing-principal placeholder on the decide/pending gates
284
- * (http/server.ts `principal ?? "__none__"`); `"_leader"` = leader durable-approval scope
345
+ * resource-suspend scope family); `"__none__"` = the missing-principal read placeholder of the approval
346
+ * queue faces up to 7.132.x (7.133.0 reads the anonymous group `"_"` instead; still reserved because a 7.132.x replica in the same
347
+ * rolling upgrade lists that scope for anonymous callers, so a tenant by that name would merge with them there); `"_leader"` = leader durable-approval scope
285
348
  * (src/leader/wire.ts); prefix `"_leader-"` = the leader resource-suspend scope family
286
- * (`_leader-resource-<workerId>`, src/leader/wire.ts). NB the prefix REQUIRES the hyphen — a tenant named
349
+ * (`_leader-resource-<workerId>`, src/leader/wire.ts); prefix `"_orphan:"` = the owner written on a delegated session whose
350
+ * delegation ancestors are gone (`_orphan:<sessionId>`, src/delegated-session-owner.ts) — a caller allowed to authenticate as it
351
+ * would read that transcript. NB the `_leader-` prefix REQUIRES the hyphen — a tenant named
287
352
  * `_leaderX` collides with nothing internal and stays valid (boundary pinned by test). */
288
353
  export declare const RESERVED_PRINCIPALS: readonly string[];
289
354
  export declare const RESERVED_PRINCIPAL_PREFIXES: readonly string[];
355
+ /** The principal-shape rule as a VERDICT (the one judge; {@link assertPrincipalShape} is its throwing reader). `undefined` = a
356
+ * principal may carry this string; otherwise which rule it breaks. A reader that only needs "can this string be anyone?" (the
357
+ * organization delivery gate's recipient: a string that breaks the rule is nobody, refused with the same bytes as an unknown
358
+ * principal) reads the verdict instead of catching the throw. */
359
+ export type PrincipalShapeProblem = "reserved" | "too_long";
360
+ export declare function principalShapeProblem(principal: string): PrincipalShapeProblem | undefined;
290
361
  export declare function assertPrincipalShape(principal: string): void;
291
362
  /** The checkpoint `scope` column's single-user/anonymous sentinel — the same "_" documented above
292
363
  * ({@link RESERVED_PRINCIPALS}) as the checkpoint/sendfile/resource-suspend scope family's shared value.
@@ -321,6 +392,10 @@ export declare const encodeCheckpointScope: (principal: string | null | undefine
321
392
  /** Decode a checkpoint `scope` column value back to a principal — {@link CHECKPOINT_PUBLIC_SCOPE} maps to
322
393
  * `undefined` (no principal), everything else passes through verbatim. */
323
394
  export declare const decodeCheckpointScope: (scope: string) => string | undefined;
395
+ /** A checkpoint `scope` value read as the **owner column** of the rows it governs (run rows, live / crash asks): {@link CHECKPOINT_PUBLIC_SCOPE}
396
+ * ⇒ `null` (the null-owner rows: tasks submitted without a principal), everything else verbatim. The one translation from the approval faces'
397
+ * scope to an owner filter — stores filter on the owner column and never recognize `"_"` themselves. */
398
+ export declare const ownerOfCheckpointScope: (scope: string) => string | null;
324
399
  /** Read the authenticated principal from the trusted header. Never from the body. */
325
400
  export declare function principalFrom(req: IncomingMessage, config: ServiceConfig): string | undefined;
326
401
  /** Header carrying the crypto-verified principal JWT on a direct-door worker (the issuer signs it; the worker only
@@ -342,5 +417,8 @@ export declare function setSsoPrincipal(req: IncomingMessage, principal: string)
342
417
  export declare function ssoVerifiedPrincipal(req: IncomingMessage): string | undefined;
343
418
  export declare function setSsoScope(req: IncomingMessage, scope: string): void;
344
419
  export declare function ssoVerifiedScope(req: IncomingMessage): string | undefined;
420
+ export declare function setSsoRole(req: IncomingMessage, role: string): void;
421
+ export declare function ssoVerifiedRole(req: IncomingMessage): string | undefined;
345
422
  export declare function verifiedPrincipal(req: IncomingMessage, config: ServiceConfig): string | undefined;
423
+ export {};
346
424
  //# sourceMappingURL=security.d.ts.map
package/dist/security.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { uuidv7, PROJECT_ID_REGEX } from "@sema-agent/core";
2
2
  import { memoryScopeFor } from "./memory-scope.js";
3
3
  import { verifyPrincipalJwt } from "./principal-jwt.js";
4
+ import { fieldConflictFacts } from "./field-conflict.js";
5
+ import { ORPHAN_SESSION_OWNER_PREFIX } from "./delegated-session-owner.js";
4
6
  export function isDestructiveSessionWrite(method, url) {
5
7
  if (method === "DELETE")
6
8
  return /^\/v1\/sessions\/[^/]+$/.test(url);
@@ -10,9 +12,26 @@ export function isDestructiveSessionWrite(method, url) {
10
12
  return /^\/v1\/sessions\/[^/]+\/(sync\/import|fork|memory\/erase)$/.test(url);
11
13
  return false;
12
14
  }
15
+ export function mintPrincipal(verified) {
16
+ return verified;
17
+ }
18
+ export function mintDurableOwnerKey(persisted) {
19
+ return persisted;
20
+ }
21
+ export function ownerlessRowOpen(cell, caller) {
22
+ if (cell.owner !== null)
23
+ return false;
24
+ return !cell.placed || caller.fleet;
25
+ }
26
+ export async function sessionOwnerCellOf(store, sessionId, owner) {
27
+ if (owner !== null)
28
+ return { owner: mintDurableOwnerKey(owner) };
29
+ const placementOf = store?.placementOf;
30
+ return { owner: null, placed: placementOf !== undefined && (await placementOf.call(store, sessionId)) !== undefined };
31
+ }
13
32
  export const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
14
- export function legacyUnownedSessionOk(requirePrincipal, gateOwner, owner) {
15
- return owner === null && legacyUnownedAmnestyOpen(requirePrincipal, gateOwner);
33
+ export function legacyUnownedSessionOk(requirePrincipal, caller, cell) {
34
+ return legacyUnownedAmnestyOpen(requirePrincipal, caller.principal ?? null) && ownerlessRowOpen(cell, caller);
16
35
  }
17
36
  export function legacyUnownedAmnestyOpen(requirePrincipal, gateOwner) {
18
37
  return !requirePrincipal && gateOwner === LEGACY_UNOWNED_AMNESTY_TENANT;
@@ -98,7 +117,7 @@ export function createAuthorizer(config, sessionStore) {
98
117
  }
99
118
  else {
100
119
  if (requireExisting) {
101
- throw createCodedHttpError(422, "request.field_conflict", "requireExistingSession requires a sessionId — there is no existing session to resume");
120
+ throw createCodedHttpError(422, "request.field_conflict", "requireExistingSession requires a sessionId — there is no existing session to resume", fieldConflictFacts("existing_session", ["requireExistingSession", "sessionId"]));
102
121
  }
103
122
  sessionId = uuidv7();
104
123
  if (register)
@@ -108,14 +127,29 @@ export function createAuthorizer(config, sessionStore) {
108
127
  };
109
128
  }
110
129
  export const PRINCIPAL_MAX_LENGTH = 190;
130
+ export const PRINCIPAL_MAX_UTF8_BYTES = PRINCIPAL_MAX_LENGTH * 3;
111
131
  export const RESERVED_PRINCIPALS = ["_", "__none__", "_leader"];
112
- export const RESERVED_PRINCIPAL_PREFIXES = ["_leader-"];
132
+ export const RESERVED_PRINCIPAL_PREFIXES = ["_leader-", ORPHAN_SESSION_OWNER_PREFIX];
133
+ export function principalShapeProblem(principal) {
134
+ if (RESERVED_PRINCIPALS.includes(principal) || RESERVED_PRINCIPAL_PREFIXES.some((p) => principal.startsWith(p)))
135
+ return "reserved";
136
+ if (principal.length > PRINCIPAL_MAX_LENGTH)
137
+ return "too_long";
138
+ return undefined;
139
+ }
113
140
  export function assertPrincipalShape(principal) {
114
- if (RESERVED_PRINCIPALS.includes(principal) || RESERVED_PRINCIPAL_PREFIXES.some((p) => principal.startsWith(p))) {
115
- throw new HttpError(400, `principal ${JSON.stringify(principal)} is reserved (an internal scope sentinel) — authenticate with a real tenant identifier`, { code: "principal_reserved" });
116
- }
117
- if (principal.length > PRINCIPAL_MAX_LENGTH) {
118
- throw new HttpError(400, `principal exceeds ${PRINCIPAL_MAX_LENGTH} characters (the scope-column width every store pins, e.g. sendfile_link.scope VARCHAR(190)); got ${principal.length}`, { code: "principal_too_long" });
141
+ const problem = principalShapeProblem(principal);
142
+ switch (problem) {
143
+ case undefined:
144
+ return;
145
+ case "reserved":
146
+ throw new HttpError(400, `principal ${JSON.stringify(principal)} is reserved (an internal scope sentinel) — authenticate with a real tenant identifier`, { code: "principal_reserved" });
147
+ case "too_long":
148
+ throw new HttpError(400, `principal exceeds ${PRINCIPAL_MAX_LENGTH} characters (the scope-column width every store pins, e.g. sendfile_link.scope VARCHAR(190)); got ${principal.length}`, { code: "principal_too_long" });
149
+ default: {
150
+ const unknownProblem = problem;
151
+ throw new Error(`assertPrincipalShape: unknown problem ${String(unknownProblem)}`);
152
+ }
119
153
  }
120
154
  }
121
155
  export const CHECKPOINT_PUBLIC_SCOPE = "_";
@@ -125,6 +159,7 @@ export function backgroundScopesForCheckpointScope(scope) {
125
159
  }
126
160
  export const encodeCheckpointScope = (principal) => principal ?? CHECKPOINT_PUBLIC_SCOPE;
127
161
  export const decodeCheckpointScope = (scope) => (scope === CHECKPOINT_PUBLIC_SCOPE ? undefined : scope);
162
+ export const ownerOfCheckpointScope = (scope) => decodeCheckpointScope(scope) ?? null;
128
163
  export function principalFrom(req, config) {
129
164
  if (!config.principalHeader)
130
165
  return undefined;
@@ -153,6 +188,14 @@ export function ssoVerifiedScope(req) {
153
188
  const v = req[SSO_SCOPE];
154
189
  return typeof v === "string" && v.length > 0 ? v : undefined;
155
190
  }
191
+ const SSO_ROLES = new WeakMap();
192
+ export function setSsoRole(req, role) {
193
+ SSO_ROLES.set(req, role);
194
+ }
195
+ export function ssoVerifiedRole(req) {
196
+ const v = SSO_ROLES.get(req);
197
+ return v !== undefined && v.length > 0 ? v : undefined;
198
+ }
156
199
  export function verifiedPrincipal(req, config) {
157
200
  const sso = ssoVerifiedPrincipal(req);
158
201
  if (sso) {
@@ -10,7 +10,12 @@
10
10
  *
11
11
  * ## 律(一句;core #1753 定,本仓只传事实、不判)
12
12
  * 本包任何进程在宿主上 spawn 的子进程:env = 引擎 `inheritedHostEnv(policy, findings)` ∪ 部署方点名放回的键(只在运维真可能要传东西的腿上有旋钮),
13
- * 剥掉的键经一个登记过的 `SecretEnvScrubSite` 留痕;git 腿再叠 git 自己的两件({@link gitSubprocessEnv})。三个继承词只在引擎一处判:
13
+ * 剥掉的键经一个登记过的 `SecretEnvScrubSite` 留痕(现场按**腿**命名);git 腿再叠 git 自己的两件({@link gitSubprocessEnv})。射程 = **每一条**宿主腿:
14
+ * src 里每一只值引 `node:child_process` 的文件都是登记腿、其中每一次起子进程都显式交组合出的 env(普查门在 `test/secret-env-scrub-host-legs.test.ts`)。
15
+ * 腿的继承词是调用点的事实,按「子进程里跑的是谁选的代码」定:模型命令(host shell,交任务自己的词)/ 仓里的钩子与凭据助手(三条 git 腿)/ 执行仓代码的
16
+ * 语言服务器 / 配方脚本 ⇒ 形状剥 `"scrub"`;请求带来的 settings hooks 命令 ⇒ 严格名单(引擎的 `[names]` 臂);部署方装在宿主上的 CLI(`docker` / `adb`,命令本身
17
+ * 在容器 / 设备里跑、那边的 env 由 `-e` 显式给)⇒ `"all"` —— 只扣本服务自有凭据,CLI 与它的凭据助手 / 插件要读的生态变量照交(形状剥会剥
18
+ * `ADB_VENDOR_KEYS` / `AWS_SECRET_ACCESS_KEY` 一类,实测)。三个继承词只在引擎一处判:
14
19
  * · `"all"` = 整份环境 **减** 本进程声明的自有凭据名;`"scrub"`(缺省)= 形状剥 ∪ 该名单;`[names]` = 严格白名单,点到名单中的名 ⇒ 引擎响亮拒
15
20
  * (`inheritEnvPolicyProblem`:构造时与 spawn 时两格都拒,拒句带名;本仓不自判 withheld、不留第二读法)。
16
21
  * · 名单 = 配置目录(`config-catalog.ts`)全部 `type:"secret"` 名 ∪ 名单型旋钮名(`env-name-allowlist-knobs.ts`,其原文可能夹着被错展开的令牌)∪ **生效配置
@@ -23,17 +28,21 @@
23
28
  * 抛同路)。能力词 `inherit_env.own_credentials_withheld` 在本进程的事实 =
24
29
  * {@link ownCredentialsWithheld}:最近一次成功声明的集合 ⊇ 当前生效配置应声明的集合(活配置经 {@link bindOwnCredentialsConfig} 在 `loadConfig()` 之后绑一次;
25
30
  * 未绑 / 未声明 ⇒ false,事实读不到应声明集合就不答 true)。
26
- * · 调用方显式传入的 env(`cfg.env` / 单次命令的 `env` / 语言服务器与沙箱的点名放回)不是继承,照旧原样叠在组合结果之上 —— 那是适配器自己的凭据通道。
27
- * 各腿只调 {@link hostSubprocessEnv} / {@link gitSubprocessEnv} —— 不许再有内联拼装、不许再有 `{ ...process.env }`、不许本仓再判任何一个继承词
28
- * (类级门在 `test/secret-env-scrub-host-legs.test.ts`)。
31
+ * · **值臂**(core 7.52.0 #1754):声明是一张表 `{ names, values }`。`values` = 本进程持有凭据的变量此刻的值(目录 secret 名 ∪ 模型条目 `apiKeyEnv`,{@link serverCredentialValueSources}),
32
+ * 逐个交给引擎的同一只判;引擎判「不是凭据值」的那一个不扣、名照扣、不拒启、点名一次。能力词 `inherit_env.own_credential_values_withheld` 的事实 = {@link ownCredentialValuesWithheld}(位真 ⇔ 值臂真扣)。
33
+ * · 调用方显式传入的 env(`cfg.env` / 单次命令的 `env` / 沙箱的点名放回)不是继承,照旧原样叠在组合结果之上 —— 那是适配器自己的凭据通道。
34
+ * 各腿只调 {@link hostSubprocessEnv} / {@link gitSubprocessEnv} —— 不许再有内联拼装、不许再有 `{ ...process.env }`、不许本仓再判任何一个继承词、不许起子进程不交 env
35
+ * (类级门与普查门在 `test/secret-env-scrub-host-legs.test.ts`)。
29
36
  *
30
37
  * ## 点名放行(S-699 / S-713,一只谓词各处用)
31
- * {@link allowlistedEnv} 是本仓「一张名单点到哪些 env 键,就把它们从源 env **原样**交给子进程」的唯一实现。调用:{@link hostSubprocessEnv}(剥后放回形:
32
- * 本地语言服务器的 `LSP_ENV_ALLOW`、bake-runner 的 `BAKE_ENV_ALLOW`)、沙箱带外 env 的 `E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` / `K8S_SANDBOX_ENV`(`config.ts`)。
38
+ * {@link allowlistedEnv} 是本仓「一张名单点到哪些 env 键,就把它们从源 env **原样**交给沙箱」的唯一实现。调用:沙箱带外 env 的 `E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` /
39
+ * `K8S_SANDBOX_ENV`(`config.ts`)与名单解析器的「在不在」判。宿主子进程的剥后放回(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)不经它 —— 那是引擎的严格名单臂(上一段)。
33
40
  * host shell 的 `inheritEnv:[names]`(hermetic 形)7.129.0 起由引擎读(与 core `NodeExecutionEnv` 同名选项同义,点到自有凭据名即拒),不经本谓词。
34
41
  * 名单型旋钮的**名单**另由 `config.ts` 的同一只解析器 `parseEnvNameAllowlist` 判形(形错拒启 / 源里没有的名按序号 warn),本函数只管取值。
35
42
  * 「点名」在各处同义:点到的键原样带值(空串值照带),密钥形也照过(点名 = 部署方显式承担);源里没有的名不产生条目。
36
- * ⚠️ 已知边界(不在本函数修):`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 点到自有凭据名会把它放回语言服务器 / 配方脚本(剥后放回形在引擎的减法之上);解析器今天只拒名单型旋钮名。
43
+ * 剥后放回形(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)的放回本身也经引擎:{@link composeHostSubprocessEnv} 把名单交引擎的严格名单臂(`inheritedHostEnv([names])`)叠在
44
+ * 继承结果之上 ⇒ 点到本服务自有凭据名 = 引擎抛(spawn 时;起服时解析器 `parseEnvNameAllowlist` 按表列 `channel` 已用同一只判 `inheritEnvPolicyProblem` 拒过),
45
+ * 点到的变量值是本服务凭据的副本 = 引擎扣下。本仓不另判。
37
46
  */
38
47
  import { type InheritEnvPolicy, type SecretEnvFinding } from "@sema-agent/core";
39
48
  import type { ServiceConfig } from "./config-types.js";
@@ -48,27 +57,44 @@ export type ModelApiKeyEnvTable = Readonly<Record<string, string>>;
48
57
  */
49
58
  export declare function serverWithheldEnvNames(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
50
59
  /**
51
- * 🔴 **唯一声明点**:把本进程自有凭据名向引擎声明(core `declareWithheldEnv`;重声明即替换,从下一次 spawn 起生效)。`modelApiKeyEnv` = 这一次要并进名单的模型条目表
52
- * (起服第一步 = 空表;换代 = 候选表),名单 = 此前声明过的 ∪ 这张表的应声明集合 —— 名单只随**落地**的世代增长:落地过的名不再退出(改名 / 删条目之后它的值仍在
53
- * 本进程 env 里),没落地的候选不留痕(旧世代在 CAS 处就拒、不到这里;换装拒 ⇒ {@link withdrawServerWithheldEnv})。引擎对坏形名 / 运行时回填名(`PATH` / `HOME` /
54
- * `USER` …)响亮抛且声明保持原状 —— 本函数不接住:起服那次抛 = 拒启;换代那次抛 = 候选整拒(`applyEffective` 抛,与 stage 抛同路)。返回声明的名单(只名、不值)。
60
+ * 本进程**持有凭据值**的变量名(值臂的来源;core 7.52.0 #1754):目录 secret 名 ∪ 模型条目 `apiKeyEnv` 的值 —— 名单与值臂两臂同一张表派生,只少名单型旋钮名(它们的值是
61
+ * 一张变量名单,不是凭据)。纯函数,排序只为读数稳定。
62
+ */
63
+ export declare function serverCredentialValueSources(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
64
+ /**
65
+ * 🔴 **唯一声明点**:把本进程自有凭据向引擎声明(core 7.52.0 `declareWithheldEnv({ names, values })`;重声明即整表替换,从下一次 spawn 起生效)。`modelApiKeyEnv` = 这一次要并进的
66
+ * 模型条目表(起服第一步 = 空表;换代 = 候选表)。两臂都只随**落地**的世代增长(落地过的名 / 值来源不退出:本进程 env 是 boot 期输入;没落地的候选不留痕 ——
67
+ * 换装拒 ⇒ {@link withdrawServerWithheldEnv})。
68
+ * · **名臂**:此前声明过的 ∪ 这张表的 {@link serverWithheldEnvNames}。引擎对坏形名 / 运行时回填名(`PATH` / `HOME` …)响亮抛且声明保持原状 —— 本函数不接住:
69
+ * 起服那次抛 = 拒启;换代那次抛 = 候选整拒(`applyEffective` 抛,与 stage 抛同路)。第一次交表带着名臂与**此前已收下的值**(引擎收过、env 不变 ⇒ 同值照收),
70
+ * 所以这一次抛只可能是名的问题。
71
+ * · **值臂**:{@link serverCredentialValueSources} 的每一个变量此刻在 env 里的值,逐个交给引擎**同一只**判(不另写「什么算凭据值」的第二份判据):引擎收下 ⇒ 记进值臂;
72
+ * 引擎拒(不是凭据值:空白 / 占位词 / 一个字符重复 / 不足 8 字符;或它是每个子进程都会拿到的变量的值)⇒ 这一个值不扣、名照扣、**不拒启**(与引擎自己的收值口
73
+ * `holdOwnCredentialValues` 同一姿势:不收 + 说一次),`console.warn` 点名那个变量一次(引擎的拒句从不回显值;本句也不),能力位 `inherit_env.own_credential_values_withheld`
74
+ * 因此答 false(位真 ⇔ 值臂真扣)。引擎拒一个值时声明保持上一份,所以逐个交表的中间态都是上一份的超集。
75
+ * 返回声明的名单(只名、不值)。
55
76
  */
56
77
  export declare function declareServerWithheldEnv(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
57
78
  /**
58
- * 席位拒 ⇒ 撤回最近一次声明(回到它之前的集合):`applyEffective` 在 Runner 换装抛时调,紧跟着那一次 {@link declareServerWithheldEnv} —— 没落地的候选不留痕。
59
- * 退回去的集合是引擎之前接受过的(判名确定)⇒ 不抛;连撤两次是同一个结果(幂等)。
79
+ * 席位拒 ⇒ 撤回最近一次声明(两臂一起回到它之前的那一份):`applyEffective` 在 Runner 换装抛时调,紧跟着那一次 {@link declareServerWithheldEnv} —— 没落地的候选不留痕。
80
+ * 退回去的那一份是引擎之前接受过的(名确定、值来源的值随 env 不变)⇒ 不抛;连撤两次是同一个结果(幂等)。
60
81
  */
61
82
  export declare function withdrawServerWithheldEnv(): void;
62
83
  /** 把活配置交给能力位读(stage-01 / run-local 在 `loadConfig()` 之后各一次;读的是 `config.modelApiKeyEnv` 这个**属性**,commit 整表重赋值之后看到的就是新表)。 */
63
84
  export declare function bindOwnCredentialsConfig(config: Pick<ServiceConfig, "modelApiKeyEnv">): void;
64
85
  /**
65
- * 能力词 `inherit_env.own_credentials_withheld` 在本进程的事实:最近一次成功声明的集合 ⊇ 当前生效配置应声明的集合。是一次比较,不是「声明过」的旗 ——
86
+ * 能力词 `inherit_env.own_credentials_withheld` 在本进程的事实:最近一次成功声明的名单 ⊇ 当前生效配置应声明的名单。是一次比较,不是「声明过」的旗 ——
66
87
  * 活表若被谁绕过声明写了新名,这里立刻 false(位不替流程担保)。没绑活配置 / 没声明过 ⇒ false(fail-closed)。
67
88
  */
68
89
  export declare function ownCredentialsWithheld(): boolean;
69
- /** 测试缝:撤回声明(引擎侧重声明为空)、忘掉声明集合(含撤回格)与活配置;生产代码从不调它。 */
90
+ /**
91
+ * 能力词 `inherit_env.own_credential_values_withheld`(core 7.52.0)在本进程的事实:当前生效配置的每一个凭据值来源({@link serverCredentialValueSources}),只要它此刻在 env 里
92
+ * 有值,那个值都已交进值臂、被引擎收下。位真 ⇔ 值臂真扣:一个值被引擎判「扣不了」⇒ false;env 里没有值的来源没有东西可扣,不影响事实。没绑活配置 / 没声明过 ⇒ false。
93
+ */
94
+ export declare function ownCredentialValuesWithheld(): boolean;
95
+ /** 测试缝:撤回声明(引擎侧重声明为空表)、忘掉两份声明镜像、点名记账与活配置;生产代码从不调它。 */
70
96
  export declare function __resetServerWithheldEnvForTest(): void;
71
- /** 一条宿主腿要什么:现场(留痕)、继承策略(缺省 `"scrub"`;只有模型可驱动的 host shell 交非缺省词)、部署方点名放回的键。 */
97
+ /** 一条宿主腿要什么:现场(留痕)、继承策略(缺省 `"scrub"`;按头注「腿的继承词」一条由调用点定)、部署方点名放回的键。 */
72
98
  export interface HostSubprocessEnvRequest {
73
99
  readonly site: SecretEnvScrubSite;
74
100
  readonly policy?: InheritEnvPolicy | undefined;
@@ -78,8 +104,8 @@ export interface HostSubprocessEnvRequest {
78
104
  * 🔴 **宿主子进程 env 的唯一组合**:{@link composeHostSubprocessEnv} + 留痕。**没有按原样交给子进程**的名字(剥掉的)经 `site` 留痕;点名放回的键取回源值,
79
105
  * 不是剥除,不计数、不披露。源 env 恒为本进程 env(引擎只读 `process.env`,本仓没有第二个源)。
80
106
  *
81
- * 六条宿主腿都只经它(直接或经 {@link gitSubprocessEnv}):host shell(三个继承词原样交给 `policy`)、project-memory / center-plugins / leader 三条 git 腿、
82
- * 本地语言服务器、bake-runner 的每一只子进程组。`allow` 只在**有部署级出路**的现场非空(今天 = `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`,
107
+ * 九条宿主腿都只经它(直接或经 {@link gitSubprocessEnv}):host shell(三个继承词原样交给 `policy`)、project-memory / center-plugins / leader 三条 git 腿、
108
+ * 本地语言服务器、bake-runner 的每一只子进程组、local-docker 与 adb 两条 CLI 腿(`"all"`)、settings hooks 的命令腿(严格名单)。`allow` 只在**有部署级出路**的现场非空(今天 = `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`,
83
109
  * 它们的现场在 `SECRET_ENV_SCRUB_SITES` 里登记了 `remedy`,披露行因此是 warn + 放行名单 + 出路句);其余现场传 `[]`。
84
110
  * 返回 `NodeJS.ProcessEnv` 形(值可能是 `undefined` 的键本来就不会进子进程);调用方显式要交的键(`LC_ALL`、`cfg.env` …)叠在它之上。
85
111
  * 调用时机 = 每次要交 env 时现算一次(`process.env` 在本仓是 boot 期输入,各次同值;计数因此是「每组合一次」)。
@@ -7,18 +7,42 @@ const NO_MODEL_ENTRIES = Object.freeze({});
7
7
  export function serverWithheldEnvNames(modelApiKeyEnv = NO_MODEL_ENTRIES) {
8
8
  return [...new Set([...CATALOG_SECRET_ENV_NAMES, ...ENV_NAME_ALLOWLIST_KNOB_NAMES, ...Object.values(modelApiKeyEnv)])].sort();
9
9
  }
10
+ export function serverCredentialValueSources(modelApiKeyEnv = NO_MODEL_ENTRIES) {
11
+ return [...new Set([...CATALOG_SECRET_ENV_NAMES, ...Object.values(modelApiKeyEnv)])].sort();
12
+ }
10
13
  let declared;
11
14
  let beforeLast;
15
+ const valueRefusalAnnounced = new Set();
12
16
  let liveConfig;
17
+ const envValueOf = (name) => process.env[name];
18
+ const valuesOf = (sources) => [...sources].map(envValueOf).filter((v) => typeof v === "string" && v !== "");
13
19
  export function declareServerWithheldEnv(modelApiKeyEnv = NO_MODEL_ENTRIES) {
14
- const names = [...new Set([...(declared ?? []), ...serverWithheldEnvNames(modelApiKeyEnv)])].sort();
15
- declareWithheldEnv(names);
20
+ const names = [...new Set([...(declared?.names ?? []), ...serverWithheldEnvNames(modelApiKeyEnv)])].sort();
21
+ const kept = [...(declared?.valueSources ?? [])];
22
+ declareWithheldEnv({ names, values: valuesOf(kept) });
23
+ const valueSources = new Set(kept);
24
+ for (const source of serverCredentialValueSources(modelApiKeyEnv)) {
25
+ if (valueSources.has(source) || valuesOf([source]).length === 0)
26
+ continue;
27
+ try {
28
+ declareWithheldEnv({ names, values: valuesOf([...valueSources, source]) });
29
+ valueSources.add(source);
30
+ }
31
+ catch (e) {
32
+ if (!valueRefusalAnnounced.has(source)) {
33
+ valueRefusalAnnounced.add(source);
34
+ console.warn(`[sema-server] own credential ${source}: its value is not withheld by value from spawned children — the engine refused it (${e instanceof Error ? e.message : String(e)}); ` +
35
+ "the variable name is still withheld under every inheritEnv policy, but a variable holding the same string under another name is not, and GET /v1/capabilities answers inherit_env.own_credential_values_withheld: false. " +
36
+ "Give it a real credential value (at least 8 characters, not a placeholder) to withhold copies of it too.");
37
+ }
38
+ }
39
+ }
16
40
  beforeLast = declared;
17
- declared = new Set(names);
41
+ declared = { names: new Set(names), valueSources };
18
42
  return names;
19
43
  }
20
44
  export function withdrawServerWithheldEnv() {
21
- declareWithheldEnv([...(beforeLast ?? [])]);
45
+ declareWithheldEnv({ names: [...(beforeLast?.names ?? [])], values: valuesOf(beforeLast?.valueSources ?? []) });
22
46
  declared = beforeLast;
23
47
  }
24
48
  export function bindOwnCredentialsConfig(config) {
@@ -27,23 +51,40 @@ export function bindOwnCredentialsConfig(config) {
27
51
  export function ownCredentialsWithheld() {
28
52
  if (declared === undefined || liveConfig === undefined)
29
53
  return false;
30
- const own = declared;
54
+ const own = declared.names;
31
55
  return serverWithheldEnvNames(liveConfig.modelApiKeyEnv).every((name) => own.has(name));
32
56
  }
57
+ export function ownCredentialValuesWithheld() {
58
+ if (declared === undefined || liveConfig === undefined)
59
+ return false;
60
+ const own = declared.valueSources;
61
+ return serverCredentialValueSources(liveConfig.modelApiKeyEnv).every((source) => own.has(source) || valuesOf([source]).length === 0);
62
+ }
33
63
  export function __resetServerWithheldEnvForTest() {
34
- declareWithheldEnv([]);
64
+ declareWithheldEnv({ names: [], values: [] });
35
65
  declared = undefined;
36
66
  beforeLast = undefined;
37
67
  liveConfig = undefined;
68
+ valueRefusalAnnounced.clear();
38
69
  }
39
70
  export function hostSubprocessEnv(o) {
40
71
  const findings = [];
41
72
  const composed = composeHostSubprocessEnv(o, findings);
42
- recordSecretEnvScrub(o.site, findings.filter((f) => composed[f.key] !== process.env[f.key]), o.allow);
73
+ const disclosed = [];
74
+ const seen = new Set();
75
+ for (const f of findings) {
76
+ const k = `${f.key}=${f.kind}`;
77
+ if (composed[f.key] === envValueOf(f.key) || seen.has(k))
78
+ continue;
79
+ seen.add(k);
80
+ disclosed.push(f);
81
+ }
82
+ recordSecretEnvScrub(o.site, disclosed, o.allow);
43
83
  return composed;
44
84
  }
45
85
  export function composeHostSubprocessEnv(o, findings = []) {
46
- return { ...inheritedHostEnv(o.policy ?? "scrub", findings), ...allowlistedEnv(o.allow, process.env) };
86
+ const putBack = o.allow.length > 0 ? inheritedHostEnv([...o.allow], findings) : {};
87
+ return { ...inheritedHostEnv(o.policy ?? "scrub", findings), ...putBack };
47
88
  }
48
89
  export function gitSubprocessEnv(o) {
49
90
  return {
@@ -27,8 +27,18 @@
27
27
  * `open` 面留白(#1077 形,见上)。
28
28
  * · `not_found` —— 留白:每一面各有自己的「不存在」答法(404 `not_found.session` / 同步口的 `resume.session_not_found` /
29
29
  * 列表里的缺席),码位各不相同,不由本表统一。
30
- * · `invalid_entry` / `invalid_fork_target` / `placement_refused` —— 留白:本仓今天没有一条 wire 口把它们作为自己的
31
- * 应答(它们在 core 的追加 / 分叉 / 放置面上抛,落进各站点既有的处置或通用 500)。给它们起名是另一件事、另一张票。
30
+ * · `placement_refused` —— `import` 面 **409 `conflict.session_placed`**(机读位 `detail.placement_kind`,固定句);`open` 面留白。
31
+ * 同一个词在两面上说的不是同一件事:import 面只有「会话同步往一只**分区会话**(委派子代的转录)上写」一个来源
32
+ * (SQL 两店的整段换装 / 暂存提交门:目标 id 的 `placement_kind` 在场 ⇒ 不适用),调用方没做错格式、是**目标**不收这种写;
33
+ * open 面上同一个词还含「声明了分区的创建撞上了分区外 / 异组的行」两形(core `TtlSessionStore.assertPlacementAdmission` 的后两条),
34
+ * 那不是「目标是分区会话」。而 run 终局上它是引擎词汇(`terminal.code`),原样随 failed 体走 —— 若在这里分诊成 409,
35
+ * 体上的 `errorCode` 仍是引擎词 `placement_refused`,一个状态两个名字。所以 open 面留白,`invalid_session` 是同形先例。
36
+ * 409 的语义:目标会话**状态**不收这种写(重试同一个 id 同一结果;换一个会话 id 推)—— 与 `conflict.session_ownerless` / `conflict.session_children_alive` 同族。
37
+ * `detail.placement_kind` 是**常量**,不是从错误里读的:core 的 `SessionError` 只带 `code` 与句子,不带种类;今天分区种类闭集只有
38
+ * `"subagent"` 一个词,所以常量就是事实。core 给 `SessionPlacementRecord["kind"]` 加第二个词 ⇒ 下面的守卫编译红,由人裁定种类从哪儿读
39
+ * (请求 core 把种类放进错误,而不是在这里解析句子)。
40
+ * · `invalid_entry` / `invalid_fork_target` —— 留白:本仓今天没有一条 wire 口把它们作为自己的
41
+ * 应答(它们在 core 的追加 / 分叉面上抛,落进各站点既有的处置或通用 500)。给它们起名是另一件事、另一张票。
32
42
  * · `storage` / `conflict` / `unknown` —— 留白:`conflict` 是 run 的写撞上真并发写,落成那条 run 的 `failed` 终局
33
43
  * (`terminal.code: "conflict"`),提交腿不另作处置;`storage` / `unknown` 是故障类,通用 500 就是它们今天的应答。
34
44
  *
@@ -50,9 +60,16 @@ export interface SessionErrorWire {
50
60
  * 常量锚格),本批逐字不改。
51
61
  */
52
62
  readonly sentence?: string;
63
+ /** 机读事实(体顶层的 `detail` 键;缺席 = 体里不带这个键)。只有 import 面的 `placement_refused` 用它:`{ placement_kind }`。 */
64
+ readonly detail?: Readonly<Record<string, string>>;
53
65
  }
54
66
  /** import 面 `invalid_session` 的固定句(修前 session-sync 暂存导入腿那一行的原文)。 */
55
67
  export declare const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
68
+ /**
69
+ * import 面 `placement_refused` 的固定句:wire 上不发引擎原句 —— 两家 SQL 店的原句不同(措辞各自铸),都点名会话 id 与引擎内部词
70
+ * (「placement partition」「delegation transcript」);固定句只说调用方能做什么(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
71
+ */
72
+ export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
56
73
  export declare function sessionErrorHttp(code: SessionErrorCode, face: SessionErrorFace): SessionErrorWire | undefined;
57
74
  export declare function isSessionErrorCode(code: string): code is SessionErrorCode;
58
75
  //# sourceMappingURL=session-error-wire.d.ts.map
@@ -1,16 +1,20 @@
1
1
  export const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
2
+ export const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
3
+ const PLACEMENT_KIND = "subagent";
2
4
  const CORRUPT_SESSION = { status: 500, errorCode: "corrupt_session" };
3
5
  const INVALID_ENTRIES = { status: 422, errorCode: "invalid_entries", sentence: STAGED_IMPORT_INVALID_SENTENCE };
6
+ const SESSION_PLACED = { status: 409, errorCode: "conflict.session_placed", sentence: PLACED_SESSION_SENTENCE, detail: { placement_kind: PLACEMENT_KIND } };
4
7
  export function sessionErrorHttp(code, face) {
5
8
  switch (code) {
6
9
  case "corrupt_session":
7
10
  return CORRUPT_SESSION;
8
11
  case "invalid_session":
9
12
  return face === "import" ? INVALID_ENTRIES : undefined;
13
+ case "placement_refused":
14
+ return face === "import" ? SESSION_PLACED : undefined;
10
15
  case "not_found":
11
16
  case "invalid_entry":
12
17
  case "invalid_fork_target":
13
- case "placement_refused":
14
18
  case "storage":
15
19
  case "conflict":
16
20
  case "unknown":
@@ -61,10 +61,19 @@ export declare class SessionIncarnationMissingError extends Error {
61
61
  constructor(sessionId: string);
62
62
  }
63
63
  /**
64
- * 行上化身那一格的**唯一解码**(三只店的 `sessionFaceOf` 与 SQL 两店 wake 带出的会话元数据都经它 —— 空值判据只写这一处)。
65
- * 不是非空字符串 ⇒ {@link SessionIncarnationMissingError}。
64
+ * 空化身那一格怎么读 —— {@link incarnationFromCell} 的参数(一只解码,两种**显式**读法;不是两只函数):
65
+ * · `refuse`(缺省,读口):一位活住客必须有令牌 ⇒ 空 / 非串 = {@link SessionIncarnationMissingError}(响亮拒,不当通配);
66
+ * · `absent`:调用方问的是「这一格里有没有一只令牌」,空 / 非串的答案是**没有**(`undefined`)—— 会话树删除时的空间键
67
+ * (没有令牌 = 没有空间,不回收缓存卷)与整段换装的沿用判据(没有令牌 = 铸一只新的)。
66
68
  */
67
- export declare function incarnationFromCell(sessionId: string, cell: unknown): string;
69
+ export type EmptyIncarnationReading = "refuse" | "absent";
70
+ /**
71
+ * 行上化身那一格的**唯一解码**(三只店的 `sessionFaceOf`、SQL 两店 wake 带出的会话元数据、留存删除的空间键、整段换装的沿用判据都经它 ——
72
+ * 「是不是一只令牌」只判这一处)。非空字符串 ⇒ 那只令牌;否则按 `empty`({@link EmptyIncarnationReading}):缺省 `refuse` ⇒
73
+ * {@link SessionIncarnationMissingError},`absent` ⇒ `undefined`。
74
+ */
75
+ export declare function incarnationFromCell(sessionId: string, cell: unknown, empty?: "refuse"): string;
76
+ export declare function incarnationFromCell(sessionId: string, cell: unknown, empty: "absent"): string | undefined;
68
77
  /** 店把一行原始列读成 {@link SessionFace} 的唯一口(三只店共用;化身那一格经 {@link incarnationFromCell})。 */
69
78
  export declare function sessionFaceFromRow(sessionId: string, owner: string | null, incarnation: unknown): SessionFace;
70
79
  /** 按 id 读住客(core `SessionStore.incarnationOf` 的形):`undefined` = 没有这只会话;读抛 = 读故障,不是答案。 */
@@ -81,9 +90,10 @@ export declare function incarnationReadOf(store: Pick<SessionStore, "incarnation
81
90
  export declare function sessionFaceReadOf(store: object | undefined): SessionFaceReader | undefined;
82
91
  /**
83
92
  * session-sync **整段换装**(replace)时化身的去留 —— 三只店共用的一句判据:换装删掉再插回的是**同一位住客**的那一行
84
- * (删除带属主门),所以行在、属主相同、化身非空 ⇒ 沿用;行不在(这是一次新建)或还是空的存量形 ⇒ 铸一只新的。
93
+ * (删除带属主门),所以行在、属主相同、那一格里有一只令牌(唯一解码 {@link incarnationFromCell} 的 `absent` 读法)⇒ 沿用;
94
+ * 行不在(这是一次新建)或还是空的存量形 ⇒ 铸一只新的。
85
95
  */
86
- export declare function carriedIncarnation(prior: {
96
+ export declare function carriedIncarnation(sessionId: string, prior: {
87
97
  owner?: unknown;
88
98
  incarnation?: unknown;
89
99
  } | undefined, owner: string | null): string;