@sema-agent/server 7.149.0 → 7.151.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 (441) hide show
  1. package/MIGRATION.md +307 -9
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +92 -40
  5. package/deploy/sema-up/README.md +7 -1
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +1 -0
  14. package/deploy/sema-up/kube-up.sh +1 -1
  15. package/deploy/sema-up/lib/flagshape.sh +1 -1
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/dist/adoption/import.js +3 -3
  19. package/dist/approval-ask-machine.d.ts +1 -1
  20. package/dist/approval-card.d.ts +3 -3
  21. package/dist/approval-gate-currency.d.ts +2 -2
  22. package/dist/audit.d.ts +1 -1
  23. package/dist/audit.js +2 -2
  24. package/dist/auth-bridge.d.ts +20 -0
  25. package/dist/auth-bridge.js +9 -0
  26. package/dist/background-session-reap.d.ts +2 -2
  27. package/dist/bake-runner/main.d.ts +4 -2
  28. package/dist/bind-host.d.ts +2 -3
  29. package/dist/bind-host.js +2 -4
  30. package/dist/boot/budget-tracing.js +1 -1
  31. package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
  32. package/dist/boot/deferred-sandbox-path-env.js +1 -2
  33. package/dist/boot/engine-lease.d.ts +5 -0
  34. package/dist/boot/engine-lease.js +1 -0
  35. package/dist/boot/execution-env.d.ts +8 -14
  36. package/dist/boot/execution-env.js +54 -17
  37. package/dist/boot/execution-lane.js +32 -5
  38. package/dist/boot/late-binds.d.ts +8 -4
  39. package/dist/boot/late-binds.js +7 -1
  40. package/dist/boot/memory-consolidation.d.ts +3 -2
  41. package/dist/boot/memory-consolidation.js +6 -6
  42. package/dist/boot/parked-revive-gate.d.ts +5 -5
  43. package/dist/boot/parked-revive-gate.js +2 -3
  44. package/dist/boot/reapers.d.ts +5 -0
  45. package/dist/boot/reapers.js +12 -1
  46. package/dist/boot/resolve-spec.d.ts +7 -8
  47. package/dist/boot/resolve-spec.js +80 -35
  48. package/dist/boot/retention-lane.d.ts +1 -1
  49. package/dist/boot/runner-deps.d.ts +9 -2
  50. package/dist/boot/runner-deps.js +3 -3
  51. package/dist/boot/session-age-out.d.ts +36 -0
  52. package/dist/boot/session-age-out.js +101 -0
  53. package/dist/boot/session-faces.d.ts +5 -14
  54. package/dist/boot/session-faces.js +28 -24
  55. package/dist/boot/stage-01-config.js +2 -0
  56. package/dist/boot/stage-03-store-backend.js +2 -2
  57. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  58. package/dist/boot/stage-05-execution-env.js +2 -2
  59. package/dist/boot/stage-06-runners.d.ts +7 -4
  60. package/dist/boot/stage-06-runners.js +16 -8
  61. package/dist/boot/stage-07-capability-layer.d.ts +7 -4
  62. package/dist/boot/stage-07-capability-layer.js +3 -2
  63. package/dist/boot/stage-08-reapers.d.ts +7 -4
  64. package/dist/boot/stage-08-reapers.js +4 -2
  65. package/dist/boot/stage-09-leader.d.ts +11 -5
  66. package/dist/boot/stage-09-leader.js +12 -3
  67. package/dist/boot/stage-10-http-server.d.ts +44 -6
  68. package/dist/boot/stage-10-http-server.js +12 -10
  69. package/dist/boot/web-admin.d.ts +1 -1
  70. package/dist/boot/web-admin.js +3 -1
  71. package/dist/boot/workflow-orchestration.d.ts +7 -2
  72. package/dist/boot/workflow-orchestration.js +24 -7
  73. package/dist/bounded-rotation.d.ts +29 -0
  74. package/dist/bounded-rotation.js +24 -0
  75. package/dist/capability-facts.d.ts +84 -66
  76. package/dist/capability-facts.js +58 -41
  77. package/dist/center-credential.d.ts +25 -6
  78. package/dist/center-credential.js +25 -5
  79. package/dist/config-catalog.d.ts +26 -7
  80. package/dist/config-catalog.js +15 -12
  81. package/dist/config-invariants.d.ts +2 -1
  82. package/dist/config-invariants.js +4 -4
  83. package/dist/config-types.d.ts +22 -15
  84. package/dist/config.d.ts +51 -2
  85. package/dist/config.js +35 -24
  86. package/dist/deployment-governance.d.ts +7 -28
  87. package/dist/deployment-governance.js +1 -14
  88. package/dist/deployment-shape.d.ts +9 -1
  89. package/dist/deployment-shape.js +2 -1
  90. package/dist/device-protocol.d.ts +5 -4
  91. package/dist/device-protocol.js +1 -1
  92. package/dist/device-ws-hub.d.ts +1 -0
  93. package/dist/device-ws-hub.js +66 -29
  94. package/dist/device-ws-protocol.d.ts +79 -12
  95. package/dist/device-ws-protocol.js +64 -26
  96. package/dist/engine-identity.d.ts +23 -5
  97. package/dist/engine-identity.js +13 -0
  98. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  99. package/dist/execution-env-refusal.d.ts +23 -0
  100. package/dist/execution-env-refusal.js +5 -0
  101. package/dist/execution-lane-caps.d.ts +3 -1
  102. package/dist/field-conflict.d.ts +3 -3
  103. package/dist/file-history-capture.d.ts +11 -4
  104. package/dist/file-history-capture.js +9 -6
  105. package/dist/file-history-disclosure.d.ts +7 -5
  106. package/dist/file-history-disclosure.js +7 -5
  107. package/dist/fleet/drain-entry.d.ts +4 -0
  108. package/dist/fleet/engine-signal.d.ts +14 -1
  109. package/dist/fleet/engine-signal.js +5 -1
  110. package/dist/fleet/fleet-reconciler.d.ts +1 -1
  111. package/dist/fleet/serving-lease.d.ts +18 -3
  112. package/dist/fleet/serving-lease.js +81 -35
  113. package/dist/fleet-client.d.ts +13 -11
  114. package/dist/fleet-client.js +53 -33
  115. package/dist/history-anchor.js +1 -1
  116. package/dist/hitl-delivery.d.ts +1 -3
  117. package/dist/hitl-delivery.js +1 -1
  118. package/dist/hooks/hook-runner.js +2 -2
  119. package/dist/host-lsp-manager.d.ts +2 -2
  120. package/dist/http/active-run-conflict.d.ts +3 -7
  121. package/dist/http/active-run-conflict.js +2 -2
  122. package/dist/http/admission.js +19 -4
  123. package/dist/http/approval-sweeps.js +7 -6
  124. package/dist/http/caller-trust.d.ts +2 -2
  125. package/dist/http/caller-trust.js +3 -3
  126. package/dist/http/checkpoint-ctx.d.ts +20 -63
  127. package/dist/http/checkpoint-ctx.js +2 -24
  128. package/dist/http/claim-heartbeat.d.ts +4 -4
  129. package/dist/http/claim-heartbeat.js +3 -3
  130. package/dist/http/dispatch.d.ts +2 -1
  131. package/dist/http/dispatch.js +36 -29
  132. package/dist/http/durable-run-leg.js +17 -17
  133. package/dist/http/health-self-report.d.ts +9 -1
  134. package/dist/http/health-self-report.js +2 -0
  135. package/dist/http/owner-access.d.ts +264 -20
  136. package/dist/http/owner-access.js +215 -5
  137. package/dist/http/readiness.d.ts +4 -2
  138. package/dist/http/resume-ctx-read.js +38 -1
  139. package/dist/http/resume-legs.d.ts +2 -1
  140. package/dist/http/resume-legs.js +273 -89
  141. package/dist/http/route-ctx.d.ts +41 -19
  142. package/dist/http/route-table.d.ts +1 -1
  143. package/dist/http/routes/a2a-serve.js +15 -14
  144. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  145. package/dist/http/routes/agents-roster.js +2 -3
  146. package/dist/http/routes/approvals-assistant.d.ts +3 -2
  147. package/dist/http/routes/approvals-assistant.js +12 -12
  148. package/dist/http/routes/background.d.ts +3 -3
  149. package/dist/http/routes/capabilities.js +10 -6
  150. package/dist/http/routes/config-catalog.d.ts +1 -1
  151. package/dist/http/routes/fleet.js +10 -8
  152. package/dist/http/routes/mcp-reconnect.js +2 -2
  153. package/dist/http/routes/memory-origin.d.ts +1 -1
  154. package/dist/http/routes/notify-wake.js +2 -3
  155. package/dist/http/routes/projects.d.ts +4 -2
  156. package/dist/http/routes/projects.js +7 -6
  157. package/dist/http/routes/retention-ops.d.ts +1 -1
  158. package/dist/http/routes/run-permission-mode.d.ts +1 -1
  159. package/dist/http/routes/run-permission-mode.js +2 -2
  160. package/dist/http/routes/runs.d.ts +1 -1
  161. package/dist/http/routes/runs.js +125 -66
  162. package/dist/http/routes/session-memory-sync.js +4 -5
  163. package/dist/http/routes/session-sync.d.ts +4 -3
  164. package/dist/http/routes/session-sync.js +174 -83
  165. package/dist/http/routes/sessions-list.js +13 -7
  166. package/dist/http/routes/sessions.d.ts +1 -1
  167. package/dist/http/routes/sessions.js +26 -48
  168. package/dist/http/routes/tasks.js +38 -23
  169. package/dist/http/routes/trace-usage.js +14 -14
  170. package/dist/http/routes/workflows.d.ts +1 -0
  171. package/dist/http/routes/workflows.js +20 -38
  172. package/dist/http/server.d.ts +28 -30
  173. package/dist/http/server.js +7 -3
  174. package/dist/http/stored-body-replay.d.ts +3 -24
  175. package/dist/http/stored-body-replay.js +2 -12
  176. package/dist/http/submit-ctx.d.ts +1 -2
  177. package/dist/http/submit-ctx.js +8 -6
  178. package/dist/http/submit-replay.d.ts +15 -2
  179. package/dist/http/submit-replay.js +10 -4
  180. package/dist/http/wire-types.d.ts +19 -6
  181. package/dist/identity-source.d.ts +20 -3
  182. package/dist/identity-source.js +14 -0
  183. package/dist/index.d.ts +4 -0
  184. package/dist/lane-home-probe.d.ts +3 -7
  185. package/dist/lane-home-probe.js +0 -1
  186. package/dist/leader/endpoint.js +9 -8
  187. package/dist/leader/leader.d.ts +2 -1
  188. package/dist/leg-facts.d.ts +19 -5
  189. package/dist/leg-facts.js +3 -1
  190. package/dist/mcp-authorization-face.d.ts +18 -14
  191. package/dist/mcp-authorization-face.js +3 -2
  192. package/dist/memory-scope.d.ts +5 -4
  193. package/dist/memory-scope.js +4 -4
  194. package/dist/memory-store-refusal.d.ts +1 -1
  195. package/dist/memory-sync-client.d.ts +30 -2
  196. package/dist/memory-sync-client.js +16 -9
  197. package/dist/observability/corrupt-read-seat.d.ts +1 -1
  198. package/dist/observability/err-text.d.ts +7 -0
  199. package/dist/observability/err-text.js +5 -0
  200. package/dist/observability/fail-open.d.ts +12 -8
  201. package/dist/observability/fail-open.js +12 -8
  202. package/dist/observability/logger.d.ts +7 -0
  203. package/dist/observability/logger.js +3 -1
  204. package/dist/observability/metrics.js +1 -0
  205. package/dist/observability/run-terminal.d.ts +1 -1
  206. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  207. package/dist/orchestration/workflow-notify-journal.js +12 -1
  208. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  209. package/dist/orchestration/workflow-park-decision.js +49 -10
  210. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  211. package/dist/orchestration/workflow-park-holder.js +98 -0
  212. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  213. package/dist/orchestration/workflow-record-fence.js +42 -0
  214. package/dist/owner-faces.d.ts +28 -4
  215. package/dist/owner-faces.js +2 -0
  216. package/dist/parked-decide.d.ts +104 -53
  217. package/dist/parked-decide.js +153 -117
  218. package/dist/peer-directory.d.ts +2 -2
  219. package/dist/peer-inbound-face.d.ts +2 -6
  220. package/dist/peer-inbound-face.js +0 -3
  221. package/dist/peer-seat.d.ts +1 -1
  222. package/dist/peer-seat.js +52 -59
  223. package/dist/permission-mode-admission.d.ts +41 -5
  224. package/dist/permission-mode-admission.js +29 -3
  225. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  226. package/dist/plugins/adoption-log-sql.js +7 -1
  227. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  228. package/dist/plugins/approval-ask-store-file.js +8 -0
  229. package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
  230. package/dist/plugins/approval-ask-store-memory.js +28 -9
  231. package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
  232. package/dist/plugins/approval-ask-store-sql.js +34 -5
  233. package/dist/plugins/approval-exemption-store.js +3 -0
  234. package/dist/plugins/approval-nonce-store.js +2 -0
  235. package/dist/plugins/breaker-state-sql.js +2 -0
  236. package/dist/plugins/caching-session-store.d.ts +9 -15
  237. package/dist/plugins/caching-session-store.js +6 -0
  238. package/dist/plugins/device-store-sql.js +6 -0
  239. package/dist/plugins/error-origin.d.ts +18 -0
  240. package/dist/plugins/error-origin.js +10 -0
  241. package/dist/plugins/exec-path-law.d.ts +34 -0
  242. package/dist/plugins/exec-path-law.js +13 -0
  243. package/dist/plugins/execution-placement-sql.js +6 -6
  244. package/dist/plugins/file-run-store.js +1 -1
  245. package/dist/plugins/image-bake-store-sql.js +6 -0
  246. package/dist/plugins/image-index-sql.js +4 -0
  247. package/dist/plugins/landed-attendants.d.ts +212 -0
  248. package/dist/plugins/landed-attendants.js +161 -0
  249. package/dist/plugins/leader-run-store-sql.js +4 -0
  250. package/dist/plugins/local-checkpoint-store.d.ts +4 -1
  251. package/dist/plugins/local-checkpoint-store.js +3 -0
  252. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  253. package/dist/plugins/local-session-live-reference.js +39 -0
  254. package/dist/plugins/local-session-store.d.ts +71 -33
  255. package/dist/plugins/local-session-store.js +129 -27
  256. package/dist/plugins/memory-engine-pg.js +4 -0
  257. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  258. package/dist/plugins/memory-engine-tidb.js +4 -0
  259. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  260. package/dist/plugins/memory-run-store.js +1 -1
  261. package/dist/plugins/memory-sync-store-pg.js +5 -0
  262. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  263. package/dist/plugins/one-time-migrations.d.ts +80 -61
  264. package/dist/plugins/one-time-migrations.js +241 -104
  265. package/dist/plugins/org-delivery-quota-store.js +4 -1
  266. package/dist/plugins/outcome-ledger-sql.js +2 -0
  267. package/dist/plugins/permission-rule-store-sql.js +11 -4
  268. package/dist/plugins/pg-cost-quota.js +4 -0
  269. package/dist/plugins/pg-pool.js +28 -1
  270. package/dist/plugins/pg-rate-limiter.js +2 -0
  271. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  272. package/dist/plugins/posix-shell-fs.js +8 -3
  273. package/dist/plugins/remote-env-adb.d.ts +19 -15
  274. package/dist/plugins/remote-env-adb.js +44 -17
  275. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  276. package/dist/plugins/remote-env-connect-seat.js +72 -0
  277. package/dist/plugins/remote-env-device.d.ts +22 -5
  278. package/dist/plugins/remote-env-device.js +114 -14
  279. package/dist/plugins/remote-env-e2b.d.ts +18 -7
  280. package/dist/plugins/remote-env-e2b.js +53 -40
  281. package/dist/plugins/remote-env-file-error.js +6 -2
  282. package/dist/plugins/remote-env-host.d.ts +18 -1
  283. package/dist/plugins/remote-env-host.js +48 -47
  284. package/dist/plugins/remote-env-k8s.d.ts +41 -39
  285. package/dist/plugins/remote-env-k8s.js +56 -32
  286. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  287. package/dist/plugins/remote-env-local-docker.js +37 -43
  288. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  289. package/dist/plugins/remote-env-ssh.js +64 -62
  290. package/dist/plugins/remote-shell.d.ts +101 -2
  291. package/dist/plugins/remote-shell.js +221 -3
  292. package/dist/plugins/replica-registration.d.ts +35 -0
  293. package/dist/plugins/replica-registration.js +48 -0
  294. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  295. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  296. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  297. package/dist/plugins/retention-lane-store-sql.js +4 -0
  298. package/dist/plugins/retention-sql.d.ts +20 -2
  299. package/dist/plugins/retention-sql.js +11 -0
  300. package/dist/plugins/run-store-sql.d.ts +22 -3
  301. package/dist/plugins/run-store-sql.js +33 -9
  302. package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
  303. package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
  304. package/dist/plugins/schema-consistency.d.ts +9 -5
  305. package/dist/plugins/schema-consistency.js +48 -18
  306. package/dist/plugins/schema-drift-sentence.js +1 -1
  307. package/dist/plugins/send-file-ledger.js +3 -0
  308. package/dist/plugins/serving-requirement.d.ts +68 -0
  309. package/dist/plugins/serving-requirement.js +60 -0
  310. package/dist/plugins/session-birth.d.ts +6 -2
  311. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  312. package/dist/plugins/session-ext-table.d.ts +14 -1
  313. package/dist/plugins/session-ext-table.js +5 -1
  314. package/dist/plugins/session-row-sql.d.ts +49 -2
  315. package/dist/plugins/session-row-sql.js +56 -13
  316. package/dist/plugins/session-store-sql.d.ts +34 -18
  317. package/dist/plugins/session-store-sql.js +98 -17
  318. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  319. package/dist/plugins/shared-memory-store-sql.js +6 -2
  320. package/dist/plugins/sql-driver.d.ts +2 -1
  321. package/dist/plugins/sql-driver.js +18 -3
  322. package/dist/plugins/sql-errors.d.ts +11 -6
  323. package/dist/plugins/sql-errors.js +5 -6
  324. package/dist/plugins/stop-then-start-sentence.d.ts +48 -3
  325. package/dist/plugins/stop-then-start-sentence.js +48 -0
  326. package/dist/plugins/stop-then-start.d.ts +109 -0
  327. package/dist/plugins/stop-then-start.js +104 -0
  328. package/dist/plugins/store-backend.d.ts +40 -13
  329. package/dist/plugins/store-backend.js +169 -27
  330. package/dist/plugins/store-boundary.d.ts +57 -0
  331. package/dist/plugins/store-boundary.js +139 -0
  332. package/dist/plugins/store-contracts.d.ts +29 -2
  333. package/dist/plugins/store-contracts.js +3 -0
  334. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  335. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  336. package/dist/plugins/store-fault.d.ts +26 -7
  337. package/dist/plugins/store-fault.js +18 -2
  338. package/dist/plugins/task-attachment-store.js +9 -0
  339. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  340. package/dist/plugins/task-list-store-sql.js +10 -8
  341. package/dist/plugins/tidb-cost-quota.js +4 -0
  342. package/dist/plugins/tidb-pool.js +6 -1
  343. package/dist/plugins/tidb-rate-limiter.js +4 -0
  344. package/dist/plugins/user-input-ledger-sql.js +4 -0
  345. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  346. package/dist/plugins/workflow-run-store-sql.js +64 -4
  347. package/dist/plugins/workspace-fill.d.ts +4 -7
  348. package/dist/plugins/workspace-fill.js +2 -1
  349. package/dist/plugins/write-behind-counter.js +5 -0
  350. package/dist/process-instance.d.ts +3 -0
  351. package/dist/process-instance.js +7 -0
  352. package/dist/project-context.d.ts +64 -0
  353. package/dist/project-context.js +66 -0
  354. package/dist/project-registry.d.ts +46 -0
  355. package/dist/project-registry.js +44 -0
  356. package/dist/question.d.ts +9 -21
  357. package/dist/question.js +28 -19
  358. package/dist/request-key-closure.js +1 -1
  359. package/dist/request-value-closure.d.ts +4 -0
  360. package/dist/request-value-closure.js +10 -0
  361. package/dist/run-acceptance.d.ts +3 -2
  362. package/dist/run-acceptance.js +4 -6
  363. package/dist/run-cancel-card.d.ts +1 -1
  364. package/dist/run-cancel-card.js +2 -1
  365. package/dist/run-local.js +1 -0
  366. package/dist/runs.d.ts +37 -8
  367. package/dist/runs.js +53 -12
  368. package/dist/runtime-governance.d.ts +5 -4
  369. package/dist/security.d.ts +31 -33
  370. package/dist/security.js +41 -7
  371. package/dist/server-secret-env.d.ts +12 -10
  372. package/dist/server-secret-env.js +24 -15
  373. package/dist/session-agent.d.ts +1 -10
  374. package/dist/session-agent.js +0 -6
  375. package/dist/session-bindings.d.ts +82 -0
  376. package/dist/session-bindings.js +18 -0
  377. package/dist/session-children-retire.d.ts +2 -2
  378. package/dist/session-children-retire.js +2 -6
  379. package/dist/session-deletion.d.ts +16 -1
  380. package/dist/session-error-wire.d.ts +3 -3
  381. package/dist/session-error-wire.js +3 -3
  382. package/dist/session-incarnation.d.ts +28 -4
  383. package/dist/session-incarnation.js +14 -2
  384. package/dist/session-kind.d.ts +57 -0
  385. package/dist/session-kind.js +22 -0
  386. package/dist/session-notify-door.d.ts +4 -4
  387. package/dist/session-notify-door.js +5 -6
  388. package/dist/session-row.d.ts +21 -1
  389. package/dist/session-row.js +7 -1
  390. package/dist/session-rules-seat.d.ts +4 -3
  391. package/dist/session-rules-seat.js +3 -11
  392. package/dist/session-sync-kernel.d.ts +24 -14
  393. package/dist/session-sync-kernel.js +3 -6
  394. package/dist/session-sync.d.ts +4 -98
  395. package/dist/session-sync.js +4 -74
  396. package/dist/session-titler.d.ts +10 -3
  397. package/dist/session-titler.js +19 -6
  398. package/dist/ssh-host-key.d.ts +5 -0
  399. package/dist/ssh-host-key.js +3 -0
  400. package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
  401. package/dist/stores-sql/checkpoint-store-sql.js +106 -18
  402. package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
  403. package/dist/stores-sql/file-history-store-sql.js +108 -70
  404. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  405. package/dist/stores-sql/pg-session-storage.js +37 -13
  406. package/dist/stores-sql/retention-store-sql.d.ts +2 -10
  407. package/dist/stores-sql/retention-store-sql.js +2 -10
  408. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  409. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  410. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  411. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  412. package/dist/stores-sql/tidb-session-store.js +37 -13
  413. package/dist/submission-exit.d.ts +3 -2
  414. package/dist/submission-exit.js +9 -1
  415. package/dist/task-cwd.d.ts +6 -5
  416. package/dist/task-settings.d.ts +19 -5
  417. package/dist/task-settings.js +13 -7
  418. package/dist/terminal.d.ts +33 -2
  419. package/dist/terminal.js +139 -9
  420. package/dist/tool-approval.d.ts +147 -12
  421. package/dist/tool-approval.js +206 -109
  422. package/dist/trace/engine-notice-wire.d.ts +14 -0
  423. package/dist/trace/engine-notice-wire.js +18 -1
  424. package/dist/trace/project.d.ts +4 -3
  425. package/dist/trace/project.js +3 -2
  426. package/dist/trace/projection-table.d.ts +33 -2
  427. package/dist/trace/self-minted-wire.d.ts +422 -26
  428. package/dist/trace/self-minted-wire.js +149 -23
  429. package/dist/trace/tool-card.d.ts +3 -0
  430. package/dist/trace/tool-card.js +24 -0
  431. package/dist/trace/tool-output-media.d.ts +2 -1
  432. package/dist/unattended-permission-mode.d.ts +1 -1
  433. package/dist/web-admin-client/apply-effective.d.ts +1 -1
  434. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  435. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  436. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
  437. package/package.json +3 -3
  438. package/wire-changes/server@7.150.0.json +335 -0
  439. package/wire-changes/server@7.151.0.json +762 -0
  440. package/dist/http/session-inherit-env.d.ts +0 -36
  441. package/dist/http/session-inherit-env.js +0 -6
