@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,4 +1,6 @@
1
- import { type ConfigDirectoryMigration } from "@sema-agent/settings-schema/node";
1
+ import { type ConfigDirectoryDocument, type ConfigDirectoryMigration } from "@sema-agent/settings-schema/node";
2
+ /** 本地读腿读的那几份(便携域 + 退役域 + remote-exec 文档)= 迁移的覆盖面 = 目录信任判官(`config-dir-trust.ts`)判的文档名单。取契约的表与文档名,不手抄。 */
3
+ export declare const LOCAL_READER_DOCUMENTS: readonly ConfigDirectoryDocument[];
2
4
  /** 一次起服迁移的结果:契约的结果闭集,外加本仓入口的两形(目录不在 ⇒ 不调;调用抛 ⇒ 失败)。纯数据。 */
3
5
  export type ConfigDirMigration = {
4
6
  readonly kind: "no-config-dir";
@@ -3,7 +3,7 @@ import { join } from "node:path";
3
3
  import { RETIRED_DOMAINS, formatConfigPath, isRetiredDomainName } from "@sema-agent/settings-schema";
4
4
  import { PORTABLE_DOMAINS, migrateConfigDirectory, nodeConfigDirectoryIo } from "@sema-agent/settings-schema/node";
5
5
  import { REMOTE_EXEC_DOCUMENT } from "@sema-agent/settings-schema/remote-exec";
6
- const READ_BACK_DOCUMENTS = [...PORTABLE_DOMAINS, ...Object.keys(RETIRED_DOMAINS).filter(isRetiredDomainName), REMOTE_EXEC_DOCUMENT];
6
+ export const LOCAL_READER_DOCUMENTS = [...PORTABLE_DOMAINS, ...Object.keys(RETIRED_DOMAINS).filter(isRetiredDomainName), REMOTE_EXEC_DOCUMENT];
7
7
  const errnoOf = (err) => (err instanceof Error && "code" in err && typeof err.code === "string" ? err.code : undefined);
8
8
  export async function migrateLocalConfigDirectory(root) {
9
9
  const dir = join(root, "config.d");
@@ -16,7 +16,7 @@ export async function migrateLocalConfigDirectory(root) {
16
16
  return { kind: "no-config-dir", dir };
17
17
  }
18
18
  try {
19
- return { ...(await migrateConfigDirectory(dir, { documents: READ_BACK_DOCUMENTS, io: nodeConfigDirectoryIo })), dir };
19
+ return { ...(await migrateConfigDirectory(dir, { documents: LOCAL_READER_DOCUMENTS, io: nodeConfigDirectoryIo })), dir };
20
20
  }
21
21
  catch (err) {
22
22
  return { kind: "threw", dir, reason: `${err instanceof Error ? err.message : String(err)}${errnoOf(err) !== undefined ? ` (${errnoOf(err)})` : ""}` };
@@ -0,0 +1,114 @@
1
+ /** 拒的机器码:起服拒启的 fatal 标题(`[config.dir_untrusted]`)与每拍那一行的句首同用。 */
2
+ export declare const CONFIG_DIR_UNTRUSTED_CODE = "config.dir_untrusted";
3
+ /** 属主声明的 env 名(登记 `config-catalog.ts`)。 */
4
+ export declare const CONFIG_LOCAL_OWNER_UID_ENV = "CONFIG_LOCAL_OWNER_UID";
5
+ /** 一份配置文档的字节上界(只在这里定)。挡的是误放的巨型文件 / 误链到日志;技能正文内联在 `skills.json` 里,所以给得宽。 */
6
+ export declare const CONFIG_DOCUMENT_MAX_BYTES: number;
7
+ /** 走一条路径最多跟几跳符号链接(与 Linux `MAXSYMLINKS` 同数)。 */
8
+ export declare const CONFIG_DIR_LINK_HOPS_MAX = 40;
9
+ /** 一条「别人改得动」的发现(闭集;句子见 {@link buildConfigDirUntrustedSentence})。`path` 是物理路径(链接已跟)。 */
10
+ export type ConfigDirUntrustedFinding = {
11
+ readonly kind: "owner";
12
+ readonly path: string;
13
+ readonly uid: number;
14
+ } | {
15
+ readonly kind: "writable";
16
+ readonly path: string;
17
+ readonly mode: number;
18
+ } | {
19
+ readonly kind: "not-regular";
20
+ readonly path: string;
21
+ readonly type: string;
22
+ } | {
23
+ readonly kind: "too-large";
24
+ readonly path: string;
25
+ readonly bytes: number;
26
+ } | {
27
+ readonly kind: "link-loop";
28
+ readonly path: string;
29
+ } | {
30
+ readonly kind: "unreadable";
31
+ readonly path: string;
32
+ readonly errno: string;
33
+ }
34
+ /** 读者会读的这一项不存在,而它所在的目录是开放的粘滞目录 —— 别的用户能在判与读之间把它建出来(缺席没有约束力)。 */
35
+ | {
36
+ readonly kind: "creatable";
37
+ readonly path: string;
38
+ readonly parent: string;
39
+ readonly mode: number;
40
+ }
41
+ /** 走路径找不到、读者却打得开:链接读出的不是路径(procfs 的 `pipe:[…]` / `net:[…]` 一类内核对象)—— 判不了它的属主与模式。 */
42
+ | {
43
+ readonly kind: "unresolvable";
44
+ readonly path: string;
45
+ }
46
+ /** 只读挂载的 kubelet ConfigMap 卷 `volume`(卷根模式 `mode`,恒组 / 他人可写)的来源在本命名空间里经可写挂载 `mountPoint` 露在 `path`(见 {@link KubeletVolume.writableExposures}):
47
+ * 走得到 `path` 的人能在判与读之间换掉 `..data`。 */
48
+ | {
49
+ readonly kind: "exposed";
50
+ readonly path: string;
51
+ readonly mountPoint: string;
52
+ readonly volume: string;
53
+ readonly mode: number;
54
+ };
55
+ /** 判官看的宿主事实(测试注入;生产 = 本进程)。 */
56
+ export interface ConfigDirTrustHost {
57
+ readonly platform: NodeJS.Platform;
58
+ readonly euid: number | undefined;
59
+ /** 本进程的挂载表(`/proc/self/mountinfo` 全文;解读见 {@link kubeletVolumeIn})。缺席 = 本进程实测(Linux 读 procfs;别的平台没有 kubelet 卷,答空表)。只在认 kubelet 卷根时读。 */
60
+ readonly mountinfo?: () => Promise<string>;
61
+ }
62
+ export interface ConfigDirTrustInput {
63
+ /** 本地配置根(持有 `config.d`;`configLocalRoot` 的那一个值)。相对路径按进程 cwd 解,与读者打开文件时同一个解法。 */
64
+ readonly root: string;
65
+ /** `CONFIG_LOCAL_OWNER_UID`(配置席 `configLocalOwnerUid`);缺席 = 只信本进程 euid 与 root。 */
66
+ readonly declaredOwnerUid: number | undefined;
67
+ /** 缺省 = 本进程。 */
68
+ readonly host?: ConfigDirTrustHost;
69
+ }
70
+ /** 来源在本命名空间里的一处可写露出:`path` = 那条路径,`mountPoint` = 露出它的那只可写挂载的挂载点。 */
71
+ export interface KubeletVolumeExposure {
72
+ readonly path: string;
73
+ readonly mountPoint: string;
74
+ }
75
+ /** 一只只读挂载的 kubelet ConfigMap 卷(见 {@link kubeletVolumeIn})。 */
76
+ export interface KubeletVolume {
77
+ /** 卷在源文件系统里的目录(mountinfo 第 4 格,如 `/var/lib/kubelet/pods/<uid>/volumes/kubernetes.io~configmap/<卷>`)。 */
78
+ readonly source: string;
79
+ /**
80
+ * 本命名空间里经**可写**挂载露出这个来源的每一处:同一文件系统(设备号同)、每挂载选项不含 `ro`、挂载根是来源本身或它的祖先 —— 按挂载点映射成一条路径,
81
+ * **且走那条路径看见的正是这只挂载**({@link visibleMountOf}):被只读挂载盖住(那条路径上只读)、被别的文件系统或映射别处的挂载盖住(那条路径上看见的不是来源)⇒ 不是露出;
82
+ * 判不出谁可见(影子挂载)⇒ 算露出(判不出就不认)。
83
+ */
84
+ readonly writableExposures: readonly KubeletVolumeExposure[];
85
+ }
86
+ /**
87
+ * 🔴 **`dir` 是不是一只只读挂载的 kubelet ConfigMap 卷的挂载点**,是则交回它的来源与来源在本命名空间里的可写露出(纯判:读的是 `/proc/self/mountinfo` 的全文)。
88
+ * 先找**走路径看见的那一只挂载**({@link visibleMountOf}:叠在祖先上的挂载会把卷根整个盖住,codex 验证轮 V1 / 二),它的挂载点必须恰是 `dir`,且两件同时成立:
89
+ * 每挂载选项含 `ro`;它在源文件系统里的根路径是 kubelet configMap 卷目录的整形({@link KUBELET_VOLUME_ROOT})。
90
+ * 路径形只认出「这是 kubelet 卷」(任何能写某个目录的人都造得出这个形,修复验证二):来源能不能被人改,看 `writableExposures`(见那一格的可见性律)。
91
+ * 内存介质的卷(Secret / projected / downwardAPI)在 mountinfo 里根路径是一只 tmpfs 的 `/`,认不出 ⇒ 不认(照拒,出路 `subPath` / 烤进镜像)。
92
+ */
93
+ export declare function kubeletVolumeIn(mountinfo: string, dir: string): KubeletVolume | undefined;
94
+ /** `<root>/config.d` 的绝对路径(相对根按 cwd 解)。 */
95
+ export declare function localConfigDirOf(root: string): string;
96
+ /** 判一次。`undefined` = 读者可以读(或没有可读的);否则那一条发现。 */
97
+ export declare function judgeLocalConfigDir(input: ConfigDirTrustInput): Promise<ConfigDirUntrustedFinding | undefined>;
98
+ /** 一条发现的句子(纯字符串 ⇒ `build*`)。头半句说为什么要判、谁可以改;后半句点名路径、实测值与改法。 */
99
+ export declare function buildConfigDirUntrustedSentence(f: ConfigDirUntrustedFinding, ctx: {
100
+ readonly configDir: string;
101
+ readonly euid: number | undefined;
102
+ readonly declaredOwnerUid: number | undefined;
103
+ }): string;
104
+ /** 判出一条发现时抛的错:`code` = {@link CONFIG_DIR_UNTRUSTED_CODE},`message` = 那一句,`finding` = 结构。 */
105
+ export declare class ConfigDirUntrustedError extends Error {
106
+ readonly code = "config.dir_untrusted";
107
+ readonly finding: ConfigDirUntrustedFinding;
108
+ constructor(sentence: string, finding: ConfigDirUntrustedFinding);
109
+ }
110
+ /** 两个调用点的口:判,有发现就抛 {@link ConfigDirUntrustedError}。 */
111
+ export declare function assertLocalConfigDirTrusted(input: ConfigDirTrustInput): Promise<void>;
112
+ /** `CONFIG_LOCAL_OWNER_UID` 的解析(`loadConfig` 调;无条件解析 —— 形错的值不许躺在一台今天不读 `config.d` 的机器上等哪天生效)。缺席 ⇒ `undefined`;形错 ⇒ 抛 = 拒启。 */
113
+ export declare function parseConfigLocalOwnerUid(raw: string | undefined): number | undefined;
114
+ //# sourceMappingURL=config-dir-trust.d.ts.map
@@ -0,0 +1,388 @@
1
+ import { lstat, readFile, readdir, readlink, realpath, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { LOCAL_READER_DOCUMENTS } from "./config-d-migration.js";
4
+ import { recordFailOpen } from "./observability/fail-open.js";
5
+ import { HOST_PLATFORM } from "./plugins/host-platform.js";
6
+ export const CONFIG_DIR_UNTRUSTED_CODE = "config.dir_untrusted";
7
+ export const CONFIG_LOCAL_OWNER_UID_ENV = "CONFIG_LOCAL_OWNER_UID";
8
+ export const CONFIG_DOCUMENT_MAX_BYTES = 16 * 1024 * 1024;
9
+ export const CONFIG_DIR_LINK_HOPS_MAX = 40;
10
+ const UID_MAX = 4294967294;
11
+ const WIN32_UNVERIFIED_TAG = "server.config-dir-trust.win32-owner-mode-unverifiable";
12
+ const errnoOf = (e) => (e instanceof Error && "code" in e && typeof e.code === "string" ? e.code : undefined);
13
+ const KUBELET_VOLUME_ROOT = /\/pods\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/volumes\/kubernetes\.io~configmap\/[^/]+$/;
14
+ const coversPath = (ancestor, p) => ancestor === p || ancestor === "/" || p.startsWith(`${ancestor}/`);
15
+ const unescapeMountinfoPath = (field) => field.replace(/\\([0-7]{3})/g, (_m, oct) => String.fromCharCode(Number.parseInt(oct, 8)));
16
+ function visibleMountOf(rows, dir) {
17
+ const ids = new Set(rows.map((r) => r.id));
18
+ let level = rows.filter((r) => !ids.has(r.parent) || r.parent === r.id);
19
+ let visible;
20
+ for (let depth = 0; depth <= rows.length; depth++) {
21
+ const covering = level.filter((r) => coversPath(r.mountPoint, dir));
22
+ if (covering.length === 0)
23
+ break;
24
+ const shortest = Math.min(...covering.map((r) => r.mountPoint.length));
25
+ const first = covering.filter((r) => r.mountPoint.length === shortest);
26
+ if (first.length !== 1)
27
+ return "ambiguous";
28
+ const next = first[0];
29
+ visible = next;
30
+ level = rows.filter((r) => r.parent === next.id && r.id !== next.id);
31
+ }
32
+ return visible;
33
+ }
34
+ export function kubeletVolumeIn(mountinfo, dir) {
35
+ const rows = [];
36
+ for (const line of mountinfo.split("\n")) {
37
+ const f = line.split(" ");
38
+ const [id, parent, dev, root, mountPoint, options] = f;
39
+ if (f.indexOf("-", 6) === -1 || id === undefined || parent === undefined || dev === undefined || root === undefined || mountPoint === undefined || options === undefined)
40
+ continue;
41
+ rows.push({ id, parent, dev, root: unescapeMountinfoPath(root), mountPoint: unescapeMountinfoPath(mountPoint), options: options.split(",") });
42
+ }
43
+ const visible = visibleMountOf(rows, dir);
44
+ if (typeof visible !== "object" || visible.mountPoint !== dir || !visible.options.includes("ro") || !KUBELET_VOLUME_ROOT.test(visible.root))
45
+ return undefined;
46
+ const source = visible.root;
47
+ const writableExposures = [];
48
+ for (const r of rows) {
49
+ if (r.dev !== visible.dev || r.options.includes("ro") || !coversPath(r.root, source))
50
+ continue;
51
+ const exposed = path.posix.join(r.mountPoint, r.root === "/" ? source : source.slice(r.root.length));
52
+ const seen = visibleMountOf(rows, exposed);
53
+ if (typeof seen === "object" && seen !== r)
54
+ continue;
55
+ if (!writableExposures.some((e) => e.path === exposed))
56
+ writableExposures.push({ path: exposed, mountPoint: r.mountPoint });
57
+ }
58
+ return { source, writableExposures };
59
+ }
60
+ async function processMountinfo() {
61
+ return HOST_PLATFORM === "linux" ? readFile("/proc/self/mountinfo", "utf8") : "";
62
+ }
63
+ const processHost = () => ({ platform: HOST_PLATFORM, euid: process.geteuid?.(), mountinfo: processMountinfo });
64
+ const UNREACHABLE = new Set(["ENOENT", "ENOTDIR"]);
65
+ const NOT_REACHED = { reached: false };
66
+ function typeOf(st) {
67
+ if (st.isDirectory())
68
+ return "directory";
69
+ if (st.isFIFO())
70
+ return "fifo";
71
+ if (st.isSocket())
72
+ return "socket";
73
+ if (st.isCharacterDevice())
74
+ return "character device";
75
+ if (st.isBlockDevice())
76
+ return "block device";
77
+ return "non-regular file";
78
+ }
79
+ function componentVerdict(p, st, owners) {
80
+ if (!owners.has(st.uid))
81
+ return { kind: "owner", path: p, uid: st.uid };
82
+ if (st.isSymbolicLink() || (st.mode & 0o022) === 0)
83
+ return "closed";
84
+ if (st.isDirectory() && (st.mode & 0o1000) !== 0)
85
+ return "open";
86
+ return { kind: "writable", path: p, mode: st.mode & 0o7777 };
87
+ }
88
+ const KUBELET_NODE_SIDE_TAG = "server.config-dir-trust.kubelet-volume-node-side-unverifiable";
89
+ const KUBELET_TIMESTAMP_DIR = /^\.\.\d{4}_\d{2}_\d{2}_\d{2}_\d{2}_\d{2}\.\d+$/;
90
+ const KUBELET_DATA_LINKS = new Set(["..data", "..data_tmp"]);
91
+ async function projectedVolumeRoot(dir, mode, ctx) {
92
+ const listing = await readdir(dir).then((names) => ({ names }), (error) => ({ error }));
93
+ if ("error" in listing)
94
+ return false;
95
+ const names = listing.names;
96
+ if (!names.includes("..data"))
97
+ return false;
98
+ let at = dir;
99
+ let volume;
100
+ try {
101
+ const stampDirs = new Set();
102
+ const linkTargets = [];
103
+ for (const name of names) {
104
+ at = path.posix.join(dir, name);
105
+ const st = await lstat(at);
106
+ if (!ctx.owners.has(st.uid))
107
+ return false;
108
+ if (KUBELET_DATA_LINKS.has(name)) {
109
+ if (!st.isSymbolicLink())
110
+ return false;
111
+ linkTargets.push(await readlink(at));
112
+ }
113
+ else if (KUBELET_TIMESTAMP_DIR.test(name)) {
114
+ if (!st.isDirectory() || componentVerdict(at, st, ctx.owners) !== "closed")
115
+ return false;
116
+ stampDirs.add(name);
117
+ }
118
+ else if (name.startsWith("..") || !st.isSymbolicLink() || (await readlink(at)) !== `..data/${name}`) {
119
+ return false;
120
+ }
121
+ }
122
+ if (!linkTargets.every((target) => stampDirs.has(target)))
123
+ return false;
124
+ at = "/proc/self/mountinfo";
125
+ volume = kubeletVolumeIn(await ctx.mountinfo(), dir);
126
+ }
127
+ catch (e) {
128
+ return { kind: "unreadable", path: at, errno: errnoOf(e) ?? String(e) };
129
+ }
130
+ if (volume === undefined)
131
+ return false;
132
+ const exposure = volume.writableExposures[0];
133
+ if (exposure !== undefined)
134
+ return { kind: "exposed", path: exposure.path, mountPoint: exposure.mountPoint, volume: dir, mode };
135
+ recordFailOpen(KUBELET_NODE_SIDE_TAG, `volume=${dir} source=${volume.source}`);
136
+ return true;
137
+ }
138
+ async function judgeComponent(p, st, ctx) {
139
+ const v = componentVerdict(p, st, ctx.owners);
140
+ if (typeof v === "string" || v.kind !== "writable" || !st.isDirectory())
141
+ return v;
142
+ const projected = await projectedVolumeRoot(p, v.mode, ctx);
143
+ if (projected === true)
144
+ return "closed";
145
+ return projected === false ? v : projected;
146
+ }
147
+ const isStats = (x) => "isDirectory" in x;
148
+ async function lstatStep(p) {
149
+ try {
150
+ return await lstat(p);
151
+ }
152
+ catch (e) {
153
+ const code = errnoOf(e);
154
+ if (code !== undefined && UNREACHABLE.has(code))
155
+ return NOT_REACHED;
156
+ return { finding: { kind: "unreadable", path: p, errno: code ?? String(e) } };
157
+ }
158
+ }
159
+ async function walk(from, pending, want, ctx) {
160
+ let cur = from.start;
161
+ let st = from.stats;
162
+ let open = from.open;
163
+ let hops = from.hops;
164
+ const queue = [...pending];
165
+ const enter = async (p) => {
166
+ const got = await lstatStep(p);
167
+ if (!isStats(got))
168
+ return got;
169
+ const v = await judgeComponent(p, got, ctx);
170
+ if (typeof v !== "string")
171
+ return { finding: v };
172
+ cur = p;
173
+ st = got;
174
+ open = v === "open";
175
+ return undefined;
176
+ };
177
+ while (queue.length > 0) {
178
+ const name = queue.shift();
179
+ if (name === "" || name === ".")
180
+ continue;
181
+ if (name === "..") {
182
+ const stop = await enter(path.posix.dirname(cur));
183
+ if (stop !== undefined)
184
+ return stop;
185
+ continue;
186
+ }
187
+ const next = path.posix.join(cur, name);
188
+ const got = await lstatStep(next);
189
+ if (!isStats(got)) {
190
+ if (!("reached" in got) || !open)
191
+ return got;
192
+ return { finding: { kind: "creatable", path: next, parent: cur, mode: st.mode & 0o7777 } };
193
+ }
194
+ const v = await judgeComponent(next, got, ctx);
195
+ if (typeof v !== "string")
196
+ return { finding: v };
197
+ if (got.isSymbolicLink()) {
198
+ if (++hops > CONFIG_DIR_LINK_HOPS_MAX)
199
+ return { finding: { kind: "link-loop", path: next } };
200
+ let target;
201
+ try {
202
+ target = await readlink(next);
203
+ }
204
+ catch (e) {
205
+ const code = errnoOf(e);
206
+ if (code !== undefined && UNREACHABLE.has(code))
207
+ return NOT_REACHED;
208
+ return { finding: { kind: "unreadable", path: next, errno: code ?? String(e) } };
209
+ }
210
+ queue.unshift(...target.split("/"));
211
+ if (target.startsWith("/")) {
212
+ const stop = await enter("/");
213
+ if (stop !== undefined)
214
+ return stop;
215
+ }
216
+ continue;
217
+ }
218
+ if (queue.some((n) => n !== "" && n !== ".") && !got.isDirectory())
219
+ return NOT_REACHED;
220
+ cur = next;
221
+ st = got;
222
+ open = v === "open";
223
+ }
224
+ if (want === "dir")
225
+ return st.isDirectory() ? { reached: true, physical: cur, stats: st, open, hops } : NOT_REACHED;
226
+ if (!st.isFile())
227
+ return { finding: { kind: "not-regular", path: cur, type: typeOf(st) } };
228
+ if (st.size > CONFIG_DOCUMENT_MAX_BYTES)
229
+ return { finding: { kind: "too-large", path: cur, bytes: st.size } };
230
+ return { reached: true, physical: cur, stats: st, open, hops };
231
+ }
232
+ async function confirmUnreached(lexical) {
233
+ try {
234
+ await stat(lexical);
235
+ }
236
+ catch (e) {
237
+ const code = errnoOf(e);
238
+ if (code !== undefined && UNREACHABLE.has(code))
239
+ return undefined;
240
+ if (code === "ELOOP")
241
+ return { kind: "link-loop", path: lexical };
242
+ return { kind: "unreadable", path: lexical, errno: code ?? String(e) };
243
+ }
244
+ return { kind: "unresolvable", path: lexical };
245
+ }
246
+ const documentFiles = () => LOCAL_READER_DOCUMENTS.map((d) => `${d}.json`);
247
+ async function reachDir(lexical, ctx) {
248
+ const top = await lstatStep("/");
249
+ if (!isStats(top))
250
+ return "finding" in top ? top.finding : undefined;
251
+ const rootVerdict = await judgeComponent("/", top, ctx);
252
+ if (typeof rootVerdict !== "string")
253
+ return rootVerdict;
254
+ const step = await walk({ start: "/", stats: top, open: rootVerdict === "open", hops: 0 }, lexical.split("/"), "dir", ctx);
255
+ if ("finding" in step)
256
+ return step.finding;
257
+ return step.reached ? step : confirmUnreached(lexical);
258
+ }
259
+ async function judgePosix(configDir, ctx) {
260
+ const dir = await reachDir(configDir, ctx);
261
+ if (dir === undefined || "kind" in dir)
262
+ return dir;
263
+ for (const file of documentFiles()) {
264
+ const doc = await walk({ start: dir.physical, stats: dir.stats, open: dir.open, hops: dir.hops }, [file], "file", ctx);
265
+ if ("finding" in doc)
266
+ return doc.finding;
267
+ if (!doc.reached) {
268
+ const unseen = await confirmUnreached(path.join(configDir, file));
269
+ if (unseen !== undefined)
270
+ return unseen;
271
+ }
272
+ }
273
+ return undefined;
274
+ }
275
+ async function judgeWin32(configDir) {
276
+ const resolveStep = async (p) => {
277
+ try {
278
+ return await realpath(p);
279
+ }
280
+ catch (e) {
281
+ const code = errnoOf(e);
282
+ if (code !== undefined && UNREACHABLE.has(code))
283
+ return undefined;
284
+ if (code === "ELOOP")
285
+ return { kind: "link-loop", path: p };
286
+ return { kind: "unreadable", path: p, errno: code ?? String(e) };
287
+ }
288
+ };
289
+ const dir = await resolveStep(configDir);
290
+ if (dir === undefined)
291
+ return undefined;
292
+ if (typeof dir !== "string")
293
+ return dir;
294
+ if (!(await stat(dir)).isDirectory())
295
+ return undefined;
296
+ for (const file of documentFiles()) {
297
+ const doc = await resolveStep(path.join(dir, file));
298
+ if (doc === undefined)
299
+ continue;
300
+ if (typeof doc !== "string")
301
+ return doc;
302
+ const st = await stat(doc);
303
+ if (!st.isFile())
304
+ return { kind: "not-regular", path: doc, type: typeOf(st) };
305
+ if (st.size > CONFIG_DOCUMENT_MAX_BYTES)
306
+ return { kind: "too-large", path: doc, bytes: st.size };
307
+ }
308
+ recordFailOpen(WIN32_UNVERIFIED_TAG, `config.d=${dir}`);
309
+ return undefined;
310
+ }
311
+ export function localConfigDirOf(root) {
312
+ return path.join(path.resolve(root), "config.d");
313
+ }
314
+ export async function judgeLocalConfigDir(input) {
315
+ const host = input.host ?? processHost();
316
+ const configDir = localConfigDirOf(input.root);
317
+ if (host.platform === "win32")
318
+ return judgeWin32(configDir);
319
+ const owners = new Set([0]);
320
+ if (host.euid !== undefined)
321
+ owners.add(host.euid);
322
+ if (input.declaredOwnerUid !== undefined)
323
+ owners.add(input.declaredOwnerUid);
324
+ return judgePosix(configDir, { owners, mountinfo: host.mountinfo ?? processMountinfo });
325
+ }
326
+ const octal = (mode) => `0${(mode & 0o7777).toString(8).padStart(3, "0")}`;
327
+ export function buildConfigDirUntrustedSentence(f, ctx) {
328
+ const self = ctx.euid === undefined ? "this server's user" : `this server's user (uid ${ctx.euid})`;
329
+ const declared = ctx.declaredOwnerUid === undefined ? "" : ` or the declared owner ${CONFIG_LOCAL_OWNER_UID_ENV}=${ctx.declaredOwnerUid}`;
330
+ const head = `${CONFIG_DIR_UNTRUSTED_CODE}: refusing to read the local config source ${ctx.configDir} — its documents decide which commands this server starts (mcp.json) ` +
331
+ `and where it sends credentials (models.json), so only ${self}, root${declared} may be able to change them, but`;
332
+ switch (f.kind) {
333
+ case "owner":
334
+ return (`${head} ${f.path} is owned by uid ${f.uid}${ctx.declaredOwnerUid === undefined ? ` (${CONFIG_LOCAL_OWNER_UID_ENV} is not set)` : ""}. ` +
335
+ `Fix: chown ${ctx.euid ?? "<this server's uid>"} ${f.path}, or declare that owner with ${CONFIG_LOCAL_OWNER_UID_ENV}=${f.uid}.`);
336
+ case "writable": {
337
+ const who = (f.mode & 0o020) !== 0 && (f.mode & 0o002) !== 0 ? "group- and other" : (f.mode & 0o020) !== 0 ? "group" : "other";
338
+ return `${head} ${f.path} is ${who}-writable (mode ${octal(f.mode)}). Fix: chmod go-w ${f.path}.`;
339
+ }
340
+ case "not-regular":
341
+ return `${head} ${f.path} is a ${f.type}, not a regular file. Fix: replace it with a regular file, or remove it.`;
342
+ case "too-large":
343
+ return `${head} ${f.path} is ${f.bytes} bytes, over the ${CONFIG_DOCUMENT_MAX_BYTES}-byte cap for one config document. Fix: shrink it.`;
344
+ case "link-loop":
345
+ return `${head} ${f.path} leads through more than ${CONFIG_DIR_LINK_HOPS_MAX} symbolic links. Fix: point the link at the file directly.`;
346
+ case "unreadable":
347
+ return `${head} ${f.path} cannot be inspected (${f.errno}), so its owner and mode cannot be checked. Fix: give this server's user search access to every directory on the path.`;
348
+ case "creatable":
349
+ return (`${head} ${f.path} does not exist and ${f.parent} (mode ${octal(f.mode)}) lets other users create it between this check and the read. ` +
350
+ `Fix: create ${f.path} as this server's user, or move the config root (CONFIG_LOCAL_DIR) under a directory only this server's user or root can write.`);
351
+ case "unresolvable":
352
+ return `${head} ${f.path} is a symbolic link that does not resolve to a path (it points at a kernel object such as a /proc descriptor), so its owner and mode cannot be checked. Fix: point it at a regular file.`;
353
+ case "exposed":
354
+ return (`${head} ${f.volume} is a read-only Kubernetes ConfigMap volume whose source is also reachable through the writable mount at ${f.mountPoint}, as ${f.path} ` +
355
+ `(mode ${octal(f.mode)}), so whoever can reach that path can replace these documents between this check and the read. ` +
356
+ `Fix: remove the writable mount at ${f.mountPoint} — do not mount the node's root, its kubelet directory or any other ancestor of that directory writable into this pod; mount the config with subPath, or do not mount that ancestor at all. Do not relax permissions on the node.`);
357
+ default: {
358
+ const unhandled = f;
359
+ throw new Error(`buildConfigDirUntrustedSentence: unhandled finding ${JSON.stringify(unhandled)}`);
360
+ }
361
+ }
362
+ }
363
+ export class ConfigDirUntrustedError extends Error {
364
+ code = CONFIG_DIR_UNTRUSTED_CODE;
365
+ finding;
366
+ constructor(sentence, finding) {
367
+ super(sentence);
368
+ this.name = "ConfigDirUntrustedError";
369
+ this.finding = finding;
370
+ }
371
+ }
372
+ export async function assertLocalConfigDirTrusted(input) {
373
+ const host = input.host ?? processHost();
374
+ const finding = await judgeLocalConfigDir({ ...input, host });
375
+ if (finding === undefined)
376
+ return;
377
+ throw new ConfigDirUntrustedError(buildConfigDirUntrustedSentence(finding, { configDir: localConfigDirOf(input.root), euid: host.euid, declaredOwnerUid: input.declaredOwnerUid }), finding);
378
+ }
379
+ export function parseConfigLocalOwnerUid(raw) {
380
+ if (raw === undefined)
381
+ return undefined;
382
+ const n = /^(0|[1-9][0-9]{0,9})$/.test(raw) ? Number(raw) : Number.NaN;
383
+ if (Number.isInteger(n) && n <= UID_MAX)
384
+ return n;
385
+ throw new Error(`env ${CONFIG_LOCAL_OWNER_UID_ENV}=${JSON.stringify(raw)} must be a uid — a decimal integer in [0, ${UID_MAX}]: the one extra owner (besides this server's user and root) ` +
386
+ `the local config source's directories and documents may have (a userns-remapped bind mount, an operator-owned config). Unset it to trust only this server's user and root.`);
387
+ }
388
+ //# sourceMappingURL=config-dir-trust.js.map
@@ -34,9 +34,9 @@ import type { ServiceConfigFlat } from "./config-types.js";
34
34
  */
35
35
  export declare const LIVENESS_HEARTBEAT_MS = 30000;
36
36
  /** 闭集:新增一条不变量必须在这里加词(拼错 = 编译红,而不是运行期悄悄不判)。 */
37
- export type CrossInvariantId = "run-stale-heartbeat" | "bind-posture" | "bake-runner-credential" | "direct-door-anchors" | "operator-principals-required" | "bake-operator-principals" | "sensitive-write-patterns" | "leader-host-lane" | "multi-tenant-shared-lane" | "leader-durable-store" | "device-durable-store" | "device-durable-approval" | "model-provider-word" | "gateway-url-userinfo" | "model-route-endpoint" | "default-model-resolvable" | "refused-names-not-minted" | "require-execution-lane" | "center-one-identity";
37
+ export type CrossInvariantId = "run-stale-heartbeat" | "bind-posture" | "bake-runner-credential" | "direct-door-anchors" | "operator-principals-required" | "operator-single-user" | "bake-operator-principals" | "sensitive-write-patterns" | "leader-host-lane" | "multi-tenant-shared-lane" | "leader-durable-store" | "device-durable-store" | "device-durable-approval" | "model-provider-word" | "gateway-url-userinfo" | "model-route-endpoint" | "default-model-resolvable" | "refused-names-not-minted" | "require-execution-lane" | "center-one-identity" | "workflow-park-decision-domain";
38
38
  /** 表读的键集(取自平铺配置型 ⇒ 键名/类型永不与真配置漂)。 */
39
- export type CrossInvariantView = Readonly<Pick<ServiceConfigFlat, "runStaleSec" | "authToken" | "authTokens" | "allowUnauthedWrites" | "imageBakes" | "directApprovalDoor" | "durableApproval" | "approvalHmacKeys" | "principalJwtPubkeys" | "principalJwtIss" | "principalJwtAud" | "requirePrincipal" | "operatorPrincipals" | "sensitiveWritePatterns" | "leaderEnabled" | "remoteExec" | "requireExecutionLane" | "dbBackend" | "tidb" | "pg" | "envModel" | "gatewayBaseUrl" | "gatewayFallbackUrls" | "anthropic" | "models" | "modelRefusals" | "tiers" | "authBridgeIssuer" | "webAdmin">>;
39
+ export type CrossInvariantView = Readonly<Pick<ServiceConfigFlat, "runStaleSec" | "authToken" | "authTokens" | "allowUnauthedWrites" | "imageBakes" | "directApprovalDoor" | "durableApproval" | "approvalHmacKeys" | "principalJwtPubkeys" | "principalJwtIss" | "principalJwtAud" | "requirePrincipal" | "operatorPrincipals" | "operatorSingleUser" | "sensitiveWritePatterns" | "leaderEnabled" | "selfOrchestrationEnabled" | "workflowRunStoreBackend" | "remoteExec" | "requireExecutionLane" | "dbBackend" | "tidb" | "pg" | "envModel" | "gatewayBaseUrl" | "gatewayFallbackUrls" | "anthropic" | "models" | "modelRefusals" | "tiers" | "authBridgeIssuer" | "webAdmin">>;
40
40
  export interface CrossInvariantInput {
41
41
  /** 现役配置(boot 期 = 候选自身)。 */
42
42
  readonly live: CrossInvariantView;
@@ -68,11 +68,17 @@ export interface CrossInvariant {
68
68
  /** `direct-door-anchors` 的状态臂:半开的直连门(开着却缺锚点)。转换臂(门姿态翻转)只活在热路径,留在条目里。 */
69
69
  export declare function halfOpenDirectDoorRefusal(v: Pick<CrossInvariantView, "directApprovalDoor" | "durableApproval" | "approvalHmacKeys" | "principalJwtPubkeys" | "principalJwtIss" | "principalJwtAud" | "requirePrincipal" | "operatorPrincipals">): string | undefined;
70
70
  /**
71
- * `operator-principals-required`([ref]-① 普查候选 1/2):BFF 多租户 durable 形(DURABLE_APPROVAL ∧ REQUIRE_PRINCIPAL,直连门关)的空 operator 名单 ——
72
- * approvals-assistant 四个读面按裸 `isOperator` 划 scope,空名单 true-for-all ⇒ 任一租户 principal 可读他租户的待批队列。单租户 legacy(REQUIRE_PRINCIPAL 未设)刻意保留。
71
+ * `operator-principals-required`([ref]-① 普查候选 1/2):BFF 多租户 durable 形(DURABLE_APPROVAL ∧ REQUIRE_PRINCIPAL,直连门关)的空 operator 名单。
72
+ * 这条不变量生于审批四读面读「空名单 = 人人是」那条读法的年代(那时它防的是跨租户读待批队列);S-1050 删了那条读法 —— 空名单在每一面都是「没人是」,
73
+ * 不再外泄任何东西 —— 剩下的事实是「这台多租 worker 的审批队列没有人能当运维」。本版只把句子改真、不改拒启集;删不删这一条是另一次表态。
73
74
  */
74
75
  export declare function operatorPrincipalsRequiredRefusal(v: Pick<CrossInvariantView, "durableApproval" | "requirePrincipal" | "operatorPrincipals">): string | undefined;
75
- /** `bake-operator-principals`(IMAGE-API-DESIGN §P2.4a):bake 门是 build-host 无限制执行面,空 operator 名单让 isOperator true-for-all = 无限制写入面。 */
76
+ /**
77
+ * `operator-single-user`(S-1050,[ref] ① 裁 A):「谁是 operator」一个事实一个来源。`OPERATOR_SINGLE_USER=true`(单用户形的每个调用方都是运维)
78
+ * 只在单用户形、名单为空时成立:多租形没有「单一用户」(声明会把每个租户都变成运维);名单非空时两个来源答同一个问题。两形都拒,句子点名两根旋钮与出路。
79
+ */
80
+ export declare function operatorSingleUserRefusal(v: Pick<CrossInvariantView, "operatorSingleUser" | "requirePrincipal" | "operatorPrincipals">): string | undefined;
81
+ /** `bake-operator-principals`(IMAGE-API-DESIGN §P2.4a):bake 门是 build-host 无限制执行面,要**具名**运维 —— 空名单下要么没人用得了,要么(单用户声明)人人用得了。 */
76
82
  export declare function bakeOperatorPrincipalsRefusal(v: Pick<CrossInvariantView, "imageBakes" | "operatorPrincipals">): string | undefined;
77
83
  /**
78
84
  * `bake-runner-credential`(IMAGE-API-DESIGN §P2.12 / H1):bake-runner 的身份由它的 bearer 凭据**派生**(token-derived `source`),不是自称的头 ——
@@ -84,6 +90,13 @@ export declare function bakeRunnerCredentialRefusal(v: Pick<CrossInvariantView,
84
90
  * 「多副本」在 config 层判不了(副本数不是本进程的知识),可判的**代理**就是 durable 前提本身。
85
91
  */
86
92
  export declare function leaderDurableStoreRefusal(v: Pick<CrossInvariantView, "leaderEnabled" | "dbBackend">): string | undefined;
93
+ /**
94
+ * `workflow-park-decision-domain`(7.133.0)—— workflow 子代审批决定行的店必须与会话认领同域。决定行在 run 店的会话认领栅栏里写(SQL 后端一个事务、同一只池),
95
+ * 而库里的决定行随库里的 workflow 记录收割 ⇒ SQL 后端上 workflow 记录也必须在库里(`WORKFLOW_RUN_STORE=auto`)。`file` / `memory` 把记录放在库外,没有一只决定店两头都满足。
96
+ * 判的是**这份配置会不会装出 SQL 店**(坐标铸出来了没有,与 `device-durable-store` 同读法),不是 `dbBackend` 标签。**配置组合的拒启** —— 判在第 1 段(loadConfig),
97
+ * 先于第 3 段的一次性迁移:拒的那一次起服没有动过库。`createHttpServer` 里的 `parkDecisionStoreRefusal` 判的是另一件事(嵌入方递进来的决定店绑没绑在这只 run 店上,按身份比)。
98
+ */
99
+ export declare function workflowParkDecisionDomainRefusal(v: Pick<CrossInvariantView, "selfOrchestrationEnabled" | "workflowRunStoreBackend" | "dbBackend" | "tidb" | "pg">): string | undefined;
87
100
  /**
88
101
  * `center-one-identity`(7.124.0)—— **中心只有一个身份**。引擎接的 web-admin 由三只旋钮描述:基址(`WEB_ADMIN_ENV.url`,传输地址)、
89
102
  * 鉴权桥 issuer(`AUTH_BRIDGE_ISSUER`,缺席 = 基址 —— {@link authBridgeIssuerOf} 一只取值口)、web 基址(`WEB_ADMIN_ENV.webUrl`,上