@sema-agent/server 7.150.0 → 7.152.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 (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  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 +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  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/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -3,9 +3,9 @@ import { skillCardFacts } from "../../approval-card.js";
3
3
  import { hostDecisionFacts, readDecider, retiredDecisionKeyFacts, DECIDED_BY_NOT_IN_PROOF } from "../../host-decision.js";
4
4
  import { sameExecutionRecord } from "@sema-agent/core";
5
5
  import { findParkedAgentForCheckpoint } from "../../parked-decide.js";
6
- import { DECIDED_REPLAY_SCAN_CAP, pendingTriageOrder } from "../../plugins/checkpoint-store-face.js";
6
+ import { DECIDED_REPLAY_SCAN_CAP, displayRuleOffers, pendingTriageOrder } from "../../plugins/checkpoint-store-face.js";
7
7
  import { approvalPayloadFingerprint } from "../../plugins/approval-payload-fingerprint.js";
8
- import { carriesDeploymentListQuestion, standingAnswerDurablyRecordable } from "../../tool-approval.js";
8
+ import { cardRuleOffersOfAskRow, carriesDeploymentListQuestion, readPersistRuleSlot, standingAnswerDurablyRecordable } from "../../tool-approval.js";
9
9
  import { APPROVAL_GATE_KINDS } from "../../approval-content-kind.js";
10
10
  import { isParkedRunStatus } from "../../plugins/store-contracts.js";
11
11
  import { principalFrom, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../../security.js";
@@ -13,7 +13,7 @@ import { keyAdmits } from "../../owner-faces.js";
13
13
  import { personOf } from "../../owner-brands.js";
14
14
  import { editedPlanBinding, verifyDirectDoorProof } from "../../principal-jwt.js";
15
15
  import { isWellFormedUnicode } from "../../principal-shape.js";
16
- import { MAX_APPROVAL_REASON_CHARS, projectQuestionAnswer, questionAnswerFromProjection } from "../../approval-hmac.js";
16
+ import { MAX_APPROVAL_REASON_CHARS, persistRuleFromProjection, projectPersistRule, projectQuestionAnswer, questionAnswerFromProjection } from "../../approval-hmac.js";
17
17
  import { PLAN_APPROVE_PERMISSION_MODES_AFTER, isPlanApprovePermissionModeAfter, planReviewDecisionExitsPlan, storedBodyPermissionMode } from "../../task-settings.js";
18
18
  import { MAX_APPROVAL_NONCE_CHARS } from "../../plugins/approval-nonce-store.js";
19
19
  import { redactedPreview, redactSecrets } from "../../trace/redact.js";
@@ -22,12 +22,13 @@ import { buildRunName } from "../../fleet/fleet-bus.js";
22
22
  import { sleep } from "../sse-log.js";
23
23
  import { bindSseLifecycle } from "../sse-lifecycle.js";
24
24
  import { sendJson, sendError, sseHeaders, logRequestError, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "../send.js";
25
- import { gatedSubject, explicitOperatorOk, sendPrincipalRefusal } from "../principal-gate.js";
25
+ import { createLogger } from "../../observability/logger.js";
26
+ import { gatedSubject, explicitOperatorOk, confinedTierOf, sendPrincipalConfined, sendPrincipalRefusal } from "../principal-gate.js";
26
27
  import { admitRunById, admitSessionById, callerEntry, callerOf, callerOfDecision, deciderSubjectOf, enter, latestRunIdOf, listRunsOfScope, protocolEntry, readSessionAgent, readVisibleRun, refuse, runFactsOf, withCaller } from "../owner-access.js";
27
28
  import { governanceOriginOf } from "../../runtime-governance.js";
28
29
  import { deploymentListAsks } from "../../approval.js";
29
30
  import { grantBindingOf } from "../../standing-answer-grant.js";
30
- import { sendResumeOutcome } from "../route-ctx.js";
31
+ import { readRememberSlot, ruleReceiptOf, sendResumeOutcome } from "../route-ctx.js";
31
32
  import { assertNever } from "../route-ctx.js";
32
33
  import * as facts from "../../capability-facts.js";
33
34
  import { storeFaultClassOf } from "../../plugins/store-fault.js";
@@ -38,13 +39,14 @@ import { fieldConflictFacts } from "../../field-conflict.js";
38
39
  import { buildSettlementEvidence } from "../../gate-settlement.js";
39
40
  import { seatText } from "../../trace/exit-seat.js";
40
41
  import { approvalQueueKindOfDoorId } from "../../approval-queue-kind.js";
41
- import { defaultPeerInboundFace, parsePeerInboundId, peerBoxScope } from "../../peer-inbound-face.js";
42
+ import { defaultPeerInboundFace, parsePeerInboundId } from "../../peer-inbound-face.js";
43
+ import { engineScopeOfOwner } from "../../engine-identity.js";
42
44
  import { RESUME_RESTATABLE_KEYS, readResumeRestatement } from "../resume-restatement.js";
43
45
  const DECIDE_BODY_DECLARED_KEYS = [
44
- "answer", "boundCallId", "boundInputHash", "checkpointToken", "decidedBy", "decidedVia", "decision", "feedback", "reason", "remember", "updatedInput",
46
+ "answer", "boundCallId", "boundInputHash", "checkpointToken", "decidedBy", "decidedVia", "decision", "feedback", "persistRule", "reason", "remember", "updatedInput",
45
47
  ...RESUME_RESTATABLE_KEYS,
46
48
  ];
47
- const DECIDE_PROOF_COVERED_KEYS = ["answer", "boundCallId", "boundInputHash", "decision", "reason"];
49
+ const DECIDE_PROOF_COVERED_KEYS = ["answer", "boundCallId", "boundInputHash", "decision", "persistRule", "reason"];
48
50
  const DECIDE_NOT_IN_PROOF_KEYS = ["checkpointToken", "decidedBy", "decidedVia", "feedback", "remember", "updatedInput", ...RESUME_RESTATABLE_KEYS];
49
51
  function readDecisionDoorRestatement(res, body, directDoorActive) {
50
52
  if (directDoorActive && RESUME_RESTATABLE_KEYS.some((key) => body[key] !== undefined)) {
@@ -67,6 +69,7 @@ const PROOF_SLOT_OF = {
67
69
  decision: "decision",
68
70
  editedPlan: "boundInputHash",
69
71
  permissionModeAfter: "permissionModeAfter",
72
+ persistRule: "persistRule",
70
73
  reason: "reason",
71
74
  };
72
75
  function buildApprovalEnvelope(sessionId, covered, reading) {
@@ -311,7 +314,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
311
314
  }
312
315
  const cs = park.checkpointStore;
313
316
  const principal = gatedSubject(req, deps.config);
314
- const operator = explicitOperatorOk(principal === undefined ? undefined : personOf(principal), deps.config);
317
+ const operator = explicitOperatorOk(principal === undefined ? undefined : personOf(principal), deps.config, "operate");
315
318
  const ownScope = principal ?? CHECKPOINT_PUBLIC_SCOPE;
316
319
  if (match.decl.id === "approvals-stream") {
317
320
  const ownerParam = operator ? (new URLSearchParams(match.search).get("owner") ?? undefined) : undefined;
@@ -332,7 +335,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
332
335
  sendApprovalsReadFailure(req, res, deps.logger, err);
333
336
  return;
334
337
  }
335
- const pending = [...(await projectDurableQueue(durableRows, deps.config, deps.sessionStorage)), ...peerInboundRowsFor(defaultPeerInboundFace, principal, ownerParam)()];
338
+ const pending = [...(await projectDurableQueue(durableRows, deps.config, deps.sessionStorage, deps.toolApproval)), ...peerInboundRowsFor(defaultPeerInboundFace, principal, ownerParam)()];
336
339
  const livePending = deps.toolApproval ? await deps.toolApproval.listLivePending(scope) : undefined;
337
340
  sendJson(res, 200, {
338
341
  pending,
@@ -676,19 +679,16 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
676
679
  return;
677
680
  }
678
681
  const storeNowMs = await store.nowMs();
679
- const hdr = (n) => { const h = req.headers[n]; return Array.isArray(h) ? h[0] : h; };
680
- const proof = verifyDirectDoorProof({ jwt: hdr(PRINCIPAL_TOKEN_HEADER), mac: hdr(APPROVAL_MAC_HEADER), kid: hdr(APPROVAL_MAC_KID_HEADER) }, buildApprovalEnvelope(run.sessionId, PLAN_REVIEW_PROOF_COVERED_KEYS, {
682
+ const proof = admitDirectDoorDecider(req, res, buildApprovalEnvelope(run.sessionId, PLAN_REVIEW_PROOF_COVERED_KEYS, {
681
683
  boundCallId: planNonce ?? null,
682
684
  checkpointId: sighting?.value,
683
685
  decision,
684
686
  editedPlan: decision === "edit" ? editedPlanBinding(body.editedPlan) : null,
685
687
  permissionModeAfter: isPlanApprovePermissionModeAfter(body.permissionModeAfter) ? body.permissionModeAfter : undefined,
686
688
  reason: typeof body.reason === "string" ? body.reason : null,
687
- }), deps.config, { actionBinding: false, nowSec: Math.floor(storeNowMs / 1000) });
688
- if (!proof.ok) {
689
- sendError(res, proof.status, proof.errorCode, proof.error);
689
+ }), deps.config, match.decl.power, { actionBinding: false, nowSec: Math.floor(storeNowMs / 1000) });
690
+ if (proof === undefined)
690
691
  return;
691
- }
692
692
  deciderPrincipal = proof.principal;
693
693
  singleUse = proof.singleUse === undefined ? undefined : { proof: proof.singleUse, store };
694
694
  }
@@ -739,7 +739,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
739
739
  const doorKind = approvalQueueKindOfDoorId(sessionId);
740
740
  switch (doorKind) {
741
741
  case "peer_inbound":
742
- await decidePeerInbound(req, res, sessionId, { readJson, config: deps.config, logger: deps.logger, principal, face: defaultPeerInboundFace });
742
+ await decidePeerInbound(req, res, sessionId, { readJson, config: deps.config, logger: deps.logger, principal, face: defaultPeerInboundFace, power: match.decl.power });
743
743
  return;
744
744
  case "checkpoint":
745
745
  break;
@@ -771,15 +771,12 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
771
771
  return;
772
772
  }
773
773
  let remember = false;
774
- if (body.remember !== undefined) {
775
- if (body.remember !== "session") {
776
- sendError(res, 400, "request.field_invalid", `remember must be "session"`);
777
- return;
778
- }
779
- if (decision !== "approve") {
780
- sendError(res, 400, "request.field_conflict", "remember requires decision 'approve'", fieldConflictFacts("remember_decision", ["remember", "decision"]));
781
- return;
782
- }
774
+ const rememberSlot = readRememberSlot(body.remember, decision);
775
+ if (rememberSlot.kind === "refused") {
776
+ sendError(res, 400, rememberSlot.refusal.errorCode, rememberSlot.refusal.message, rememberSlot.refusal.facts);
777
+ return;
778
+ }
779
+ if (rememberSlot.kind === "session") {
783
780
  if (deps.config.directDoorActive) {
784
781
  sendError(res, 400, "remember_not_in_proof", "remember is not supported on a direct-door worker (not covered by the decision proof)");
785
782
  return;
@@ -790,6 +787,12 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
790
787
  }
791
788
  remember = true;
792
789
  }
790
+ const ruleSlot = readPersistRuleSlot(body.persistRule, decision === "approve" ? "allow" : "deny");
791
+ if (!ruleSlot.ok) {
792
+ sendError(res, 400, "request.body_shape", ruleSlot.error);
793
+ return;
794
+ }
795
+ const ruleProjection = ruleSlot.slot !== undefined ? projectPersistRule(ruleSlot.slot) : undefined;
793
796
  let answer;
794
797
  let answerProjection;
795
798
  if (body.answer !== undefined) {
@@ -863,24 +866,19 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
863
866
  };
864
867
  let deciderPrincipal = principal === undefined ? undefined : personOf(principal);
865
868
  if (deps.config.directDoorActive) {
866
- const hdr = (n) => {
867
- const h = req.headers[n];
868
- return Array.isArray(h) ? h[0] : h;
869
- };
870
- const proof = verifyDirectDoorProof({ jwt: hdr(PRINCIPAL_TOKEN_HEADER), mac: hdr(APPROVAL_MAC_HEADER), kid: hdr(APPROVAL_MAC_KID_HEADER) }, buildApprovalEnvelope(sessionId, DECIDE_PROOF_COVERED_KEYS, {
869
+ const proof = admitDirectDoorDecider(req, res, buildApprovalEnvelope(sessionId, DECIDE_PROOF_COVERED_KEYS, {
871
870
  answer: answerProjection,
872
871
  boundCallId: binding.boundCallId,
873
872
  boundInputHash: binding.boundInputHash,
874
873
  decision,
874
+ persistRule: ruleProjection,
875
875
  reason: typeof body.reason === "string" ? body.reason : null,
876
- }), deps.config);
877
- if (!proof.ok) {
878
- sendError(res, proof.status, proof.errorCode, proof.error);
876
+ }), deps.config, match.decl.power);
877
+ if (proof === undefined)
879
878
  return;
880
- }
881
879
  deciderPrincipal = proof.principal;
882
880
  }
883
- const deciderCaller = { subject: deciderSubjectOf(principal, deciderPrincipal), operator: explicitOperatorOk(deciderPrincipal, deps.config) };
881
+ const deciderCaller = { subject: deciderSubjectOf(principal, deciderPrincipal), operator: explicitOperatorOk(deciderPrincipal, deps.config, "operate") };
884
882
  if (!deciderCaller.operator) {
885
883
  const cpScope = await cs
886
884
  .peekPendingScope(sessionId, { gateKinds: APPROVAL_GATE_KINDS })
@@ -890,7 +888,8 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
890
888
  return;
891
889
  }
892
890
  }
893
- const out = await resumeCheckpoint(sessionId, decision, body.reason ?? undefined, hostDecisionFacts(decider, deciderPrincipal), req, answer, binding, remember ? { grantedBy: deciderPrincipal ?? null, laneCannotRecord: "refuse" } : undefined, true, deciderCaller, restated.restatement);
891
+ const persistRule = ruleProjection !== undefined ? { slot: persistRuleFromProjection(ruleProjection), inputWasEdited: binding.updatedInput !== undefined } : undefined;
892
+ const out = await resumeCheckpoint(sessionId, decision, body.reason ?? undefined, hostDecisionFacts(decider, deciderPrincipal), req, answer, binding, remember ? { grantedBy: deciderPrincipal ?? null, laneCannotRecord: "refuse" } : undefined, true, deciderCaller, restated.restatement, persistRule);
894
893
  const replay = await decideIdempotentReplay(cs, {
895
894
  sessionId,
896
895
  out,
@@ -909,12 +908,31 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
909
908
  sendResumeOutcome(res, replay, deps.logger);
910
909
  return;
911
910
  }
912
- sendResumeOutcome(res, out, deps.logger, remember ? { rememberApplied: out.rememberApplied === true } : undefined);
911
+ const rule = out.status >= 200 && out.status < 300 ? ruleReceiptOf(out, persistRule) : undefined;
912
+ const extra = { ...(remember ? { rememberApplied: out.rememberApplied === true } : {}), ...(rule ?? {}) };
913
+ sendResumeOutcome(res, out, deps.logger, Object.keys(extra).length > 0 ? extra : undefined);
913
914
  return;
914
915
  }
915
916
  }
916
917
  return assertNever(match.decl.id);
917
918
  }
919
+ function admitDirectDoorDecider(req, res, envelope, config, power, opts) {
920
+ const hdr = (n) => {
921
+ const h = req.headers[n];
922
+ return Array.isArray(h) ? h[0] : h;
923
+ };
924
+ const proof = verifyDirectDoorProof({ jwt: hdr(PRINCIPAL_TOKEN_HEADER), mac: hdr(APPROVAL_MAC_HEADER), kid: hdr(APPROVAL_MAC_KID_HEADER) }, envelope, config, opts);
925
+ if (!proof.ok) {
926
+ sendError(res, proof.status, proof.errorCode, proof.error);
927
+ return undefined;
928
+ }
929
+ const confined = confinedTierOf(proof.principal, config, power);
930
+ if (confined !== undefined) {
931
+ sendPrincipalConfined(res, confined);
932
+ return undefined;
933
+ }
934
+ return proof;
935
+ }
918
936
  async function decidePeerInbound(req, res, id, env) {
919
937
  const body = (await env.readJson(req));
920
938
  const decision = body?.decision === "approve" ? "approve" : body?.decision === "deny" ? "deny" : undefined;
@@ -937,19 +955,13 @@ async function decidePeerInbound(req, res, id, env) {
937
955
  }
938
956
  let decider = env.principal;
939
957
  if (env.config.directDoorActive) {
940
- const hdr = (n) => {
941
- const h = req.headers[n];
942
- return Array.isArray(h) ? h[0] : h;
943
- };
944
- const proof = verifyDirectDoorProof({ jwt: hdr(PRINCIPAL_TOKEN_HEADER), mac: hdr(APPROVAL_MAC_HEADER), kid: hdr(APPROVAL_MAC_KID_HEADER) }, buildApprovalEnvelope(id, DECIDE_PROOF_COVERED_KEYS, { answer: undefined, boundCallId: undefined, boundInputHash: undefined, decision, reason: null }), env.config);
945
- if (!proof.ok) {
946
- sendError(res, proof.status, proof.errorCode, proof.error);
958
+ const proof = admitDirectDoorDecider(req, res, buildApprovalEnvelope(id, DECIDE_PROOF_COVERED_KEYS, { answer: undefined, boundCallId: undefined, boundInputHash: undefined, decision, persistRule: undefined, reason: null }), env.config, env.power);
959
+ if (proof === undefined)
947
960
  return;
948
- }
949
961
  decider = proof.principal;
950
962
  }
951
963
  const coord = parsePeerInboundId(id);
952
- const outcome = coord === undefined ? { kind: "not_found" } : await env.face.decide(peerBoxScope(decider), coord, decision);
964
+ const outcome = coord === undefined ? { kind: "not_found" } : await env.face.decide(engineScopeOfOwner(decider), coord, decision);
953
965
  switch (outcome.kind) {
954
966
  case "not_found":
955
967
  sendError(res, 404, "not_found.approval", "approval not found");
@@ -1016,7 +1028,7 @@ function redactPendingDisclosures(row) {
1016
1028
  function peerInboundRowsFor(face, principal, operatorOwnerParam) {
1017
1029
  if (operatorOwnerParam !== undefined && operatorOwnerParam !== principal)
1018
1030
  return () => [];
1019
- const scope = peerBoxScope(principal);
1031
+ const scope = engineScopeOfOwner(principal);
1020
1032
  return () => face.list(scope);
1021
1033
  }
1022
1034
  function projectPendingForWire(row, deployment, agent) {
@@ -1034,9 +1046,45 @@ function projectPendingForWire(row, deployment, agent) {
1034
1046
  });
1035
1047
  return { kind: "checkpoint", ...redacted, ...(governanceForced ? { governanceForced } : {}), ...(rememberRefused ? { rememberRefused: true } : {}), ...(agent !== undefined ? { agent } : {}) };
1036
1048
  }
1037
- async function projectDurableQueue(rows, deployment, sessions) {
1049
+ async function projectDurableQueue(rows, deployment, sessions, cards) {
1038
1050
  const agents = await sessionAgentsOf(rows.map((r) => r.sessionId), sessions);
1039
- return rows.map((r) => projectPendingForWire(r, deployment, agents.get(r.sessionId)));
1051
+ const carded = await Promise.all(rows.map((r) => withCardRecord(r, cards)));
1052
+ return carded.map((r) => projectPendingForWire(r, deployment, agents.get(r.sessionId)));
1053
+ }
1054
+ const queueLogger = createLogger();
1055
+ async function withCardRecord(row, cards) {
1056
+ if (cards === undefined || row.toolCallId === null || row.boundInputHash === undefined)
1057
+ return row;
1058
+ const asked = await cards.readParkedAskOfGate(row.sessionId, { boundCallId: row.toolCallId, boundInputHash: row.boundInputHash });
1059
+ const withOffers = (ruleOffers) => {
1060
+ const next = { ...row };
1061
+ if (ruleOffers === undefined)
1062
+ delete next.ruleOffers;
1063
+ else
1064
+ next.ruleOffers = ruleOffers;
1065
+ return next;
1066
+ };
1067
+ const withAskIdentity = (next, ask) => {
1068
+ if (next.taskId !== null && next.taskId !== ask.taskId) {
1069
+ queueLogger.warn("approval queue row: the parked leg's task differs from the ask's task — the row keeps its checkpoint identity", { sessionId: row.sessionId, askId: ask.askId });
1070
+ return next;
1071
+ }
1072
+ return { ...next, taskId: ask.taskId, askId: ask.askId };
1073
+ };
1074
+ switch (asked.kind) {
1075
+ case "none":
1076
+ return row;
1077
+ case "unreadable":
1078
+ return withOffers(undefined);
1079
+ case "row": {
1080
+ const offers = cardRuleOffersOfAskRow(asked.row);
1081
+ return withAskIdentity(withOffers(offers === undefined ? undefined : displayRuleOffers(offers, { countRedactions: false })), asked.row);
1082
+ }
1083
+ default: {
1084
+ const unhandled = asked;
1085
+ throw new Error(`queue projection: unhandled parked-ask reading ${JSON.stringify(unhandled)}`);
1086
+ }
1087
+ }
1040
1088
  }
1041
1089
  async function sessionAgentsOf(sessionIds, sessions) {
1042
1090
  const out = new Map();
@@ -1121,7 +1169,7 @@ export async function streamApprovals(req, res, cs, live, peerInbound, sessions,
1121
1169
  while (!closed) {
1122
1170
  let snapshot;
1123
1171
  try {
1124
- const pending = [...(await projectDurableQueue(await cs.listPending(scope), governance, sessions)), ...(peerInbound?.() ?? [])];
1172
+ const pending = [...(await projectDurableQueue(await cs.listPending(scope), governance, sessions, live)), ...(peerInbound?.() ?? [])];
1125
1173
  snapshot = { pending, livePending: live ? await live.listLivePending(scope) : [] };
1126
1174
  }
1127
1175
  catch (err) {
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * ── 读口:逐字投 core `list()` 行 ─────────────────────────────────────────────────────────────────
11
11
  * 读的是**进程内**注册表(`defaultTaskRegistry.list`),访问元组 = 会话自己的 `{ owner: sid, sessionId: sid, scope }`
12
- * (scope = 会话行属主 `owner ?? "default"`,与 core 注册铸值同源)⇒ 可见集完全由 core 的 `canAccess` 判(fail-closed:
12
+ * (scope = 会话的引擎租户分区 `sessionTenantScope`,经唯一换算 `engineScopeOfOwner`,与 core 注册铸值同源)⇒ 可见集完全由 core 的 `canAccess` 判(fail-closed:
13
13
  * 缺轴即拒;本会话的会话驻留行、task id 即会话 id 的 run 行、本会话发起的 workflow、根会话是本会话的后台 agent)。
14
14
  * 键逐个处置(下面的 {@link ROW_KEY_DISPOSITION},core 给行加键 ⇒ 编译红):`task_id` 改名 `id`;`retained` **真才带**
15
15
  * (core:缺席 ⇒ 这一行在 `includeRetained:false` 的硬面上会停);`description` 是模型写的描述、缺席时是启动时的命令文本 ——
@@ -40,8 +40,8 @@
40
40
  *
41
41
  * 🔴 **停止口在无凭据写门内**(`credentialGated: ["POST"]`;车OL F1 = 7.102.0 合并复审 gpt-6 腿 [high]):门的两个合取项它都中
42
42
  * —— ① 授权的唯一输入是 principal 头(属主判 `admitSessionRow` 与 operator 臂 `explicitOperatorOk` 读的都是 `gatedSubject`,
43
- * 无 service 凭证的部署上它收调用方自报的头);② 不可撤销、爆炸半径跨租户(知道会话 id + 自报它的属主 ⇒ 停掉那个会话的后台
44
- * 进程,`includeRetained:true` 连显式 retain 的活服务一起停)。于是无 service 凭证且未开 `ALLOW_UNAUTHED_WRITES` 的部署上它与
43
+ * 没带过门凭据的请求上它收调用方自报的头);② 不可撤销、爆炸半径跨租户(知道会话 id + 自报它的属主 ⇒ 停掉那个会话的后台
44
+ * 进程,`includeRetained:true` 连显式 retain 的活服务一起停)。于是无 service 凭证且未开 `ALLOW_UNAUTHED_WRITES` 的部署上,不带过门凭据的请求打它与
45
45
  * 其余改写门同码同句 503 `auth.service_token_required`(在路由之前,`dispatch.ts` 那一道),同一只会话级收敛函数的另一个调用点
46
46
  * `DELETE /v1/sessions/:id` 早在同一形下被 `isDestructiveSessionWrite` 拒。读口 `GET …/background` 不进:它有属主门兜底、只读、
47
47
  * 只列本会话,与 `GET /v1/rules` 同判。已知同族缺口(不在本口单独打补丁):能力位 `exitFaces` 不含「凭据就绪」这一项,见契约
@@ -38,6 +38,10 @@ export declare const CAPABILITIES_ROUTES: readonly [{
38
38
  readonly id: "capability-mcp";
39
39
  readonly path: "/v1/capabilities/mcp";
40
40
  readonly methods: readonly ["GET"];
41
+ }, {
42
+ readonly id: "capability-scenario-effective";
43
+ readonly path: "/v1/capabilities/scenario";
44
+ readonly methods: readonly ["GET"];
41
45
  }, {
42
46
  readonly id: "capability-mcp-probe";
43
47
  readonly path: "/v1/capabilities/mcp/probe";
@@ -19,7 +19,7 @@ import { sendJson, sendError } from "../send.js";
19
19
  import { codeFieldOf } from "../../terminal.js";
20
20
  import { engineRefusalAnswerOf } from "../engine-refusal.js";
21
21
  import { assertNever } from "../route-ctx.js";
22
- import { fileHistoryCaptureOf } from "../../file-history-capture.js";
22
+ import { fileHistoryCaptureOf, fileHistoryWired } from "../../file-history-capture.js";
23
23
  import { projectMemoryEngineCapability } from "../../memory-posture.js";
24
24
  import { projectWriteProtectionCapability } from "../../write-protection.js";
25
25
  import { projectStoreCapability, unwiredStorePosture } from "../../store-posture.js";
@@ -27,6 +27,7 @@ import { projectWebSearchCapability } from "../../plugins/web-search.js";
27
27
  import { projectExecutionLaneCapability } from "../../capabilities/execution-lane.js";
28
28
  import { SETTINGS_CONTRACT_CAPABILITY } from "../../capabilities/settings-contract.js";
29
29
  import { judgeSandboxGitPlane, sandboxGitPlanePremisesOf } from "../../sandbox-git-plane.js";
30
+ import { SESSION_KINDS } from "../../session-kind.js";
30
31
  import { MCP_ASSERTION_HEADER_SENT, MCP_REQUEST_TRANSPORT_KINDS } from "../../mcp-assertion-header.js";
31
32
  import { gateCompositeMembers } from "../../capabilities/composite-members.js";
32
33
  import { projectApprovalsStreamLiveCapability } from "../../capabilities/approvals-push.js";
@@ -35,7 +36,8 @@ import { centerEntitlementSourceWired } from "../../runtime-caps-resolver.js";
35
36
  import * as facts from "../../capability-facts.js";
36
37
  import { judgeAutoModeArming } from "../../auto-mode-face.js";
37
38
  import { coercePermissionModeStrict, PERMISSION_MODE_WORDS, taskHooksHonored } from "../../task-settings.js";
38
- import { gatedPerson, sendPrincipalRefusal } from "../principal-gate.js";
39
+ import { gatedPerson, gatedSubject, sendPrincipalRefusal } from "../principal-gate.js";
40
+ import { scenarioRequestedBySubject } from "../../request-form.js";
39
41
  import { readAdoptionImportCapability } from "../../adoption/import.js";
40
42
  import { headReadPresent } from "../../session-incarnation.js";
41
43
  import { callerTrust } from "../caller-trust.js";
@@ -56,6 +58,12 @@ function retentionAdvertisement(config) {
56
58
  export function createCapabilitiesLocal() {
57
59
  return { mcpProbe: createMcpProbeLocal() };
58
60
  }
61
+ const QUERY_SCENARIO_REPEATED = Symbol("scenario query given more than once");
62
+ const SCENARIO_QUERY_REPEATED_REFUSAL = "scenario must be given at most once (omit it to read this deployment's default scenario)";
63
+ function scenarioQueryOf(search) {
64
+ const given = new URLSearchParams(search).getAll("scenario");
65
+ return given.length > 1 ? QUERY_SCENARIO_REPEATED : given[0];
66
+ }
59
67
  export async function handleCapabilities(req, res, match, ctx) {
60
68
  const { deps } = ctx;
61
69
  switch (match.decl.id) {
@@ -84,6 +92,7 @@ export async function handleCapabilities(req, res, match, ctx) {
84
92
  deps.logger?.warn("auto_mode_face_resolver_fault", { fault: autoModeFault });
85
93
  const rulesLaneForCaller = facts.ruleLaneForCaller(deps, gatedPerson(req, deps.config)).available;
86
94
  const streamApprovalFact = facts.streamApproval(deps);
95
+ const historyWired = fileHistoryWired(deps.backend);
87
96
  sendJson(res, 200, gateCompositeMembers({
88
97
  ...deps.capabilities,
89
98
  ...facts.engineCapabilityBits(),
@@ -138,6 +147,7 @@ export async function handleCapabilities(req, res, match, ctx) {
138
147
  permissionRulesRevoke: facts.ruleLane(deps).available,
139
148
  respondFreeFormRules: true,
140
149
  respondBatchRuleOffers: true,
150
+ approvalDecideRuleSlot: true,
141
151
  oneShot: true,
142
152
  policy: true,
143
153
  usage: Boolean(deps.costQuota),
@@ -211,19 +221,21 @@ export async function handleCapabilities(req, res, match, ctx) {
211
221
  retention: retentionAdvertisement(deps.config),
212
222
  peerLane: Boolean(deps.peerDirectory),
213
223
  scenarioSubject: true,
224
+ effectiveScenario: true,
214
225
  sessionList: facts.sessionList(deps).available,
215
226
  sessionSearch: facts.sessionList(deps).available,
227
+ sessionKinds: facts.sessionKinds(deps).available ? [...SESSION_KINDS] : [],
216
228
  sessionFork: facts.sessionFork(deps).available,
217
229
  sessionDelete: facts.sessionDelete(deps).available,
218
- resumeAt: Boolean(deps.resumeAnchorStore && headReadPresent(deps.sessionStorage)),
230
+ resumeAt: deps.backend !== undefined && headReadPresent(deps.sessionStorage),
219
231
  promptSuggestions: true,
220
232
  sessionPolicy: facts.sessionPolicy(deps).available,
221
233
  sessionRulesNamespaceForms: sessionRulesNamespaceFormsHonored(),
222
- restoreFiles: Boolean(deps.fileHistoryStore),
223
- rewindFilesTo: Boolean(deps.fileHistoryStore && deps.resumeAnchorStore && headReadPresent(deps.sessionStorage)),
234
+ restoreFiles: historyWired,
235
+ rewindFilesTo: historyWired && headReadPresent(deps.sessionStorage),
224
236
  sessionRewindFiles: facts.sessionRewindFiles(deps).available,
225
237
  sessionRewindFilesPreview: facts.sessionRewindFilesPreview(deps).available,
226
- fileHistoryCapture: fileHistoryCaptureOf(deps.fileHistoryStore, deps.config.fileHistoryCapture),
238
+ fileHistoryCapture: fileHistoryCaptureOf(historyWired, deps.config.fileHistoryCapture),
227
239
  scheduler: facts.hostScheduler(deps.config).available,
228
240
  sessionSync: facts.sessionSync(deps).available,
229
241
  sessionSyncFileHistory: facts.sessionSyncFileHistory(deps).available,
@@ -260,15 +272,30 @@ export async function handleCapabilities(req, res, match, ctx) {
260
272
  sendPrincipalRefusal(res, req, deps.config);
261
273
  return;
262
274
  }
263
- const scenarioParams = new URLSearchParams(match.search).getAll("scenario");
264
- if (scenarioParams.length > 1) {
265
- sendError(res, 400, "request.field_invalid", "scenario must be given at most once (omit it to read this deployment's default scenario)");
275
+ const named = scenarioQueryOf(match.search);
276
+ if (named === QUERY_SCENARIO_REPEATED) {
277
+ sendError(res, 400, "request.field_invalid", SCENARIO_QUERY_REPEATED_REFUSAL);
266
278
  return;
267
279
  }
268
- const scenarioName = await deps.scenarioGate(principal, scenarioParams[0]);
280
+ const { scenario: scenarioName } = await deps.scenarioGate(principal, scenarioRequestedBySubject(gatedSubject(req, deps.config), named));
269
281
  await serveMcpProbeFace(res, ctx, principal, { declaredBy: "deployment", specs: mcpForScenario(deps.config.mcpServers, scenarioName) ?? [] });
270
282
  return;
271
283
  }
284
+ case "capability-scenario-effective": {
285
+ const principal = gatedPerson(req, deps.config);
286
+ if (deps.config.requirePrincipal && !principal) {
287
+ sendPrincipalRefusal(res, req, deps.config);
288
+ return;
289
+ }
290
+ const named = scenarioQueryOf(match.search);
291
+ if (named === QUERY_SCENARIO_REPEATED) {
292
+ sendError(res, 400, "request.field_invalid", SCENARIO_QUERY_REPEATED_REFUSAL);
293
+ return;
294
+ }
295
+ const choice = await deps.scenarioGate(principal, scenarioRequestedBySubject(gatedSubject(req, deps.config), named));
296
+ sendJson(res, 200, { scenario: choice.scenario, source: choice.source });
297
+ return;
298
+ }
272
299
  case "capability-mcp-probe": {
273
300
  const principal = gatedPerson(req, deps.config);
274
301
  if (deps.config.requirePrincipal && !principal) {
@@ -398,6 +425,7 @@ export const CAPABILITIES_ROUTES = [
398
425
  { id: "capabilities", path: "/v1/capabilities", methods: ["GET"] },
399
426
  { id: "capability-scenario", pattern: /^\/v1\/capabilities\/scenarios\/(?<name>.*)$/, label: "/v1/capabilities/scenarios/:name", methods: ["GET"] },
400
427
  { id: "capability-mcp", path: "/v1/capabilities/mcp", methods: ["GET"] },
428
+ { id: "capability-scenario-effective", path: "/v1/capabilities/scenario", methods: ["GET"] },
401
429
  { id: "capability-mcp-probe", path: "/v1/capabilities/mcp/probe", methods: ["POST"] },
402
430
  ];
403
431
  //# sourceMappingURL=capabilities.js.map
@@ -23,13 +23,13 @@ export async function handleConfigCatalog(req, res, match, ctx) {
23
23
  sendError(res, 501, "feature.config_catalog_disabled", "the config catalog is switched off on this deployment (CONFIG_CATALOG_ENABLED=false)");
24
24
  return;
25
25
  case "operator_principals_empty":
26
- sendOperatorPrincipalsRequired(res);
26
+ sendOperatorPrincipalsRequired(res, "operate");
27
27
  return;
28
28
  default:
29
29
  return assertNever(fact.why);
30
30
  }
31
31
  }
32
- if (!explicitOperatorOk(principal, deps.config)) {
32
+ if (!explicitOperatorOk(principal, deps.config, "operate")) {
33
33
  sendError(res, 403, "auth.operator_only", OPERATOR_ONLY_MESSAGE);
34
34
  return;
35
35
  }
@@ -144,7 +144,7 @@ export async function handleDevices(req, res, match, ctx) {
144
144
  }
145
145
  }
146
146
  const { store, hub, enrollment, runStore } = lane;
147
- const operator = explicitOperatorOk(principal, deps.config);
147
+ const operator = explicitOperatorOk(principal, deps.config, "operate");
148
148
  const domain = deviceOwnerDomainOf(req, deps.config);
149
149
  if (match.decl.id === "devices-list") {
150
150
  if (!operator && domain === undefined) {
@@ -42,7 +42,6 @@ export interface ServerWiringGates {
42
42
  * 不再是装配现场的事实,而是别处算完可能已漂的复述)。 */
43
43
  export interface ServerWiringGateInput {
44
44
  toolApprovalEnabled: boolean;
45
- streamApprovalEnabled: boolean;
46
45
  /** 谓词自己的入参类型(结构形,不 import store 依赖树)—— 取型而非重述,两处不可能漂。 */
47
46
  backend: StreamApprovalGateInput["backend"];
48
47
  /** 谓词自己的入参类型(只收店的形,工厂方法过不了 tsc)—— 取型而非重述,与 `backend` 同理;在场性即事实,本面不读实例的内容。 */
@@ -116,8 +115,9 @@ export declare function assertStaticWiringConsistent(facts: StaticWiringFacts, l
116
115
  * 字符串,端口误暴露到公网就是侦察面(装配拓扑 / 治理姿态 / 写保护名表)。配了 service 凭据的部署上,到得了这里的请求都过了全局凭据门、
117
116
  * 必然带着验过的身份,本判不咬;不要求静态凭据在场(鉴权桥的登录令牌就是身份)。
118
117
  *
119
- * 判源 = TCP 对端地址(`req.socket.remoteAddress`),**非任何头**(XFF 类头在无反代形上是自造面;有反代的部署必然配凭据)。
120
- * `remoteAddress` 缺席(socket 已断等边缘)⇒ 判拒(fail-closed)。
118
+ * 「本机」按请求通道穷举(`request-channel.ts`;加一种通道不接 ⇒ 编译红):经本机控制 socket 来的请求 = 本机(能连上它的只有引擎的 OS 用户 —— 与 `/health` 把它认作
119
+ * 本机用户同读,同一只请求不被一面认作本机、另一面认作远程);经 TCP 来的请求判源 = TCP 对端地址(`req.socket.remoteAddress`),**非任何头**(XFF 类头在无反代形上是自造面;
120
+ * 有反代的部署必然配凭据)。`remoteAddress` 缺席(socket 已断等边缘)⇒ 判拒(fail-closed)。
121
121
  */
122
122
  export declare function remoteWithoutVerifiedIdentity(req: IncomingMessage, config: Parameters<typeof verifiedIdentitySource>[1]): boolean;
123
123
  export declare function handleDiagnostics(req: IncomingMessage, res: ServerResponse, match: RouteMatch<DiagnosticsRouteId>, ctx: RouteCtx): Promise<void>;
@@ -5,6 +5,7 @@ import { readOutboundWiring } from "../../outbound-dispatcher.js";
5
5
  import { resolveStreamApprovalGate } from "../../tool-approval.js";
6
6
  import { sendJson, sendError } from "../send.js";
7
7
  import { gatedPerson, explicitOperatorOk, isLoopbackAddress, sendOperatorPrincipalsRequired, verifiedIdentitySource } from "../principal-gate.js";
8
+ import { requestChannelOf } from "../request-channel.js";
8
9
  import * as facts from "../../capability-facts.js";
9
10
  import { assertNever } from "../route-ctx.js";
10
11
  import { STORE_NOT_DURABLE_CODE, StoreNotDurableError, describeStoreRoot, projectStoreDurabilityWiring, unwiredStorePosture } from "../../store-posture.js";
@@ -12,7 +13,6 @@ import { describeLocalStoreDeclaration } from "../../local-store-declaration.js"
12
13
  export function buildServerWiringGates(input) {
13
14
  const gate = resolveStreamApprovalGate({
14
15
  toolApprovalEnabled: input.toolApprovalEnabled,
15
- streamApprovalEnabled: input.streamApprovalEnabled,
16
16
  backend: input.backend,
17
17
  checkpointStore: input.checkpointStore,
18
18
  });
@@ -126,17 +126,30 @@ export function assertStaticWiringConsistent(facts, logger) {
126
126
  return audit;
127
127
  }
128
128
  export function remoteWithoutVerifiedIdentity(req, config) {
129
- return !isLoopbackAddress(req.socket.remoteAddress) && verifiedIdentitySource(req, config) === undefined;
129
+ return !requestFromThisHost(req) && verifiedIdentitySource(req, config) === undefined;
130
+ }
131
+ function requestFromThisHost(req) {
132
+ const channel = requestChannelOf(req);
133
+ switch (channel) {
134
+ case "tcp":
135
+ return isLoopbackAddress(req.socket.remoteAddress);
136
+ case "control-socket":
137
+ return true;
138
+ default: {
139
+ const unknownChannel = channel;
140
+ throw new Error(`diagnostics: request channel ${String(unknownChannel)} has no locality reading`);
141
+ }
142
+ }
130
143
  }
131
144
  export async function handleDiagnostics(req, res, match, ctx) {
132
145
  const { deps } = ctx;
133
146
  switch (match.decl.id) {
134
147
  case "diagnostics-wiring": {
135
- if (!facts.operatorLane(deps).available) {
136
- sendOperatorPrincipalsRequired(res);
148
+ if (!facts.operatorLane(deps, "operate").available) {
149
+ sendOperatorPrincipalsRequired(res, "operate");
137
150
  return;
138
151
  }
139
- if (!explicitOperatorOk(gatedPerson(req, deps.config), deps.config)) {
152
+ if (!explicitOperatorOk(gatedPerson(req, deps.config), deps.config, "operate")) {
140
153
  sendError(res, 403, "auth.operator_only", "wiring diagnostics are operator-only");
141
154
  return;
142
155
  }
@@ -156,8 +169,7 @@ export async function handleDiagnostics(req, res, match, ctx) {
156
169
  configApply: deps.configApplyState?.() ?? null,
157
170
  mcpRevocations: deps.mcpRevocationState?.() ?? null,
158
171
  serverGates: buildServerWiringGates({
159
- toolApprovalEnabled: deps.toolApproval !== undefined,
160
- streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
172
+ toolApprovalEnabled: deps.config.toolApprovalEnabled === true,
161
173
  backend: deps.backend,
162
174
  checkpointStore: deps.checkpointStore,
163
175
  durableApproval: deps.config.durableApproval === true,