@@ -1,3 +1,4 @@
1
+ import { assembleFileHistory } from "./file-history-capture.js";
1
2
  import { buildOperatorRosterWayOut, operatorRosterPresent } from "./http/principal-gate.js";
2
3
  import { mcpInjectionHonored } from "./task-mcp.js";
3
4
  import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
@@ -5,9 +6,12 @@ import { presentedApprovalFrameFamily, resolveStreamApprovalGate } from "./tool-
5
6
  import { selfOrchestrationDenial } from "./task-workflow.js";
6
7
  import { centerEntitlementSourceWired } from "./runtime-caps-resolver.js";
7
8
  import { WEB_ADMIN_ENV } from "@sema-agent/settings-schema";
8
- import { blobExchangeOf, overwriteWipeIncapable } from "./session-sync.js";
9
+ import { blobExchangeOf } from "./session-sync.js";
10
+ import { overwriteWipeIncapable } from "./plugins/landed-attendants.js";
9
11
  import { WORKSPACE_PERSIST_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, workspaceSnapshotTimeoutOf } from "./workspace-space.js";
10
- import { deletionHeadReadOf, headReadOf } from "./session-incarnation.js";
12
+ import { sessionKindFaceOf } from "./session-kind.js";
13
+ import { birthFaceOf } from "./plugins/session-birth.js";
14
+ import { headReadPresent } from "./session-incarnation.js";
11
15
  import { laneWiresExecutionEnv } from "./execution-lane-caps.js";
12
16
  export const CAPABILITY_FACT_WHY = {
13
17
  run_store_absent: "no durable run store is wired (DB_BACKEND=mysql|pg|local)",
@@ -23,7 +27,7 @@ export const CAPABILITY_FACT_WHY = {
23
27
  session_fork_face_absent: "the session store has no fork face",
24
28
  session_row_faces_absent: "the session store has no session-row faces (headOf / sessionSummaryOf / writeSessionRowCells)",
25
29
  session_purge_absent: "no session purge coordinator is wired",
26
- session_policy_store_absent: "no session policy store is wired",
30
+ session_kind_faces_absent: "the session store cannot record a session kind (it needs the birth receipt face that takes a kind, sessionKindOf, listSessions and listIdleOfKind) or no session purge coordinator is wired to age such sessions out",
27
31
  store_backend_absent: "no store backend is wired (DB_BACKEND=memory, multi-tenant bare boot, or half-configured SQL)",
28
32
  file_history_store_absent: "no file-history store is wired",
29
33
  resume_anchor_store_absent: "no rewind anchor map is wired (the handle → session-entry map a rewind target is read through, with the run store an unknown handle is checked against — both come from the store backend)",
@@ -95,25 +99,28 @@ export function subagentSteer(d) {
95
99
  const runs = durableRuns(d);
96
100
  if (!runs.available)
97
101
  return runs;
98
- return d.subagentSteerRegistry !== undefined ? yes({ runStore: runs.runStore, registry: d.subagentSteerRegistry }) : no("subagent_registry_absent");
102
+ const registry = d.subagentSteerRegistry;
103
+ return registry !== undefined ? yes({ runStore: runs.runStore, registry }) : no("subagent_registry_absent");
99
104
  }
100
105
  export function subagentOutput(d) {
101
106
  const runs = durableRuns(d);
102
107
  if (!runs.available)
103
108
  return runs;
104
- return d.subagentTaskOutput !== undefined ? yes({ runStore: runs.runStore, output: d.subagentTaskOutput }) : no("subagent_output_face_absent");
109
+ const output = d.subagentTaskOutput;
110
+ return output !== undefined ? yes({ runStore: runs.runStore, output }) : no("subagent_output_face_absent");
105
111
  }
106
112
  export function taskHandles(d) {
107
113
  const runs = durableRuns(d);
108
114
  if (!runs.available)
109
115
  return runs;
110
- return d.taskHandleOutput !== undefined && d.taskHandleStop !== undefined
111
- ? yes({ runStore: runs.runStore, output: d.taskHandleOutput, stop: d.taskHandleStop })
116
+ const { taskHandleOutput: output, taskHandleStop: stop } = d;
117
+ return output !== undefined && stop !== undefined
118
+ ? yes({ runStore: runs.runStore, output, stop })
112
119
  : no("task_handle_faces_absent");
113
120
  }
114
121
  export function sessionOwnership(d) {
115
122
  const s = d.sessionStorage;
116
- return headReadOf(s) !== undefined ? yes({ sessionStorage: s }) : no("session_head_face_absent");
123
+ return headReadPresent(s) ? yes({ sessionStorage: s }) : no("session_head_face_absent");
117
124
  }
118
125
  export function executionPlacementRead(d) {
119
126
  const seat = d.sessionStorage?.executionPlacement;
@@ -141,67 +148,70 @@ export function sessionAuditView(d) {
141
148
  return d.sessionAudit !== undefined ? yes({ sessionAudit: d.sessionAudit }) : no("session_audit_absent");
142
149
  }
143
150
  export function sessionEventStream(d) {
144
- if (d.sessionWatch === undefined)
151
+ const watch = d.sessionWatch;
152
+ if (watch === undefined)
145
153
  return no("session_watch_absent");
146
154
  const owned = sessionOwnership(d);
147
155
  if (!owned.available)
148
156
  return owned;
149
- return yes({ watch: d.sessionWatch, sessionStorage: owned.sessionStorage });
157
+ return yes({ watch, sessionStorage: owned.sessionStorage });
150
158
  }
151
159
  export function sessionList(d) {
152
160
  const lister = d.sessionStorage?.listSessions?.bind(d.sessionStorage);
153
161
  return lister !== undefined ? yes({ lister }) : no("session_lister_absent");
154
162
  }
163
+ export function sessionKinds(d) {
164
+ const s = d.sessionStorage;
165
+ return birthFaceOf(s) !== undefined && sessionKindFaceOf(s) !== undefined && typeof s?.listSessions === "function" && typeof s.listIdleOfKind === "function" && d.purgeSession !== undefined
166
+ ? YES
167
+ : no("session_kind_faces_absent");
168
+ }
155
169
  export function sessionFork(d) {
156
170
  const s = d.sessionStorage;
157
171
  if (s?.fork === undefined)
158
172
  return no("session_fork_face_absent");
159
- if (headReadOf(s) === undefined)
173
+ if (!headReadPresent(s))
160
174
  return no("session_head_face_absent");
161
175
  return yes({ sessionStorage: s });
162
176
  }
163
177
  export function sessionPatch(d) {
164
178
  const s = d.sessionStorage;
165
- if (headReadOf(s) === undefined || s?.writeSessionRowCells === undefined)
179
+ if (!headReadPresent(s) || s?.writeSessionRowCells === undefined)
166
180
  return no("session_row_faces_absent");
167
181
  return yes({ sessionStorage: s });
168
182
  }
169
183
  export function sessionDelete(d) {
170
- if (d.purgeSession === undefined)
184
+ const purge = d.purgeSession;
185
+ if (purge === undefined)
171
186
  return no("session_purge_absent");
172
187
  const owned = sessionOwnership(d);
173
188
  if (!owned.available)
174
189
  return owned;
175
- const store = owned.sessionStorage;
176
- const headOf = deletionHeadReadOf(store);
177
- if (headOf === undefined)
178
- return no("session_head_face_absent");
179
- const placementOf = store.placementOf?.bind(store);
180
- return yes({ purge: d.purgeSession, gateStore: { headOf, ...(placementOf !== undefined ? { placementOf } : {}) } });
190
+ return yes({ purge, sessionStorage: owned.sessionStorage });
181
191
  }
182
192
  export function sessionPolicy(d) {
183
- if (d.sessionPolicyStore === undefined)
184
- return no("session_policy_store_absent");
193
+ const backend = d.backend;
194
+ if (backend === undefined)
195
+ return no("store_backend_absent");
185
196
  const owned = sessionOwnership(d);
186
197
  if (!owned.available)
187
198
  return owned;
188
- return yes({ policyStore: d.sessionPolicyStore, sessionStorage: owned.sessionStorage });
199
+ return yes({ sessionStorage: owned.sessionStorage, backend });
189
200
  }
190
201
  export function sessionSync(d) {
191
- if (d.backend === undefined)
202
+ const backend = d.backend;
203
+ if (backend === undefined)
192
204
  return no("store_backend_absent");
193
- if (d.fileHistoryStore === undefined)
194
- return no("file_history_store_absent");
195
205
  const s = d.sessionStorage;
196
206
  if (s?.exportEntries === undefined || s.exportEntriesStream === undefined)
197
207
  return no("session_export_absent");
198
208
  if (s.beginImportStaging === undefined)
199
209
  return no("session_import_staging_absent");
200
- if (headReadOf(s) === undefined || s.sessionSummaryOf === undefined || s.writeSessionRowCells === undefined)
210
+ if (!headReadPresent(s) || s.sessionSummaryOf === undefined || s.writeSessionRowCells === undefined)
201
211
  return no("session_row_faces_absent");
202
- if (overwriteWipeIncapable(d.sessionPolicyStore))
212
+ if (overwriteWipeIncapable(backend.sessionPolicy()))
203
213
  return no("policy_purge_absent");
204
- return yes({ backend: d.backend, sessionStorage: s, historyStore: d.fileHistoryStore });
214
+ return yes({ backend, sessionStorage: s, historyStore: assembleFileHistory(backend).store });
205
215
  }
206
216
  export function sessionSyncFileHistory(d) {
207
217
  const sync = sessionSync(d);
@@ -211,20 +221,22 @@ export function sessionSyncFileHistory(d) {
211
221
  return blobExchange !== undefined ? yes({ historyStore: sync.historyStore, blobExchange }) : no("blob_exchange_absent");
212
222
  }
213
223
  export function sessionRewindFiles(d) {
214
- if (d.fileHistoryStore === undefined)
224
+ const { config, backend } = d;
225
+ if (backend === undefined)
215
226
  return no("file_history_store_absent");
216
227
  const owned = sessionOwnership(d);
217
228
  if (!owned.available)
218
229
  return owned;
219
- if (d.resumeAnchorStore === undefined || d.runStore === undefined)
230
+ const runs = durableRuns(d);
231
+ if (!runs.available)
220
232
  return no("resume_anchor_store_absent");
221
- if (!laneWiresExecutionEnv(d.config.remoteExec.provider))
233
+ if (!laneWiresExecutionEnv(config.remoteExec.provider))
222
234
  return no("execution_lane_handless");
223
- if (!DEPLOYMENT_SHAPE_PREDICATES.rewindableWorkspace.holds(d.config))
235
+ if (!DEPLOYMENT_SHAPE_PREDICATES.rewindableWorkspace.holds(config))
224
236
  return no("workspace_rebuilt_per_task");
225
- if (d.backend?.kind !== "local")
237
+ if (backend.kind !== "local")
226
238
  return no("session_store_shared");
227
- return yes({ historyStore: d.fileHistoryStore, anchors: { anchors: d.resumeAnchorStore, runs: d.runStore }, sessionStorage: owned.sessionStorage });
239
+ return yes({ historyStore: assembleFileHistory(backend).store, anchors: { anchors: backend.resumeAnchor(), runs: runs.runStore }, sessionStorage: owned.sessionStorage });
228
240
  }
229
241
  export function sessionRewindFilesPreview(d) {
230
242
  const rewind = sessionRewindFiles(d);
@@ -245,14 +257,17 @@ export function toolApproval(d) {
245
257
  return d.toolApproval !== undefined ? yes({ coordinator: d.toolApproval }) : no("tool_approval_disabled");
246
258
  }
247
259
  export function streamApproval(d) {
260
+ if (d.toolApproval === undefined)
261
+ return no("tool_approval_disabled");
262
+ const coordinator = d.toolApproval;
248
263
  const gate = resolveStreamApprovalGate({
249
- toolApprovalEnabled: d.toolApproval !== undefined,
264
+ toolApprovalEnabled: true,
250
265
  streamApprovalEnabled: d.config.streamApproval?.enabled === true,
251
266
  backend: d.backend,
252
267
  checkpointStore: d.checkpointStore,
253
268
  });
254
269
  if (gate.active)
255
- return yes({ askStore: gate.askStore });
270
+ return yes({ askStore: gate.askStore, coordinator });
256
271
  switch (gate.reason) {
257
272
  case "no_tool_approval":
258
273
  return no("tool_approval_disabled");
@@ -294,14 +309,15 @@ export function deviceManagement(d) {
294
309
  const lane = deviceLane(d);
295
310
  if (!lane.available)
296
311
  return lane;
297
- if (d.deviceStore === undefined)
312
+ const { deviceStore: store, deviceEnrollment: enrollment } = d;
313
+ if (store === undefined)
298
314
  return no("device_store_absent");
299
- if (d.deviceEnrollment === undefined)
315
+ if (enrollment === undefined)
300
316
  return no("device_enrollment_absent");
301
317
  const runs = durableRuns(d);
302
318
  if (!runs.available)
303
319
  return runs;
304
- return yes({ hub: lane.hub, store: d.deviceStore, enrollment: d.deviceEnrollment, runStore: runs.runStore });
320
+ return yes({ hub: lane.hub, store, enrollment, runStore: runs.runStore });
305
321
  }
306
322
  export function fleetStream(d) {
307
323
  return d.fleetBus !== undefined ? yes({ fleetBus: d.fleetBus }) : no("fleet_bus_absent");
@@ -341,7 +357,8 @@ export function memorySyncServe(d) {
341
357
  return identity !== undefined ? yes({ perform: d.memorySync, identity }) : no("memory_sync_identity_undeclared");
342
358
  }
343
359
  export function sessionMemorySync(d) {
344
- if (d.memorySyncLeg === undefined)
360
+ const leg = d.memorySyncLeg;
361
+ if (leg === undefined)
345
362
  return no("memory_sync_leg_absent");
346
363
  const runs = durableRuns(d);
347
364
  if (!runs.available)
@@ -349,7 +366,7 @@ export function sessionMemorySync(d) {
349
366
  const owned = sessionOwnership(d);
350
367
  if (!owned.available)
351
368
  return owned;
352
- return yes({ leg: d.memorySyncLeg, runStore: runs.runStore, sessionStorage: owned.sessionStorage });
369
+ return yes({ leg, runStore: runs.runStore, sessionStorage: owned.sessionStorage });
353
370
  }
354
371
  export function principalInboxDelivery(d) {
355
372
  return d.orgDeliveryGate !== undefined ? yes({ gate: d.orgDeliveryGate }) : no("org_delivery_gate_absent");
@@ -1,9 +1,9 @@
1
- import { type WebAdminCredentialDeclaration } from "@sema-agent/settings-schema";
1
+ import { type WebAdminCredential, type WebAdminCredentialDeclaration } from "@sema-agent/settings-schema";
2
2
  /** 凭证种类闭集。新增一个种类 = 本文件与 `web-admin-client/center-request.ts` 的穷举 switch 当场编译红。 */
3
3
  export type CenterCredentialKind = "pull-token" | "user-jwt" | "user-session" | "none";
4
4
  /** 一次取值失败的成因闭集(见模块头注「四个成因」;boot 判决 {@link judgeCenterCredentialAtBoot} 对它穷举)。 */
5
5
  export type CenterCredentialFailure = "missing" | "malformed" | "multi_tenant_session" | "expired";
6
- /** 声明形的**非秘密**投影(进日志 / 拒因 / 未来的 caps 读面):env 形不带值。 */
6
+ /** 声明形的**非秘密**投影(进日志 / 拒因 / 自报位):env 形不带值。唯一铸点 {@link credentialOriginOf}。 */
7
7
  export type CenterCredentialOrigin = {
8
8
  readonly from: "env";
9
9
  } | {
@@ -12,6 +12,10 @@ export type CenterCredentialOrigin = {
12
12
  } | {
13
13
  readonly from: "absent";
14
14
  };
15
+ /** 声明**在**的那两形(配置里 `webAdmin.assertionToken` 的型:没声明 ⇒ 那一格缺席,缺席只有一种读法)。 */
16
+ export type DeclaredCredentialOrigin = Exclude<CenterCredentialOrigin, {
17
+ readonly from: "absent";
18
+ }>;
15
19
  /**
16
20
  * 一次取值的结果。`ok:false` 只有文件形会出现(env / absent 形的取值恒成功)。
17
21
  * `identity` 是「此刻的凭证是谁」—— 成功恒在;失败时只有 `expired` 知道(信封还读得出 `sub`,只是令牌不许再出站),
@@ -92,11 +96,26 @@ export type CenterCredentialSourceSpec = Exclude<WebAdminCredentialDeclaration,
92
96
  readonly multiTenant: boolean;
93
97
  };
94
98
  /**
95
- * 读两个声明键 —— 判定全交 settings-schema 的判官 `judgeWebAdminCredentialDeclaration`([ref]:二选一规则的**唯一**实现;空串 = 未设、
96
- * 不 trim;两个都设 ⇒ throw,boot 拒启,拒句点名两个键、不回显值)。本仓只多读方自己的那一步:文件路径按本进程 cwd 解析成绝对
97
- * 路径(之后 cwd 变了也读同一个文件 —— 纯契约不碰 `node:path`,这一步归读方)。
99
+ * 读一份 web-admin 凭证(`credential` ∈ 契约闭集 `WEB_ADMIN_CREDENTIALS`)的那一对声明键 —— 两份凭证的**唯一**读口。判定全交 settings-schema 的判官
100
+ * `judgeWebAdminCredentialDeclaration`([ref]:二选一规则的**唯一**实现;空串 = 未设、不 trim;两个都设 ⇒ throw,boot 拒启,拒句点名那一对键、不回显值;
101
+ * 判哪一份由调用方说,判官没有缺省)。本仓只多读方自己的那一步:文件路径按本进程 cwd 解析成绝对路径(之后 cwd 变了也读同一个文件 —— 纯契约不碰
102
+ * `node:path`,这一步归读方)。
103
+ */
104
+ export declare function readWebAdminCredentialDeclaration(credential: WebAdminCredential, env?: Readonly<Record<string, string | undefined>>): WebAdminCredentialDeclaration;
105
+ /** 声明 → 非秘密投影的**唯一**铸点(env 形丢掉值)。凭证来源的 `origin` 与断言令牌的配置读数都经它。 */
106
+ export declare function credentialOriginOf(declared: Readonly<{
107
+ from: "env";
108
+ } | {
109
+ from: "file";
110
+ path: string;
111
+ } | {
112
+ from: "absent";
113
+ }>): CenterCredentialOrigin;
114
+ /**
115
+ * [ref] —— 起服日志 `center_assertion_token` 的字段(`build*`:纯数据;`boot/web-admin.ts` 接了中心时打一次,info 级)。声明在 ⇒ 来源形(文件形另带
116
+ * 绝对路径;值形不带值);没声明 ⇒ 只有 `declared:false`。`effect` 如实说这一份凭证此刻的用途:只被读出声明,没有任何请求出示它。
98
117
  */
99
- export declare function readCenterCredentialDeclaration(env?: Readonly<Record<string, string | undefined>>): WebAdminCredentialDeclaration;
118
+ export declare function buildAssertionTokenBootFields(declared: DeclaredCredentialOrigin | undefined): Readonly<Record<string, string | boolean>>;
100
119
  /**
101
120
  * 凭证来源工厂(活对象:文件形每次取值读盘并记健康态)。`worker` = `SEMA_WEB_ADMIN_WORKER`(拉取令牌形的身份)。
102
121
  * `readFile` / `now` 只为测试注入。
@@ -12,10 +12,30 @@ export class CenterCredentialUnavailableError extends Error {
12
12
  this.name = "CenterCredentialUnavailableError";
13
13
  }
14
14
  }
15
- export function readCenterCredentialDeclaration(env = process.env) {
16
- const declared = judgeWebAdminCredentialDeclaration(env, "access");
15
+ export function readWebAdminCredentialDeclaration(credential, env = process.env) {
16
+ const declared = judgeWebAdminCredentialDeclaration(env, credential);
17
17
  return declared.from === "file" ? { from: "file", path: resolvePath(declared.path) } : declared;
18
18
  }
19
+ export function credentialOriginOf(declared) {
20
+ switch (declared.from) {
21
+ case "env":
22
+ return { from: "env" };
23
+ case "file":
24
+ return { from: "file", path: declared.path };
25
+ case "absent":
26
+ return { from: "absent" };
27
+ }
28
+ }
29
+ export function buildAssertionTokenBootFields(declared) {
30
+ if (declared === undefined)
31
+ return { declared: false };
32
+ return {
33
+ declared: true,
34
+ from: declared.from,
35
+ ...(declared.from === "file" ? { path: declared.path } : {}),
36
+ effect: "the declaration is read and reported only (GET /health center.assertionToken); no request from this engine presents the assertion token to the center",
37
+ };
38
+ }
19
39
  const digest16 = (s) => createHash("sha256").update(s, "utf8").digest("hex").slice(0, 16);
20
40
  function jwtSubject(bearer) {
21
41
  let parsed;
@@ -90,10 +110,10 @@ export function createCenterCredentialSource(spec, worker, deps = {}) {
90
110
  };
91
111
  switch (spec.from) {
92
112
  case "absent":
93
- return { origin: spec, declared: false, read: () => observed(NONE), health: () => ({ state: "ok" }), onRead };
113
+ return { origin: credentialOriginOf(spec), declared: false, read: () => observed(NONE), health: () => ({ state: "ok" }), onRead };
94
114
  case "env": {
95
115
  const fixed = classify(spec.token, worker);
96
- return { origin: { from: "env" }, declared: true, read: () => observed(fixed), health: () => ({ state: "ok" }), onRead };
116
+ return { origin: credentialOriginOf(spec), declared: true, read: () => observed(fixed), health: () => ({ state: "ok" }), onRead };
97
117
  }
98
118
  case "file": {
99
119
  const readFile = deps.readFile ?? ((p) => readFileSync(p, "utf8"));
@@ -111,7 +131,7 @@ export function createCenterCredentialSource(spec, worker, deps = {}) {
111
131
  return readCredentialText(text, spec, worker, now());
112
132
  };
113
133
  return {
114
- origin: { from: "file", path: spec.path },
134
+ origin: credentialOriginOf(spec),
115
135
  declared: true,
116
136
  read() {
117
137
  const r = readOnce();
@@ -2,6 +2,7 @@ import { type RetiredEnvWire } from "@sema-agent/settings-schema";
2
2
  import type { ServiceConfig, ServiceConfigGroups } from "./config-types.js";
3
3
  import type { ConfigKnobRecord } from "./config.js";
4
4
  import type { RestartSlice } from "./web-admin-client/restart-signal.js";
5
+ import { type EnvNameAllowlistKnob } from "./env-name-allowlist-knobs.js";
5
6
  export declare const CATALOG_VALUE_TYPES: readonly ["boolean", "number", "string", "enum", "csv", "json", "path", "url", "secret", "opaque"];
6
7
  export type CatalogValueType = (typeof CATALOG_VALUE_TYPES)[number];
7
8
  export declare const CATALOG_TIMINGS: readonly ["hot", "restart", "deploy", "inert"];
@@ -19,15 +20,33 @@ export type CatalogDangerAxis = (typeof CATALOG_DANGER_AXES)[number];
19
20
  export declare const URL_CREDENTIAL_POLICIES: readonly ["refuse", "mask"];
20
21
  export type UrlCredentialPolicy = (typeof URL_CREDENTIAL_POLICIES)[number];
21
22
  /**
22
- * secret 行的值**装着几枚凭据、按什么读出来**(闭集;只在 `type: "secret"` 的行上,其余行恒缺席)—— 本服务凭据的颗粒按本服务读这只变量的那一只解析器定:
23
- * · `whole` —— 整值是一枚(令牌 / 口令 / 私钥 / 一只模型密钥;名单型旋钮的原文也按凭据类整值对待);
23
+ * secret 行的值**装着几枚本服务凭据、按什么读出来**(闭集;只在 `type: "secret"` 的行上,其余行恒缺席)—— 本服务凭据的颗粒按本服务读这只变量的那一只解析器定:
24
+ * · `whole` —— 整值是一枚(令牌 / 口令 / 私钥 / 一只模型密钥);
24
25
  * · `token-table` —— `tok=system` 逗号表,每个 `tok` 是一枚(`SERVICE_AUTH_TOKENS`;读法 = `auth-keys.ts` `parseServiceAuthTokens`,`loadConfig` 同读);
25
- * · `key-set` —— `{kid,key,status}` JSON 数组,每个 `key` 是一枚(`APPROVAL_HMAC_KEYS`;读法 = `auth-keys.ts` `parseApprovalHmacKeys`,`loadConfig` 同读)。
26
- * 读者只有一个:自有凭据声明的值臂(`server-secret-env.ts`)—— 整值总在内,列表形另把每一枚交给引擎 ⇒ 一枚令牌换了个变量名放着,与原变量同扣。
27
- * 词加一个而读者不补 ⇒ 编译红(读者是穷举 switch);secret 行不写 ⇒ 编译红(`r()` 的 secret 重载要它)。不上 wire。
26
+ * · `key-set` —— `{kid,key,status}` JSON 数组,每个 `key` 是一枚(`APPROVAL_HMAC_KEYS`;读法 = `auth-keys.ts` `parseApprovalHmacKeys`,`loadConfig` 同读);
27
+ * · `name-list` —— 零枚:原文是一张环境变量名单(名单型旋钮;读法 = `config.ts` `parseEnvNameAllowlist`)。名单不是凭据,原文不交引擎比值;
28
+ * 旋钮变量本身照按名扣(它的原文可能夹着被错展开进来的令牌,所以是 secret 行:目录只回在场位、名进自有凭据声明、不进任何子进程)。
29
+ * 读者只有一个:自有凭据声明的值臂(`server-secret-env.ts`)—— 交给引擎的恰是颗粒读出来的那几枚(列表形另把每一枚交出去 ⇒ 一枚令牌换了个变量名放着,与原变量同扣)。
30
+ * 词加一个而读者不补 ⇒ 编译红(读者是穷举 switch);secret 行不写 ⇒ 编译红(`r()` 的 secret 重载要它);哪只行取 `name-list` 由行名定类({@link SecretRowForm}),写反 ⇒ 编译红。不上 wire。
28
31
  */
29
- export declare const SECRET_CREDENTIAL_FORMS: readonly ["whole", "token-table", "key-set"];
32
+ export declare const SECRET_CREDENTIAL_FORMS: readonly ["whole", "token-table", "key-set", "name-list"];
30
33
  export type SecretCredentialForm = (typeof SECRET_CREDENTIAL_FORMS)[number];
34
+ /** 装着本服务凭据值的颗粒(`name-list` 以外的词):名单型旋钮以外的每条 secret 行、bake-runner 的凭据行都取其一。 */
35
+ export type CredentialValueForm = Exclude<SecretCredentialForm, "name-list">;
36
+ /**
37
+ * secret 行的颗粒**按行名定类**:名单型旋钮(闭集 `EnvNameAllowlistKnob`,叶表 `env-name-allowlist-knobs.ts` —— 「哪只变量是名单」只在那里写一次)恒 `name-list`,
38
+ * 其余恒是装着凭据值的颗粒。目录行写反(旋钮写 `whole`、凭据写 `name-list`)⇒ `r()` 的 secret 重载当场编译红 —— 列与旋钮闭集不会说两样。
39
+ */
40
+ export type SecretRowForm<N extends string> = N extends EnvNameAllowlistKnob ? "name-list" : CredentialValueForm;
41
+ /**
42
+ * 配置目录**之外**的本包凭据变量:bake-runner 进程(构建宿主守护进程)自己读的凭据 —— 目录只装服务进程读的 env(D1 对账门把 `bake-runner/` 整只排除),
43
+ * runner 的键不是目录行,却是本包的自有凭据。自有凭据声明(`server-secret-env.ts`)把目录 secret 行与本表并成**一张**「名 → 颗粒」,三个进程入口
44
+ * (stage-01 / run-local / bake-runner)同读这一份(不按「归谁消费」切):名全声明,值按颗粒逐枚交引擎 ⇒ 名单型旋钮点到它(名是或值是)拒启、任何宿主腿都不交它与它的副本。
45
+ * 读点 `bake-runner/main.ts` `loadEnv` 按本表的键读(键改名而读点不跟 ⇒ 编译红)。不上 wire,不进 `GET /v1/config/catalog`。
46
+ */
47
+ export declare const BAKE_RUNNER_CREDENTIAL_ENV: {
48
+ readonly BAKE_RUNNER_TOKEN: "whole";
49
+ };
31
50
  /** 域 = 配置九组(类型锁步:组集变了这里跟着红)。 */
32
51
  export type CatalogDomain = keyof ServiceConfigGroups;
33
52
  export declare const CATALOG_RESTART_SLICES: readonly RestartSlice[];
@@ -103,7 +122,7 @@ export interface ConfigCatalogSpec {
103
122
  readonly scope?: "bootstrap-only";
104
123
  /** url 行的凭据处置披露({@link UrlCredentialPolicy});url 行必填(`r()` 的 url 重载要它,缺 ⇒ 编译红),其余行写不进来。 */
105
124
  readonly credentialPolicy?: UrlCredentialPolicy;
106
- /** secret 行的凭据颗粒({@link SecretCredentialForm});secret 行必填(`r()` 的 secret 重载要它,缺 ⇒ 编译红),其余行写不进来。 */
125
+ /** secret 行的凭据颗粒({@link SecretCredentialForm});secret 行必填(`r()` 的 secret 重载要它,缺 ⇒ 编译红;取哪一类按行名定 —— {@link SecretRowForm}),其余行写不进来。 */
107
126
  readonly credentialForm?: SecretCredentialForm;
108
127
  }
109
128
  export interface ConfigCatalogRowCenter {
@@ -28,7 +28,8 @@ export const CATALOG_VALUE_TYPES = ["boolean", "number", "string", "enum", "csv"
28
28
  export const CATALOG_TIMINGS = ["hot", "restart", "deploy", "inert"];
29
29
  export const CATALOG_DANGER_AXES = ["security", "billing", "data"];
30
30
  export const URL_CREDENTIAL_POLICIES = ["refuse", "mask"];
31
- export const SECRET_CREDENTIAL_FORMS = ["whole", "token-table", "key-set"];
31
+ export const SECRET_CREDENTIAL_FORMS = ["whole", "token-table", "key-set", "name-list"];
32
+ export const BAKE_RUNNER_CREDENTIAL_ENV = { BAKE_RUNNER_TOKEN: "whole" };
32
33
  const RESTART_SLICE_SET = {
33
34
  skills: true,
34
35
  mcp: true,
@@ -70,7 +71,7 @@ export const CONFIG_CATALOG = [
70
71
  r("ADOPTION_IMPORT_MAX_SESSIONS", "limitsHttp", "number", `收编批量导入 POST /v1/adoption/:id/sessions 每请求最多几个会话信封(超了整请求 400 request.field_invalid,句子点名本旋钮;地板 ${ADOPTION_IMPORT_MAX_SESSIONS_FLOOR},越界夹取 + 点名,小数拒启);当前值经能力位 adoptionImport.maxSessions 交给已收编的源主体`, { staticDefault: String(ADOPTION_IMPORT_MAX_SESSIONS_DEFAULT), configKey: "adoptionImportMaxSessions" }),
71
72
  r("ADOPTION_IMPORT_MAX_SESSION_BYTES", "limitsHttp", "number", `收编批量导入每个会话信封最多多少字节(信封 JSON 的 UTF-8 字节;超了只拒那一个元素 rejected/too_large,带 count 与 cap;合法域 [${ADOPTION_IMPORT_MAX_SESSION_BYTES_FLOOR}, ${ADOPTION_IMPORT_MAX_SESSION_BYTES_CEILING}] —— 上帽 = JSON 体上限减空批包络,再大的值够不着,越界夹取 + 点名,小数拒启);当前值经能力位 adoptionImport.maxSessionBytes 交给已收编的源主体`, { staticDefault: String(ADOPTION_IMPORT_MAX_SESSION_BYTES_DEFAULT), configKey: "adoptionImportMaxSessionBytes" }),
72
73
  r("AGENT_DATA_DIR", "store", "path", "本机数据根回落链一环(LOCAL_DATA_ROOT → CONFIG_LOCAL_DIR → AGENT_DATA_DIR → ~/.ai-agent);记忆引擎缺省根同链", { danger: DATA, derivedDefaultNote: "缺席 ⇒ 链上下一环,最终 ~/.ai-agent" }),
73
- r("ALLOW_UNAUTHED_WRITES", "auth", "boolean", "无 service token 时仍接受任务提交(本地开发逃生口;缺省 fail-closed 拒提交)", { staticDefault: "false", danger: SEC, configKey: "allowUnauthedWrites" }),
74
+ r("ALLOW_UNAUTHED_WRITES", "auth", "boolean", "写门对没带过门凭据(service token / 鉴权桥验过的登录令牌)的请求也放行:任务提交、改写门与破坏性会话写都照收(本地开发逃生口;缺省 fail-closed 拒)", { staticDefault: "false", danger: SEC, configKey: "allowUnauthedWrites" }),
74
75
  r("ANTHROPIC_API_KEY", "modelPlane", "secret", "Anthropic 协议路线的 x-api-key 凭据(只发 x-api-key 头;与 ANTHROPIC_AUTH_TOKEN 互斥 —— 同设拒启,机读码 `config.anthropic_credential_conflict`;与 BASE_URL 同在时可推断 provider)", { credentialForm: "whole", danger: [...SEC, ...BILL] }),
75
76
  r("ANTHROPIC_AUTH_TOKEN", "modelPlane", "secret", "Anthropic 兼容生态的 Bearer 凭据(只发 Authorization: Bearer 头;与 ANTHROPIC_API_KEY 互斥 —— 同设拒启,机读码 `config.anthropic_credential_conflict`)", { credentialForm: "whole", danger: [...SEC, ...BILL] }),
76
77
  r("ANTHROPIC_BASE_URL", "modelPlane", "url", "Anthropic 协议路线 base URL(与凭据同在且 MODEL_PROVIDER 未设 ⇒ 推断 provider=anthropic 并 boot notice;带 userinfo 拒启,机读码 `config.gateway_url_userinfo`;解析不动/不透明形拒启,机读码 `config.model_route_url_invalid`;带 `#fragment` 拒启,机读码 `config.model_route_url_fragment` —— fragment 从不上线,后缀会落进被丢弃的那一半)", { credentialPolicy: "refuse" }),
@@ -94,7 +95,7 @@ export const CONFIG_CATALOG = [
94
95
  r("AUTH_BRIDGE_AUDIENCE", "auth", "string", "registry SSO-JWT 验签期望 aud", { danger: SEC }),
95
96
  r("AUTH_BRIDGE_ISSUER", "auth", "url", "registry SSO-JWT issuer(auth bridge 的开关之一;**不是**托管证据 —— 多租户只认 REQUIRE_PRINCIPAL=true)", { credentialPolicy: "mask", danger: SEC, derivedDefaultNote: "缺席 ⇒ 桥的装配处回退到 webAdmin.baseUrl(配了 center 即默认开桥);显式值与回退值在托管判定上同判(都不算)", configKey: "authBridgeIssuer" }),
96
97
  r("AUTH_BRIDGE_JWKS_URL", "auth", "url", "registry SSO-JWT 的 JWKS 地址(缺省从 issuer 派生)", { credentialPolicy: "mask", danger: SEC }),
97
- r("AUTONOMY", "auth", "enum", "运维 autonomy 模式(read-only ⇒ 只读手 + 写面 roots,每段续跑重折,子代同受、委派照挂;ask ⇒ 恒 shellGate,每段重折;plan ⇒ 提交入口的模式词地板:新提交的任务以 permissionMode:plan 起步,请求词钳到它之下,写与非只读调用在调用时问 / 拒,批准计划之后整条 run 按批准的档跑完);center 腿热且 non-sticky(plan 地板只作用于之后提交的任务)", { danger: SEC, enumValues: AUTONOMY_MODES, configKey: "autonomy", center: cGov("autonomy") }),
98
+ r("AUTONOMY", "auth", "enum", "运维 autonomy 模式(read-only ⇒ 只读手 + 写面 roots,每段续跑重折,子代同受、委派照挂;ask ⇒ 恒 shellGate,每段重折;plan ⇒ 提交入口的模式词地板:新提交的任务以 permissionMode:plan 起步,请求词钳到它之下,写与非只读调用在调用时问 / 拒,批准计划之后整条 run 按批准的档跑完);center 腿热且 non-sticky(plan 地板作用于之后的提交,也作用于停驻 run 的下一次续跑:续跑之前体上的词过此刻的地板,批准计划写下的档原样)", { danger: SEC, enumValues: AUTONOMY_MODES, configKey: "autonomy", center: cGov("autonomy") }),
98
99
  r("AUTO_BACKGROUND_ON_TIMEOUT", "orchestration", "boolean", "前台 Bash 命令撞上它自己的超时时:开 ⇒ 合格的命令(资格由引擎判)转成后台任务继续跑(后台进程上限与后台超时硬上限照常管它);同一个开关也让引擎在有人的输入排队等着而合格命令还在跑时把它转后台、好让输入送达;关 ⇒ 两件都不做,超时即杀。只在能把运行中的命令领养成后台的车道上生效,其余车道照起、旋钮不生效 —— 本车道上生不生效看 GET /health 的 autoBackgroundOnTimeout(armed / off / unsupported)", { staticDefault: "true", configKey: "autoBackgroundOnTimeout" }),
99
100
  r("AUTO_MODE_CLASSIFIER_FALLBACK", "approval", "enum", "auto 分类器席答不出裁决时的梯子(main=主模型代判 / none=只留分类器那一级,整条拒)", { enumValues: ["main", "none"], danger: SEC, derivedDefaultNote: "未设/空串 ⇒ 不铸键,跟随引擎缺省 main(core 7.18.0 起;空串按未设,与其余词表旋钮同判);none = 7.77.0 及以前的行为逐字;词表外的值启动期拒启。权限轴放宽,升级须知见 DEPLOY-PREREQS", configKey: "autoModeClassifierFallback" }),
100
101
  r("AUTO_MODE_CLASSIFIER_TIMEOUT_MS", "approval", "number", `auto 分类器单级判决上限(ms;缺席 = core 缺省;自托管慢网关按排队 + prefill 留足;一级到点没裁 ⇒ 走下一级,走完仍没裁 ⇒ 这次门控调用整条拒;须为 [${AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS.minMs}, ${AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS.maxMs}] 内十进制整数,0 / 小数 / 越界拒启)`, { derivedDefaultNote: "未设/空串 ⇒ 不铸键,跟随 core 缺省(本仓不复制上游数字;core 改缺省本旋钮照映不改)", configKey: "autoModeClassifierTimeoutMs" }),
@@ -106,7 +107,7 @@ export const CONFIG_CATALOG = [
106
107
  r("BAKE_SUBMIT_RATE_MAX", "orchestration", "number", "per-principal bake 提交限流窗内最大次数(0=关)", { staticDefault: "10" }),
107
108
  r("BAKE_SUBMIT_RATE_WINDOW_SEC", "orchestration", "number", "per-principal bake 提交限流窗长(秒)", { staticDefault: "60" }),
108
109
  r("BG_AGENT_PARK_CLAIM_STALE_MS", "orchestration", "number", "parked 后台 agent 的 stale-claim 清算窗(ms;claimer 崩死的行由此解卡)", { staticDefault: String(60 * 60_000), configKey: "backgroundAgentParkClaimStaleMs" }),
109
- r("BG_AGENT_RETENTION_MS", "orchestration", "number", "TERMINAL 后台 agent 行保留期(ms,reaper 按 scope 清)", { staticDefault: String(7 * 24 * 60 * 60 * 1000), danger: DATA, configKey: "backgroundAgentRetentionMs" }),
110
+ r("BG_AGENT_RETENTION_MS", "orchestration", "number", "保留期(ms)的两个读者:TERMINAL 后台 agent 行(终局起,reaper 按 scope 清)与 sidechain 会话(最后活动起,维护拍的会话老化腿删)", { staticDefault: String(7 * 24 * 60 * 60 * 1000), danger: DATA, configKey: "backgroundAgentRetentionMs" }),
110
111
  r("BG_AGENT_STALE_RUNNING_MS", "orchestration", "number", "running 后台 agent 行写者心跳断更超此值翻 failed(ms;下限 10min 硬钳)", { staticDefault: String(15 * 60_000), configKey: "backgroundAgentStaleRunningMs" }),
111
112
  r("BG_AGENT_STALL_MS", "orchestration", "number", "会话驻留后台子代理的停滞收割窗(ms;最后一次工具活动距今超此值 ⇒ 行收成 killed、归因 system、run 中止;缺省 = 下限,只许拉大,无关闭档)", { derivedDefaultNote: "缺席 ⇒ max(600000, max(STREAM_ASK_WINDOW_MS, UNREACHED_ASK_TTL_MS, QUESTION_TTL_MS, MCP_ELICITATION_TTL_MS) + 引擎单命令上限(缺省 600000));单用户 posture 下 86400000 + 600000", configKey: "backgroundAgentStallMs" }),
112
113
  r("BIND_HOST", "auth", "string", "监听绑址(显式值恒生效)", { danger: SEC, derivedDefaultNote: "缺席:无鉴权写面(allowUnauthedWrites ∧ 零凭证)自动收窄 127.0.0.1,其余全接口", resolve: (c) => c.bindHost ?? null }),
@@ -152,7 +153,7 @@ export const CONFIG_CATALOG = [
152
153
  r("DOCKER_NETWORK", "orchestration", "enum", "local-docker 容器网络模式", { enumValues: ["none", "bridge", "host"], staticDefault: "bridge", danger: SEC }),
153
154
  r("DOCKER_PATH", "orchestration", "path", "docker 二进制路径"),
154
155
  r("DOCKER_PIDS_LIMIT", "orchestration", "number", "local-docker fork-bomb 背栓(--pids-limit;非法值回 adapter 默认 512+warn)", { danger: SEC, derivedDefaultNote: "缺席 ⇒ adapter 默认 512" }),
155
- r("DOCKER_SANDBOX_ENV", "orchestration", "secret", "local-docker 车道每条 docker exec 以 -e 注入的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/日志;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "whole", danger: SEC }),
156
+ r("DOCKER_SANDBOX_ENV", "orchestration", "secret", "local-docker 车道每条 docker exec 以 -e 注入的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/日志;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "name-list", danger: SEC }),
156
157
  r("DRAIN_GRACE_MS", "limitsHttp", "number", "SIGTERM 优雅排空窗(ms;期间新计费提交 503+Retry-After)。出厂默认是**服务器部署**的取值;壳自 spawn 的引擎会被壳注入更短的窗 ⇒ 排壳形关机预算时按壳自己注入的值算(壳读不到本目录:它是 operator-only),排空开始后本次排空定死的到期点读 GET /health 的 engineSignal.draining.deadlineAt,从信号到进程退出的上界见 USAGE 的「停机上界(契约句)」;不照抄 staticDefault", { staticDefault: String(10 * 60 * 1000), configKey: "drainGraceMs", center: cLimits("drainGraceMs") }),
157
158
  r("DRAIN_SECOND_SIGNAL_MIN_GAP_MS", "limitsHttp", "number", `排空期「第二发信号 = 硬停」的最小间隔(ms;锚 = 本次排空的第一发停止信号 —— SIGTERM / SIGHUP 升级进的排空,入口那一发就是它;排空口 / 租约被拒 / 附着租约自退进的排空,到达的第一发被吸收、不缩短期限。SIGTERM / SIGINT 与锚相隔不足 ⇒ 同一拍的重复投递,一行 drain_duplicate_signal_ignored 后忽略、排空继续;0 = 关,恒按第二发硬停;须为 [${DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS.minMs}, ${DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS.maxMs}] 内十进制整数(上界 = DRAIN_GRACE_MS 地板),小数 / 负数 / 越界拒启)`, { staticDefault: String(DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS), configKey: "drainSecondSignalMinGapMs" }),
158
159
  r("DURABLE_APPROVAL", "approval", "boolean", "durable suspend/resume HITL(需 SQL 店;决定 checkpointStore 与 /v1/approvals 面的存在性)", { danger: SEC, derivedDefaultNote: "posture 三态:显式词恒赢,缺席 = 单用户(REQUIRE_PRINCIPAL≠true)且有耐久店 ⇒ on / 多租户或无耐久店 ⇒ off;生效来源见 GET /v1/diagnostics/wiring 的 serverGates.durableApproval.source", configKey: "durableApproval" }),
@@ -164,7 +165,7 @@ export const CONFIG_CATALOG = [
164
165
  r("E2B_LIVENESS_MS", "orchestration", "number", LIVENESS_KNOB_SEMANTICS("e2b"), { derivedDefaultNote: LIVENESS_KNOB_DEFAULT_NOTE }),
165
166
  r("E2B_MOUNT_PATH", "orchestration", "path", "e2b 工作区根(resume 用当前值,改前先 drain 挂起任务)"),
166
167
  r("E2B_ORPHAN_RECLAIM", "orchestration", "boolean", "崩溃遗留沙盒回收腿(boot 一次+周期;判据保守,拿不准恒不杀)", { staticDefault: "true", danger: BILL }),
167
- r("E2B_SANDBOX_ENV", "orchestration", "secret", "转发进 e2b 沙箱的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/事件日志;与 LSP_ENV_ALLOW / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "whole", danger: SEC }),
168
+ r("E2B_SANDBOX_ENV", "orchestration", "secret", "转发进 e2b 沙箱的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值不进 spec/center/事件日志;与 LSP_ENV_ALLOW / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { credentialForm: "name-list", danger: SEC }),
168
169
  r("E2B_SANDBOX_MAX_MS", "orchestration", "number", "e2b 沙箱最长存活(ms)", { staticDefault: "3600000", danger: BILL }),
169
170
  r("E2B_TEMPLATE", "orchestration", "string", "e2b 模板名(缺省 adapter 基础模板)"),
170
171
  r("E2B_TIMEOUT_MS", "orchestration", "number", "e2b 单命令总超时(ms)"),
@@ -177,10 +178,10 @@ export const CONFIG_CATALOG = [
177
178
  r("FILE_HISTORY_CAPTURE", "store", "boolean", "文件历史**捕获**总开关(三条车道同义)。关 = 不再捕获任何改动文件的首次快照(落 core 的部署捕获位 `RunnerDeps.fileHistoryCapture: \"off\"`,能力词 `fileHistoryCapture` 翻 off);7.104.0 起**只关捕获**:历史店照接,已存历史照常 restoreFiles / rewindFilesTo / 2c session-sync。关掉 ≠ 删掉:已捕获的历史不被批量删除,仍按会话删除与留存规则清理 —— 要清存量走 DELETE 会话或留存旋钮;没有「整库历史不可用」的旋钮", { staticDefault: "true", danger: DATA, configKey: "fileHistoryCapture" }),
178
179
  r("FILE_HISTORY_RETENTION_KEEP", "store", "number", "per-file rewind 历史的保留上限(与 core FileStorageBackend 同域键形,三条车道一套语义)", { danger: DATA, derivedDefaultNote: "缺席 ⇒ core 缺省 100" }),
179
180
  r("FLEET_ADVERTISE_ADDRESS", "integrations", "url", `fleet 面向 center 公告的本 worker 可达地址(中心车道配齐 + 本键 ⇒ 公告环;空串 = 未设;用量环不看本键)。中心往它后面拼路径,与中心基址三席同一条判据:${CENTER_BASE_URL_RULE}`, { credentialPolicy: "refuse", configKey: "fleetAdvertiseAddress" }),
180
- r("FLEET_GENERATION", "integrations", "string", "fleet 成员的代际(配置渲染器写;引擎回声到心跳与 /health 的 generation)。缺席 ⇔ 非 fleet 成员(不续服务租约、不受围栏);在场必须是规范十进制串(\"0\" / \"7\";空串、前导零、符号、空白拒启)", { danger: SEC, configKey: "fleetGeneration" }),
181
+ r("FLEET_GENERATION", "integrations", "string", "fleet 成员的代际(配置渲染器写;引擎回声到心跳与 /health 的 generation)。缺席 ⇔ 非 fleet 成员(不续服务租约、不受围栏、sso 准入不比对令牌 scope;成员上令牌 scope 必须等于 FLEET_SCOPE);在场必须是规范十进制串(\"0\" / \"7\";空串、前导零、符号、空白拒启)", { danger: SEC, configKey: "fleetGeneration" }),
181
182
  r("FLEET_LEASE_FAIL_CLOSED", "integrations", "boolean", "租约连接级失败(中心鉴权拒 / 凭证不可读 / 不可达 / 5xx / 超时 / 坏体)时计费入口拒 503 fleet.lease_unavailable(true)还是放行(false);409 not-lease 与耗尽 429 不受它管;词表外拒启", { danger: SEC, derivedDefaultNote: "缺席 ⇒ 按部署姿态派生:REQUIRE_PRINCIPAL=true ⇒ true(多租:额度是安全轴);单用户 ⇒ false(AP 姿态)。显式值压过派生。生效值见 caps centerWiring.failMode", configKey: "fleetLeaseFailClosed" }),
182
- r("FLEET_LEASE_OUTAGE_MAX_MS", "integrations", "number", "一台实例「活着而不服务」的最长时长 T_max(ms),两处读它:① 服务租约中心不可达的容忍上限 —— 租约过期满这么久 ⇒ 新计费提交 503 state.lease_expired(取消 / HITL 应答 / 续跑 / 读面照放行,在飞不动,/readyz 不翻),只在 fleet 成员 ∧ 中心宣告 servingLease 能力位时生效;② 排空口 POST /v1/admin/drain 的期限上界 —— deadlineAt 离此刻超过它 ⇒ 400 request.field_invalid,成员与非成员同读;< 60000(租约 TTL 地板)或非整数拒启", { danger: SEC, staticDefault: String(FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS), configKey: "fleetLeaseOutageMaxMs" }),
183
- r("FLEET_SCOPE", "integrations", "string", "本引擎所在的租户 scope(配置渲染器对每台受管引擎写,缺省 scope 也写;手接的引擎缺席 = 缺省 scope;唯一读者 = 排空口 POST /v1/admin/drain 的身份比对,请求不带 scope 也读成缺省 scope)。在场必须是 scope id 形(小写字母 / 数字 / 内部连字符,1–64;空串拒启);与 FLEET_GENERATION 不联动(成员缺席 ⇒ 缺省 scope)。续租体与心跳不带它(scope 由中心凭证绑定)", { danger: SEC, staticDefault: GLOBAL_SCOPE, configKey: "fleetScope" }),
183
+ r("FLEET_LEASE_OUTAGE_MAX_MS", "integrations", "number", "一台实例「活着而不服务」的最长时长 T_max(ms),两处读它:① 服务租约中心不可达的容忍上限 —— 租约过期(从没被授予过的:从围栏生效那一刻;一直没听到中心的成员从本进程起点)满这么久 ⇒ 新计费提交 503 state.lease_expired(取消 / HITL 应答 / 续跑 / 读面照放行,在飞不动,/readyz 不翻),只在 fleet 成员 ∧ 中心没有声明不执行租约(心跳答复的 capabilities 声明不带 servingLease)时生效;② 排空口 POST /v1/admin/drain 的期限上界 —— deadlineAt 离此刻超过它 ⇒ 400 request.field_invalid,成员与非成员同读;< 60000(租约 TTL 地板)或非整数拒启", { danger: SEC, staticDefault: String(FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS), configKey: "fleetLeaseOutageMaxMs" }),
184
+ r("FLEET_SCOPE", "integrations", "string", "本引擎所在的租户 scope(配置渲染器对每台受管引擎写,缺省 scope 也写;手接的引擎缺席 = 缺省 scope;两个读者读同一个值:排空口 POST /v1/admin/drain 的身份比对(请求不带 scope 也读成缺省 scope)与 fleet 成员(FLEET_GENERATION 在场)上的 sso 准入 —— 登记中心登录令牌的 scope ≠ 本值 ⇒ 整次请求 403 auth.scope_mismatch;非成员不比对)。在场必须是 scope id 形(小写字母 / 数字 / 内部连字符,1–64;空串拒启);与 FLEET_GENERATION 不联动(成员缺席 ⇒ 缺省 scope)。续租体与心跳不带它(scope 由中心凭证绑定)", { danger: SEC, staticDefault: GLOBAL_SCOPE, configKey: "fleetScope" }),
184
185
  r("FORK_ENABLED", "orchestration", "boolean", "CC /fork(core Fork 工具)装配开关", { derivedDefaultNote: "posture 三态:缺席 = 单用户 ⇒ on / 多租户 ⇒ off(per-principal entitlement 另判)", configKey: "forkEnabled" }),
185
186
  r("GATEWAY_MAX_RETRIES", "modelPlane", "number", "openai 兼容腿每次调用重试上限", {
186
187
  derivedDefaultNote: "缺席 ⇒ 按外层拓扑分两态(启动日志 `brain` 字段的 `gatewayRetryCap` 回显哪一态):配了备用网关(`MODEL_GATEWAY_FALLBACK_URLS`)/ 开了断路器开关(`MODEL_CIRCUIT_BREAKER`,单路网关上也算)/ 开了反应式降级(配着 `MODEL_DEGRADE_TO` 且 `MODEL_DEGRADE_REACTIVE` 开)" +
@@ -191,7 +192,7 @@ export const CONFIG_CATALOG = [
191
192
  r("GIT_API_KIND", "integrations", "enum", "Git host API 方言", { enumValues: ["gitea", "github"], staticDefault: "gitea", configKey: "gitApiKind" }),
192
193
  r("GIT_API_TOKEN", "integrations", "secret", "repo 工具的 Git host 凭据", { credentialForm: "whole", danger: SEC }),
193
194
  r("HOOKS_TIMEOUT_MS", "orchestration", "number", "请求 hooks 的每张车道注册(settings.hooks / settings.hooks.managed,各一份同值)每个 handler 的时间预算(ms;0=零预算是合法值)", { derivedDefaultNote: "缺席 ⇒ 不铸键,读法 settingsHooksBudgetMs 取 600000" }),
194
- r("HOOK_ENV_ALLOW", "orchestration", "secret", `settings hook 环境的点名放回名单(点到的键从服务进程环境原样放回 hook 环境、部署方显式承担:命令 hook 的子进程 env 与 http hook 头的 $NAME 插值读同一份;服务进程变量进 hook 环境只有这一个来源,请求的 allowedEnvVars / settings.httpHookAllowedEnvVars 只收窄、不授予;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本;列表形凭据逐枚比)—— (判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放回、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "whole", danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 不放回(hook 环境 = 十二名基础名单 + 请求 settings.env)" }),
195
+ r("HOOK_ENV_ALLOW", "orchestration", "secret", `settings hook 环境的点名放回名单(点到的键从服务进程环境原样放回 hook 环境、部署方显式承担:命令 hook 的子进程 env 与 http hook 头的 $NAME 插值读同一份;服务进程变量进 hook 环境只有这一个来源,请求的 allowedEnvVars / settings.httpHookAllowedEnvVars 只收窄、不授予;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本;列表形凭据逐枚比)—— (判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放回、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "name-list", danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 不放回(hook 环境 = 十二名基础名单 + 请求 settings.env)" }),
195
196
  r("HOST_BG_DEFAULT_TIMEOUT_SEC", "orchestration", "number", "host 后台 shell 缺省超时(秒)", { staticDefault: "300" }),
196
197
  r("HOST_BG_ENABLED", "orchestration", "boolean", "host 车道后台 shell 开关", { staticDefault: "true" }),
197
198
  r("HOST_BG_FILE_CAP", "orchestration", "number", "host 后台 shell 磁盘护栏(字节;失控输出被 reap)", { staticDefault: String(64 * 1024 * 1024) }),
@@ -227,7 +228,7 @@ export const CONFIG_CATALOG = [
227
228
  r("K8S_NAMESPACE", "orchestration", "string", "沙箱 pod 所在的 namespace(REMOTE_EXEC=k8s 必需件,与 K8S_SANDBOX_IMAGE 同级:缺席、空串或只有空白 ⇒ 起服拒,拒句点名本旋钮;服务不带内置缺省 —— 部署的声明是唯一来源,随包 chart 已显式设为 sandbox.namespace;只在 REMOTE_EXEC=k8s 被选中时求值)"),
228
229
  r("K8S_RUNTIME_CLASS", "orchestration", "string", "沙箱 pod runtimeClass(Kata 等)"),
229
230
  r("K8S_SANDBOX_BROKER_IMAGE", "orchestration", "string", "成员 git 凭据代理容器的镜像(k8s 沙箱 pod 的 containers[1],只挂在成员 run 的 pod 上;建议填本引擎自身镜像 —— 代理是本包里固定路径的一只程序,命令固定);不设 ⇒ 成员 git 凭据平面关(GET /v1/capabilities 的 credentialPlane.sandboxGit = broker_image_unset),任何 pod 都不挂代理,pod 形逐字节同不设时;只在 REMOTE_EXEC=k8s 被选中时求值"),
230
- r("K8S_SANDBOX_ENV", "orchestration", "secret", `转发进 k8s 沙箱 pod 容器 env 的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值只进该 pod 自己的 Secret —— pod spec 的容器 env 只带 secretKeyRef 引用、不带值,Secret 随 pod 由集群回收;不进工作区 / 快照 / center / 事件日志;沙箱命名空间的 Role 要 secrets ${SANDBOX_SECRET_SEAT_VERBS.env.join(" / ")},起服问不许即拒启;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;与包源派生 env 撞名时显式名单胜;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "whole", danger: SEC }),
231
+ r("K8S_SANDBOX_ENV", "orchestration", "secret", `转发进 k8s 沙箱 pod 容器 env 的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值只进该 pod 自己的 Secret —— pod spec 的容器 env 只带 secretKeyRef 引用、不带值,Secret 随 pod 由集群回收;不进工作区 / 快照 / center / 事件日志;沙箱命名空间的 Role 要 secrets ${SANDBOX_SECRET_SEAT_VERBS.env.join(" / ")},起服问不许即拒启;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮 / 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (会把本服务的凭据装进模型读得到的沙箱;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;与包源派生 env 撞名时显式名单胜;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)`, { credentialForm: "name-list", danger: SEC }),
231
232
  r("K8S_SANDBOX_IMAGE", "orchestration", "string", "k8s 车道沙箱镜像(REMOTE_EXEC=k8s 必需件)"),
232
233
  r("K8S_SANDBOX_IPV6", "orchestration", "enum", "k8s 沙箱 pod 的 IPv6:disabled = pod 级 sysctl 关 IPv6(net.ipv6.conf.all / default.disable_ipv6=1;两只都不在 k8s 的 safe sysctl 表里 ⇒ 每个节点 kubelet 要 --allowed-unsafe-sysctls 点名,否则 pod 起不来;沙箱 ns 不能 enforce PodSecurity baseline / restricted);enabled = 不动 pod(pod 保留平台给的 IPv6,只执行 IPv4 的出网策略管不到它,起服自检每次一行 sandbox_egress_policy_gap{kind: ipv6_enabled});词表外拒启", { enumValues: SANDBOX_IPV6_WORDS, staticDefault: SANDBOX_IPV6_DEFAULT, danger: SEC }),
233
234
  r("K8S_TIMEOUT_MS", "orchestration", "number", "k8s 沙箱 pod 寿命(activeDeadlineSeconds,ms;整只 pod 的泄漏护栏,后台任务超时也被它钳;各条命令的超时见工具超时)"),
@@ -253,7 +254,7 @@ export const CONFIG_CATALOG = [
253
254
  r("LOCAL_STORE_DURABILITY", "store", "enum", "运维声明 local 店易失(词闭集只有 ephemeral):local 后端交给会话店与检查点店两半的引擎声明都降为 process-local(委派分区不降:后台子代照旧能停驻) ⇒ 数据根落在易失介质(容器可写层 / tmpfs / emptyDir)上不再拒启 config.store_not_durable,起服 warn 一行;后果 = 店里的会话、停驻审批与记忆不随容器 / Pod 替换保留(进程重启照旧活过)。读面 store.durability 照旧按介质如实报。SQL / memory 后端不读。部署者自己设,壳 / 编排器不代写", { enumValues: LOCAL_STORE_DECLARATION_WORDS, danger: DATA, derivedDefaultNote: "缺席 ⇒ 店型的设计声明(活过进程重启);店落在调用方自己的盘上(host 车道单主)且数据根介质易失时,同样降为 process-local", configKey: "localStoreDurability" }),
254
255
  r("LOCKED_CONFIG_KEYS", "auth", "csv", "管理员锁定层声明(词表=core 闭集注册表,未知键拒启)", { danger: SEC, configKey: "lockedConfigKeys" }),
255
256
  r("LOG_LEVEL", "observability", "string", "日志档位", { staticDefault: "info", configKey: "logLevel" }),
256
- r("LSP_ENV_ALLOW", "orchestration", "secret", `host 腿语言服务器子进程 env 的点名放行名单(点到的键从服务 env 原样放回、部署方显式承担;没点到的照剥;与 host shell inheritEnv:[names] 同一只谓词;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (剥后放回会把引擎刚扣下的凭据交回去;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放行、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程,生效名单见起服披露行 allowed)`, { credentialForm: "whole", danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 全剥(7.100.0 行为)" }),
257
+ r("LSP_ENV_ALLOW", "orchestration", "secret", `host 腿语言服务器子进程 env 的点名放行名单(点到的键从服务 env 原样放回、部署方显式承担;没点到的照剥;与 host shell inheritEnv:[names] 同一只谓词;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据 —— 名是,或值是本服务的某一枚凭据(另一个名下的副本)—— (剥后放回会把引擎刚扣下的凭据交回去;判官 = 引擎此刻的自有凭据声明)拒启且不回显值;本进程环境里没有的名按序号 warn、不放行、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程,生效名单见起服披露行 allowed)`, { credentialForm: "name-list", danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 全剥(7.100.0 行为)" }),
257
258
  r("LSP_HOST_ENABLED", "orchestration", "boolean", "本机语言服务器开关(只在 host 车道且单主时挂;本机 language server,优雅降级)", { staticDefault: "true", configKey: "lspHostEnabled" }),
258
259
  r("MANUAL_MODE_SHELL_GATE", "approval", "enum", "手动模式 shell 门收紧腿(off=no-op 非放松 —— 本键只有收紧半场;拼错拒启;classify 档已退役 = 拒启指路)", { danger: SEC, enumValues: ["always", "off"], echoWords: ["always"], resolve: (c) => c.manualModeShellGate ?? null, derivedDefaultNote: "off/未设 ⇒ 本键不贡献任何东西(归一成键缺席)⇒ 回显 null;真姿态只有 always 一个(core 7.34.0 起形状档在每一种模式下都装,classify 不再是运维选的档)" }),
259
260
  r("MAX_PRINCIPAL_COST_USD", "limitsHttp", "number", "per-principal 窗内成本天花板(0=关)", { staticDefault: "0", danger: BILL, configKey: "maxPrincipalCostUsd", center: cLimits("maxPrincipalCostUsd") }),
@@ -462,6 +463,8 @@ export const CONFIG_CATALOG = [
462
463
  r("SEMA_UV_INDEX", "orchestration", "url", "SANDBOX_PKG_SOURCE=custom 的显式 uv index 地址", { credentialPolicy: "refuse" }),
463
464
  r("SEMA_UV_PY_MIRROR", "orchestration", "url", "SANDBOX_PKG_SOURCE=custom 的显式 uv python 分发镜像地址", { credentialPolicy: "refuse" }),
464
465
  r(WEB_ADMIN_ENV.adminToken, "integrations", "secret", "写 web-admin 的管理凭证(仅 boot 上报执行公钥用;刻意不入 ServiceConfig —— 不进 configHash/日志面)", { credentialForm: "whole", danger: SEC, scope: "bootstrap-only" }),
466
+ r(WEB_ADMIN_ENV.assertionToken, "integrations", "secret", `web-admin 断言令牌(值形;编排器注入;与 ${WEB_ADMIN_ENV.assertionTokenFile} 二选一,都设=拒启)。唯一读者 = 中心凭证的声明读口(与 ${WEB_ADMIN_ENV.token} 同一只判官;只在接了中心 ${WEB_ADMIN_ENV.url} 时读):本版只报声明在 / 不在(/health center.assertionToken、起服日志 center_assertion_token),值不进配置、不向中心出示;它是本服务自有凭据,宿主子进程环境里扣掉`, { credentialForm: "whole", danger: SEC }),
467
+ r(WEB_ADMIN_ENV.assertionTokenFile, "integrations", "path", `web-admin 断言令牌文件(给不经编排器的手接引擎;与 ${WEB_ADMIN_ENV.assertionToken} 二选一,都设=拒启)。唯一读者同 ${WEB_ADMIN_ENV.assertionToken}:本版只报声明在 / 不在,不读文件内容`, { danger: SEC }),
465
468
  r(WEB_ADMIN_ENV.dryRun, "integrations", "boolean", "web-admin 腿 dry-run(拉而不应用)", { staticDefault: "false", danger: SEC }),
466
469
  r(WEB_ADMIN_ENV.liveUrl, "integrations", "url", `fleet 活性组(心跳 / 注销、服务租约 = settings-schema FLEET_LIVE_PATHS)的 web-admin 基址:给管理面在就绪门后、活性面另走一条不看就绪的入口的部署。缺席 = ${WEB_ADMIN_ENV.url}。传输地址,不参与中心身份互证。${CENTER_BASE_URL_RULE}`, { credentialPolicy: "refuse", danger: SEC }),
467
470
  r(WEB_ADMIN_ENV.token, "integrations", "secret", `center 拉取凭据(值形;与 ${WEB_ADMIN_ENV.tokenFile} 二选一,都设=拒启)`, { credentialForm: "whole", danger: SEC }),
@@ -117,7 +117,8 @@ type AnonymousBoundaryView = Pick<CrossInvariantView, (typeof ANONYMOUS_BOUNDARY
117
117
  * 写面无鉴权(`ALLOW_UNAUTHED_WRITES` ∧ 没配 service 凭据 = {@link bindMustNarrow})时,能连上这个口的都能不带主体提交 run;监听地址只在本机回环 ⇒ 能连上的只有本机,成立;
118
118
  * 否则 ⇒ 网络上任何人都按那个人的规则跑 ⇒ 起服拒,拒句一行给两条出路:配凭据 / 只听本机回环。不加旋钮(两条出路都是既有键)。
119
119
  * 写面无鉴权且零凭据时,监听地址缺省就收窄到 127.0.0.1(继承的 `HOST` 也压不过)⇒ 本条只在运维显式 `BIND_HOST` 把它暴露出去时成立。
120
- * 写面要凭据而没配凭据的部署没有人能提交 run,不归本条;配了凭据的部署,调用方 = 凭据持有者(与 `operator-single-user-boundary` 同一道边界)。
120
+ * 写面要凭据的部署(没开逃生口)上能提交 run 的只有带着凭据门认的凭据的调用方(service 凭据持有者 / 鉴权桥验过的登录令牌 —— 后者恒带主体),不归本条;
121
+ * 配了 service 凭据的部署,调用方 = 凭据持有者(与 `operator-single-user-boundary` 同一道边界)。
121
122
  * 「谁受伤」= 单用户 ∧ 写面无鉴权 ∧ 显式非回环 `BIND_HOST` 的部署(含容器里 `BIND_HOST=0.0.0.0`、宿主只发布到回环的那一形 —— 进程看不见宿主怎么发布端口);补偿 = 两条出路之一。
122
123
  * **只在服务入口判**(起服第 1 段,紧跟 `operator-single-user-boundary`):律管开监听口的进程;`run-local` 不监听、同读 `loadConfig`,不在射程。
123
124
  */
@@ -6,11 +6,11 @@ import { modelRouteEndpointRefusal } from "./model-route-endpoint.js";
6
6
  import { defaultModelRefusal, refusedNameMintedRefusal } from "./model-entry-refusal.js";
7
7
  import { judgeEnvTableReplacement } from "./env-model-table-gate.js";
8
8
  import { WEB_ADMIN_ENV, httpUrlFlaws } from "@sema-agent/settings-schema";
9
- import { authBridgeIssuerOf } from "./identity-source.js";
9
+ import { authBridgeIssuerOf, hasServiceAuth } from "./identity-source.js";
10
10
  import { buildDisplaySafeUrl } from "./trace/redact.js";
11
11
  import { ALL_EXECUTION_LANES, executionLaneCaps } from "./execution-lane-caps.js";
12
12
  import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
13
- import { anyServiceCredential, bindMustNarrow, listensLoopbackOnly, resolveBindHost } from "./bind-host.js";
13
+ import { bindMustNarrow, listensLoopbackOnly, resolveBindHost } from "./bind-host.js";
14
14
  export const LIVENESS_HEARTBEAT_MS = 30_000;
15
15
  const directDoorConjuncts = (v) => Boolean(v.directApprovalDoor) && Boolean(v.durableApproval) && v.approvalHmacKeys.length > 0 && v.principalJwtPubkeys.length > 0 && Boolean(v.principalJwtIss) && Boolean(v.principalJwtAud);
16
16
  function multiTenantSharedLaneRefusal(v) {
@@ -65,10 +65,10 @@ export function operatorDeclarationRefusal(v) {
65
65
  }
66
66
  const SINGLE_USER_BOUNDARY_KEYS = ["operatorSingleUser", "authToken", "authTokens", "allowUnauthedWrites", "bindHost", "bindHostSource"];
67
67
  function sameSingleUserBoundary(a, b) {
68
- return a.operatorSingleUser === b.operatorSingleUser && anyServiceCredential(a) === anyServiceCredential(b) && resolveBindHost(a) === resolveBindHost(b);
68
+ return a.operatorSingleUser === b.operatorSingleUser && hasServiceAuth(a) === hasServiceAuth(b) && resolveBindHost(a) === resolveBindHost(b);
69
69
  }
70
70
  export function operatorSingleUserBoundaryRefusal(v) {
71
- if (v.operatorSingleUser !== true || anyServiceCredential(v))
71
+ if (v.operatorSingleUser !== true || hasServiceAuth(v))
72
72
  return undefined;
73
73
  const where = offHostListener(v);
74
74
  if (where === undefined)