@sema-agent/server 7.132.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 (402) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +174 -55
  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 +79 -19
  24. package/dist/approval-card.js +44 -13
  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 +27 -10
  29. package/dist/audit.js +12 -16
  30. package/dist/bake-runner/main.js +3 -2
  31. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  32. package/dist/boot/execution-env.js +9 -7
  33. package/dist/boot/execution-lane.js +11 -0
  34. package/dist/boot/leader.js +2 -0
  35. package/dist/boot/memory-boundary.js +2 -2
  36. package/dist/boot/memory-consolidation.d.ts +5 -4
  37. package/dist/boot/memory-consolidation.js +7 -6
  38. package/dist/boot/org-delivery.d.ts +28 -0
  39. package/dist/boot/org-delivery.js +20 -0
  40. package/dist/boot/reapers.d.ts +3 -0
  41. package/dist/boot/reapers.js +21 -1
  42. package/dist/boot/resolve-spec.d.ts +3 -0
  43. package/dist/boot/resolve-spec.js +60 -81
  44. package/dist/boot/runner-deps.js +1 -0
  45. package/dist/boot/session-faces.d.ts +1 -0
  46. package/dist/boot/session-faces.js +4 -2
  47. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  48. package/dist/boot/stage-06-runners.d.ts +2 -0
  49. package/dist/boot/stage-06-runners.js +6 -3
  50. package/dist/boot/stage-07-capability-layer.d.ts +2 -0
  51. package/dist/boot/stage-07-capability-layer.js +24 -3
  52. package/dist/boot/stage-08-reapers.d.ts +2 -0
  53. package/dist/boot/stage-08-reapers.js +2 -2
  54. package/dist/boot/stage-09-leader.d.ts +3 -0
  55. package/dist/boot/stage-10-http-server.d.ts +3 -0
  56. package/dist/boot/stage-10-http-server.js +5 -6
  57. package/dist/boot/stores.js +2 -2
  58. package/dist/boot/web-admin.d.ts +4 -0
  59. package/dist/boot/web-admin.js +151 -63
  60. package/dist/boot/workflow-orchestration.d.ts +2 -0
  61. package/dist/boot/workflow-orchestration.js +2 -1
  62. package/dist/brain.js +8 -3
  63. package/dist/breaker-key.d.ts +6 -0
  64. package/dist/breaker-key.js +29 -0
  65. package/dist/caller-text-echo.d.ts +9 -6
  66. package/dist/caller-text-echo.js +8 -11
  67. package/dist/capabilities/center-plugins.d.ts +7 -0
  68. package/dist/capabilities/center-plugins.js +1 -1
  69. package/dist/capabilities/composite-members.d.ts +1 -1
  70. package/dist/capabilities/composite-members.js +1 -1
  71. package/dist/capabilities/execution-lane.js +2 -2
  72. package/dist/capabilities/hands-lane.d.ts +21 -0
  73. package/dist/capabilities/hands-lane.js +10 -0
  74. package/dist/capabilities/mcp-probe.d.ts +36 -4
  75. package/dist/capabilities/mcp-probe.js +27 -4
  76. package/dist/capabilities/scenarios.d.ts +63 -7
  77. package/dist/capabilities/scenarios.js +39 -7
  78. package/dist/capability-facts.d.ts +34 -4
  79. package/dist/capability-facts.js +28 -2
  80. package/dist/center-config-tier.d.ts +69 -0
  81. package/dist/center-config-tier.js +42 -0
  82. package/dist/checkpoint-identity.d.ts +16 -0
  83. package/dist/checkpoint-identity.js +19 -0
  84. package/dist/config-catalog.d.ts +17 -10
  85. package/dist/config-catalog.js +43 -28
  86. package/dist/config-d-migration.d.ts +3 -1
  87. package/dist/config-d-migration.js +2 -2
  88. package/dist/config-dir-trust.d.ts +114 -0
  89. package/dist/config-dir-trust.js +388 -0
  90. package/dist/config-invariants.d.ts +18 -5
  91. package/dist/config-invariants.js +35 -3
  92. package/dist/config-provider.d.ts +6 -1
  93. package/dist/config-provider.js +6 -2
  94. package/dist/config-types.d.ts +71 -14
  95. package/dist/config-types.js +8 -0
  96. package/dist/config.d.ts +13 -0
  97. package/dist/config.js +121 -59
  98. package/dist/delegated-session-owner.d.ts +185 -0
  99. package/dist/delegated-session-owner.js +119 -0
  100. package/dist/device-protocol.d.ts +5 -3
  101. package/dist/device-protocol.js +1 -1
  102. package/dist/device-ws-hub.js +21 -2
  103. package/dist/device-ws-protocol.d.ts +70 -6
  104. package/dist/device-ws-protocol.js +50 -23
  105. package/dist/elicitation.js +3 -2
  106. package/dist/entry-problems.d.ts +34 -0
  107. package/dist/entry-problems.js +14 -0
  108. package/dist/execution-lane-caps.d.ts +49 -10
  109. package/dist/execution-lane-caps.js +43 -4
  110. package/dist/field-conflict.d.ts +43 -0
  111. package/dist/field-conflict.js +20 -0
  112. package/dist/fleet/fleet-bus.d.ts +80 -6
  113. package/dist/fleet/fleet-bus.js +41 -9
  114. package/dist/hooks/classic-stations.d.ts +10 -5
  115. package/dist/hooks/classic-stations.js +4 -4
  116. package/dist/hooks/command-spawn.d.ts +57 -0
  117. package/dist/hooks/command-spawn.js +139 -0
  118. package/dist/hooks/hook-llm.js +2 -2
  119. package/dist/hooks/hook-runner.d.ts +127 -25
  120. package/dist/hooks/hook-runner.js +668 -287
  121. package/dist/hooks/hook-source.d.ts +44 -0
  122. package/dist/hooks/hook-source.js +40 -0
  123. package/dist/http/active-run-conflict.d.ts +5 -13
  124. package/dist/http/active-run-conflict.js +17 -27
  125. package/dist/http/admission.js +103 -60
  126. package/dist/http/approval-sweeps.js +55 -18
  127. package/dist/http/caller-trust.d.ts +77 -0
  128. package/dist/http/caller-trust.js +143 -0
  129. package/dist/http/checkpoint-ctx.d.ts +16 -16
  130. package/dist/http/checkpoint-ctx.js +13 -10
  131. package/dist/http/claimed-run.d.ts +4 -3
  132. package/dist/http/device-placement.d.ts +2 -4
  133. package/dist/http/device-placement.js +2 -1
  134. package/dist/http/dispatch.js +10 -4
  135. package/dist/http/durable-run-leg.d.ts +4 -32
  136. package/dist/http/durable-run-leg.js +34 -10
  137. package/dist/http/owner-access.d.ts +56 -0
  138. package/dist/http/owner-access.js +42 -0
  139. package/dist/http/principal-gate.d.ts +48 -23
  140. package/dist/http/principal-gate.js +39 -12
  141. package/dist/http/readiness.d.ts +11 -5
  142. package/dist/http/readiness.js +10 -3
  143. package/dist/http/request-guards.d.ts +16 -23
  144. package/dist/http/request-guards.js +30 -15
  145. package/dist/http/resume-ctx-read.d.ts +2 -5
  146. package/dist/http/resume-ctx-read.js +7 -4
  147. package/dist/http/resume-legs.d.ts +3 -4
  148. package/dist/http/resume-legs.js +126 -69
  149. package/dist/http/retired-service-deps.d.ts +43 -0
  150. package/dist/http/retired-service-deps.js +18 -0
  151. package/dist/http/route-ctx.d.ts +44 -28
  152. package/dist/http/route-ctx.js +4 -0
  153. package/dist/http/route-table.js +2 -0
  154. package/dist/http/routes/a2a-serve.js +3 -4
  155. package/dist/http/routes/admin-config-refresh.js +1 -1
  156. package/dist/http/routes/admin-drain.js +1 -1
  157. package/dist/http/routes/admin-memory-optout.js +5 -1
  158. package/dist/http/routes/adoption.js +2 -9
  159. package/dist/http/routes/approvals-assistant.js +49 -48
  160. package/dist/http/routes/background.js +3 -2
  161. package/dist/http/routes/capabilities.js +20 -4
  162. package/dist/http/routes/config-catalog.d.ts +3 -3
  163. package/dist/http/routes/config-catalog.js +1 -1
  164. package/dist/http/routes/devices.js +3 -17
  165. package/dist/http/routes/diagnostics.js +5 -1
  166. package/dist/http/routes/images.js +6 -7
  167. package/dist/http/routes/leader.js +1 -8
  168. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  169. package/dist/http/routes/mcp-reconnect.js +3 -2
  170. package/dist/http/routes/memory-bundle.js +1 -1
  171. package/dist/http/routes/memory-compliance.js +1 -1
  172. package/dist/http/routes/memory-consolidation.js +1 -1
  173. package/dist/http/routes/memory-origin.js +1 -1
  174. package/dist/http/routes/memory-policy.d.ts +1 -1
  175. package/dist/http/routes/memory-policy.js +3 -2
  176. package/dist/http/routes/notify-wake.js +8 -21
  177. package/dist/http/routes/observability.js +2 -2
  178. package/dist/http/routes/principal-inbox.d.ts +39 -0
  179. package/dist/http/routes/principal-inbox.js +76 -0
  180. package/dist/http/routes/retention-ops.js +2 -9
  181. package/dist/http/routes/rules.js +5 -18
  182. package/dist/http/routes/runs.d.ts +5 -0
  183. package/dist/http/routes/runs.js +33 -106
  184. package/dist/http/routes/session-sync.js +15 -28
  185. package/dist/http/routes/sessions.js +30 -40
  186. package/dist/http/routes/side-query.js +6 -4
  187. package/dist/http/routes/tasks.js +50 -14
  188. package/dist/http/routes/workflows.d.ts +351 -0
  189. package/dist/http/routes/workflows.js +153 -119
  190. package/dist/http/send.d.ts +24 -3
  191. package/dist/http/send.js +14 -2
  192. package/dist/http/server.d.ts +17 -18
  193. package/dist/http/server.js +15 -13
  194. package/dist/http/stored-body-replay.js +17 -4
  195. package/dist/http/submit-ctx.js +4 -3
  196. package/dist/http/submit-replay.d.ts +4 -3
  197. package/dist/http/submit-replay.js +5 -4
  198. package/dist/http/wire-types.d.ts +10 -7
  199. package/dist/index.d.ts +1 -1
  200. package/dist/index.js +0 -1
  201. package/dist/lane-home-probe.d.ts +78 -9
  202. package/dist/lane-home-probe.js +78 -12
  203. package/dist/leader/endpoint.d.ts +4 -1
  204. package/dist/leader/endpoint.js +11 -10
  205. package/dist/limit-refusal.d.ts +17 -5
  206. package/dist/limit-refusal.js +4 -1
  207. package/dist/mcp-assertion-header.d.ts +31 -10
  208. package/dist/mcp-assertion-header.js +10 -3
  209. package/dist/mcp-tool-faces.js +1 -3
  210. package/dist/memory-project-layer.d.ts +37 -0
  211. package/dist/memory-project-layer.js +46 -0
  212. package/dist/memory-scope.d.ts +23 -16
  213. package/dist/memory-scope.js +24 -8
  214. package/dist/memory-sync-client.d.ts +27 -13
  215. package/dist/memory-sync-client.js +107 -18
  216. package/dist/model-entry-refusal.d.ts +9 -1
  217. package/dist/model-entry-refusal.js +6 -1
  218. package/dist/model-plane-face.d.ts +51 -0
  219. package/dist/model-plane-face.js +24 -0
  220. package/dist/model-provider.d.ts +5 -0
  221. package/dist/model-provider.js +4 -2
  222. package/dist/model-route-endpoint.d.ts +8 -11
  223. package/dist/model-route-endpoint.js +4 -7
  224. package/dist/model-route-env.d.ts +22 -0
  225. package/dist/model-route-env.js +2 -0
  226. package/dist/model-route-gap.d.ts +60 -30
  227. package/dist/model-route-gap.js +21 -15
  228. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  229. package/dist/observability/corrupt-read-seat.js +9 -0
  230. package/dist/observability/err-text.d.ts +6 -0
  231. package/dist/observability/err-text.js +18 -4
  232. package/dist/observability/fail-open.d.ts +35 -9
  233. package/dist/observability/fail-open.js +35 -9
  234. package/dist/observability/metrics.js +1 -0
  235. package/dist/observability/prompt-manifest.d.ts +3 -17
  236. package/dist/observability/prompt-manifest.js +45 -42
  237. package/dist/observability/tool-trace.js +9 -9
  238. package/dist/operator-ask.d.ts +10 -0
  239. package/dist/operator-ask.js +3 -0
  240. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  241. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  242. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  243. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  244. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  245. package/dist/orchestration/workflow-notify-journal.js +27 -34
  246. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  247. package/dist/orchestration/workflow-park-decision.js +118 -0
  248. package/dist/org-delivery-gate.d.ts +81 -0
  249. package/dist/org-delivery-gate.js +59 -0
  250. package/dist/panel-tool-names.d.ts +23 -0
  251. package/dist/panel-tool-names.js +8 -0
  252. package/dist/parked-decide.d.ts +39 -6
  253. package/dist/parked-decide.js +98 -51
  254. package/dist/parked-revive-surface.d.ts +9 -2
  255. package/dist/parked-revive-surface.js +11 -8
  256. package/dist/permission-rule-list.d.ts +1 -1
  257. package/dist/permission-rule-list.js +2 -2
  258. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  259. package/dist/plugins/approval-ask-store-file.js +21 -0
  260. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  261. package/dist/plugins/approval-ask-store-memory.js +34 -2
  262. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  263. package/dist/plugins/approval-ask-store-sql.js +37 -1
  264. package/dist/plugins/blob-backend.d.ts +38 -25
  265. package/dist/plugins/blob-backend.js +29 -19
  266. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  267. package/dist/plugins/breaker-state-sql.js +4 -4
  268. package/dist/plugins/caching-session-store.d.ts +3 -0
  269. package/dist/plugins/caching-session-store.js +3 -0
  270. package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
  271. package/dist/plugins/checkpoint-store-sql.js +20 -2
  272. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  273. package/dist/plugins/file-history-store-sql.js +3 -1
  274. package/dist/plugins/file-run-store.d.ts +5 -13
  275. package/dist/plugins/file-run-store.js +9 -0
  276. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  277. package/dist/plugins/fork-routing-session-store.js +12 -1
  278. package/dist/plugins/host-platform.d.ts +2 -0
  279. package/dist/plugins/host-platform.js +2 -1
  280. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  281. package/dist/plugins/local-checkpoint-store.js +6 -1
  282. package/dist/plugins/local-session-store.d.ts +1 -1
  283. package/dist/plugins/local-session-window.d.ts +39 -0
  284. package/dist/plugins/local-session-window.js +54 -0
  285. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  286. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  287. package/dist/plugins/mailbox-store-sql.js +77 -52
  288. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  289. package/dist/plugins/memory-run-store.d.ts +5 -13
  290. package/dist/plugins/memory-run-store.js +8 -0
  291. package/dist/plugins/one-time-migrations.d.ts +110 -5
  292. package/dist/plugins/one-time-migrations.js +320 -8
  293. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  294. package/dist/plugins/org-delivery-quota-store.js +228 -0
  295. package/dist/plugins/pg-pool.js +39 -7
  296. package/dist/plugins/pg-session-storage.d.ts +17 -4
  297. package/dist/plugins/pg-session-storage.js +29 -6
  298. package/dist/plugins/remote-env-adb.d.ts +6 -12
  299. package/dist/plugins/remote-env-adb.js +12 -2
  300. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  301. package/dist/plugins/remote-env-k8s.js +23 -5
  302. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  303. package/dist/plugins/remote-env-local-docker.js +12 -9
  304. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  305. package/dist/plugins/remote-env-ssh.js +17 -11
  306. package/dist/plugins/run-store-sql.d.ts +16 -14
  307. package/dist/plugins/run-store-sql.js +22 -2
  308. package/dist/plugins/schema-indexes.js +2 -0
  309. package/dist/plugins/send-user-file.js +2 -2
  310. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  311. package/dist/plugins/session-epoch-anchor.js +2 -3
  312. package/dist/plugins/session-store.d.ts +18 -8
  313. package/dist/plugins/session-store.js +15 -4
  314. package/dist/plugins/sql-driver.d.ts +74 -11
  315. package/dist/plugins/sql-driver.js +210 -12
  316. package/dist/plugins/sql-errors.d.ts +23 -0
  317. package/dist/plugins/sql-errors.js +21 -0
  318. package/dist/plugins/store-backend.d.ts +36 -1
  319. package/dist/plugins/store-backend.js +40 -14
  320. package/dist/plugins/store-contracts.d.ts +42 -0
  321. package/dist/plugins/store-contracts.js +1 -0
  322. package/dist/plugins/tidb-pool.d.ts +6 -1
  323. package/dist/plugins/tidb-pool.js +44 -10
  324. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  325. package/dist/plugins/tidb-session-storage.js +2 -2
  326. package/dist/plugins/tidb-session-store.d.ts +24 -4
  327. package/dist/plugins/tidb-session-store.js +28 -4
  328. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  329. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  330. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  331. package/dist/plugins/workflow-run-store-sql.js +50 -9
  332. package/dist/posture-source.d.ts +18 -10
  333. package/dist/posture-source.js +4 -1
  334. package/dist/project-identity.d.ts +45 -6
  335. package/dist/project-identity.js +162 -8
  336. package/dist/project-layer-key.d.ts +28 -0
  337. package/dist/project-layer-key.js +29 -0
  338. package/dist/question.js +3 -2
  339. package/dist/read-deny-entry.d.ts +25 -0
  340. package/dist/read-deny-entry.js +12 -0
  341. package/dist/read-face-posture.d.ts +37 -11
  342. package/dist/read-face-posture.js +32 -3
  343. package/dist/request-key-closure.d.ts +7 -0
  344. package/dist/request-key-closure.js +9 -1
  345. package/dist/request-value-closure.d.ts +5 -0
  346. package/dist/request-value-closure.js +11 -3
  347. package/dist/rule-entry-list.d.ts +26 -2
  348. package/dist/rule-entry-list.js +72 -12
  349. package/dist/rules-consent.js +3 -4
  350. package/dist/run-acceptance.d.ts +19 -3
  351. package/dist/run-acceptance.js +13 -1
  352. package/dist/run-local.js +36 -6
  353. package/dist/runs.d.ts +10 -9
  354. package/dist/runs.js +21 -3
  355. package/dist/runtime-caps-resolver.d.ts +16 -6
  356. package/dist/runtime-caps-resolver.js +18 -5
  357. package/dist/sandbox-pkg-source.d.ts +19 -1
  358. package/dist/sandbox-pkg-source.js +29 -7
  359. package/dist/security.d.ts +87 -9
  360. package/dist/security.js +52 -9
  361. package/dist/session-error-wire.d.ts +19 -2
  362. package/dist/session-error-wire.js +5 -1
  363. package/dist/session-titled-frame.d.ts +33 -0
  364. package/dist/session-titled-frame.js +4 -0
  365. package/dist/session-titler.d.ts +9 -1
  366. package/dist/session-titler.js +15 -4
  367. package/dist/spec-fields.js +21 -2
  368. package/dist/sql-engine-posture.d.ts +3 -1
  369. package/dist/task-cwd.d.ts +1 -1
  370. package/dist/task-mcp.d.ts +3 -3
  371. package/dist/task-mcp.js +7 -66
  372. package/dist/task-settings.d.ts +89 -88
  373. package/dist/task-settings.js +71 -63
  374. package/dist/text-bidi.d.ts +0 -4
  375. package/dist/text-bidi.js +1 -3
  376. package/dist/tighten-only-seats.d.ts +150 -0
  377. package/dist/tighten-only-seats.js +196 -0
  378. package/dist/tool-approval.d.ts +303 -87
  379. package/dist/tool-approval.js +623 -239
  380. package/dist/trace/core-keyset-guard.d.ts +104 -22
  381. package/dist/trace/exit-seat.d.ts +28 -0
  382. package/dist/trace/exit-seat.js +76 -0
  383. package/dist/trace/ledger-events.d.ts +3 -2
  384. package/dist/trace/project.d.ts +80 -12
  385. package/dist/trace/project.js +41 -28
  386. package/dist/trace/projection-table.d.ts +100 -0
  387. package/dist/trace/projection-table.js +130 -0
  388. package/dist/trace/redact.d.ts +54 -0
  389. package/dist/trace/redact.js +778 -152
  390. package/dist/trace/self-minted-wire.d.ts +345 -1
  391. package/dist/trace/self-minted-wire.js +117 -1
  392. package/dist/trace/wire-projection-faces.d.ts +298 -2
  393. package/dist/trace/wire-projection-faces.js +154 -13
  394. package/dist/url-refusal.js +2 -0
  395. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  396. package/dist/web-admin-client/apply-effective.js +56 -5
  397. package/dist/web-admin-client/facade.d.ts +1 -1
  398. package/dist/web-admin-client/facade.js +1 -1
  399. package/dist/web-admin-client/read-face.js +5 -9
  400. package/dist/web-admin-client/skills-mcp.js +4 -5
  401. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  402. package/package.json +7 -3
@@ -1,12 +1,11 @@
1
1
  import { z } from "zod";
2
- import { sendJson, sendError, sendHttpError } from "../send.js";
2
+ import { sendJson, sendError } from "../send.js";
3
3
  import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sendUnauthorized } from "../principal-gate.js";
4
4
  import { assertNever } from "../route-ctx.js";
5
5
  import * as facts from "../../capability-facts.js";
6
6
  import { createLogger } from "../../observability/logger.js";
7
7
  import { RULE_IMPORT_RETRY_AFTER_SEC, RULE_SCOPE_REFUSAL_SENTENCE, MAX_RULE_SCOPE_CHARS, buildCcImportLayerRootRefusal, parseRuleScope, serializeRuleScope } from "../../rules-consent.js";
8
- import { CONTROL_AND_BIDI_CHARS } from "../../text-bidi.js";
9
- import { HttpError } from "../../security.js";
8
+ import { hasControlOrBidi } from "@sema-agent/settings-schema";
10
9
  import { MAX_RULE_TEXT_CHARS, RULE_BEHAVIORS, isValidDurableScope } from "@sema-agent/core";
11
10
  import { PERSISTED_RULE_MATCHES, isPersistedRuleTool, isDirectWritableRuleBehavior } from "../../permission-rule-vocab.js";
12
11
  const logger = createLogger();
@@ -37,8 +36,7 @@ const CcImportPrepareBodySchema = z
37
36
  function ccImportRootRefused(layer) {
38
37
  return !isValidDurableScope({ kind: "project", root: layer.root });
39
38
  }
40
- const TICKET_CONTROL_CHARS_RE = new RegExp(`[${CONTROL_AND_BIDI_CHARS}]`);
41
- const TicketStringSchema = z.string().min(1).max(190).refine((t) => !TICKET_CONTROL_CHARS_RE.test(t));
39
+ const TicketStringSchema = z.string().min(1).max(190).refine((t) => !hasControlOrBidi(t));
42
40
  const CcImportRedeemBodySchema = z.object({ ticket: TicketStringSchema }).strict();
43
41
  const LocalImportAddSchema = z
44
42
  .object({
@@ -107,18 +105,7 @@ export async function handleRules(req, res, match, ctx) {
107
105
  await handleRuleList(res, match.search, principal, lane, deps.config);
108
106
  return;
109
107
  }
110
- let rawBody;
111
- try {
112
- rawBody = await readJson(req);
113
- }
114
- catch (err) {
115
- if (err instanceof HttpError && err.status !== 400) {
116
- sendHttpError(res, err);
117
- return;
118
- }
119
- sendError(res, 400, "request.body_shape", "body must be valid JSON");
120
- return;
121
- }
108
+ const rawBody = await readJson(req);
122
109
  if (match.decl.id === "rules-revoke") {
123
110
  await handleRuleRevoke(res, rawBody, principal, lane, deps.config);
124
111
  return;
@@ -216,7 +203,7 @@ function resolveTargetPrincipal(requested, caller, config) {
216
203
  return { ok: true, principal: caller };
217
204
  if (!facts.operatorLane({ config }).available)
218
205
  return { ok: false, why: "operator_principals_empty" };
219
- if (!explicitOperatorOk(caller, config.operatorPrincipals))
206
+ if (!explicitOperatorOk(caller, config))
220
207
  return { ok: false, why: "not_operator" };
221
208
  return { ok: true, principal: requested };
222
209
  }
@@ -133,6 +133,11 @@ export declare const RUN_VERBS_ROUTES: readonly [{
133
133
  readonly pattern: RegExp;
134
134
  readonly label: "/v1/tool-approvals/:id/respond";
135
135
  readonly methods: readonly ["POST"];
136
+ }, {
137
+ readonly id: "tool-approval-read";
138
+ readonly pattern: RegExp;
139
+ readonly label: "/v1/tool-approvals/:id";
140
+ readonly methods: readonly ["GET"];
136
141
  }, {
137
142
  readonly id: "task-ask-decision";
138
143
  readonly pattern: RegExp;
@@ -5,7 +5,7 @@ import { uuidv7, mintCheckpointToken, CheckpointError, policyCannotAnswer, valid
5
5
  import { isTerminalRunStatus, isParkedRunStatus, runProvenElsewhere } from "../../plugins/store-contracts.js";
6
6
  import { LIVE_RUN_GATE_KINDS, TERMINAL_PARK_GATE_KINDS } from "../../plugins/checkpoint-store-sql.js";
7
7
  import { redactSecrets } from "../../trace/redact.js";
8
- import { HttpError, isUuidV7, encodeCheckpointScope } from "../../security.js";
8
+ import { isUuidV7, encodeCheckpointScope } from "../../security.js";
9
9
  import { redactSteerIn, STEER_IN_MAX_CHARS, STEER_IN_MAX_REQUEST_CHARS } from "../../orchestration/workflow-agent-steer.js";
10
10
  import { defaultSubagentTailBus } from "../../fleet/subagent-tail-bus.js";
11
11
  import { idemCallerOf, idemKeyOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
@@ -14,10 +14,10 @@ import { bindSseLifecycle } from "../sse-lifecycle.js";
14
14
  import { buildApprovalPreamble, buildApprovalPreambleSseFrames, readClosedWordSeat, storedCardDemandsAPerson } from "../../approval-card.js";
15
15
  import { heldAskOf, liveSettledBy, readDecidedBy, retiredDecisionKeyFacts, DECIDED_BY_NOT_IN_PROOF, DECIDED_BY_OUTSIDE_CLOSED_SET, POLICY_CANNOT_ALLOW_PERSON_ASK } from "../../host-decision.js";
16
16
  import { ASK_DECISION_CONSUMER_ABSENT, outcomeOfDecidedRow, resolveStreamApprovalGate } from "../../tool-approval.js";
17
- import { MAX_DECISION_NOTE_CHARS } from "../../approval-ask-machine.js";
17
+ import { MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt } from "../../approval-ask-machine.js";
18
18
  import { causeOfAskRow } from "../../approval-deny-reasons.js";
19
19
  import { normalizeRunEventType, screenedStoredEventData } from "../../trace/project.js";
20
- import { sendJson, sendError, sendHttpError, sseHeaders } from "../send.js";
20
+ import { invalidJsonError, sendJson, sendError, sendHttpError, sseHeaders } from "../send.js";
21
21
  import { mintCancelledResult } from "../../run-cancel-context.js";
22
22
  import { acceptedInputKindOf } from "../../user-input-ledger.js";
23
23
  import { INJECTION_TIERS } from "../../trace/injection-tier.js";
@@ -35,6 +35,7 @@ import { storedBodyReplayAnswer, storedBodyReplayLogFields } from "../checkpoint
35
35
  import { serviceVersion } from "../../service-version.js";
36
36
  import { storedBodyReplayRefusal } from "../stored-body-replay.js";
37
37
  import { steerBodyKeyIssue } from "../../request-key-closure.js";
38
+ import { fieldConflictFacts } from "../../field-conflict.js";
38
39
  const STEER_PRIORITY_WORDS = INJECTION_TIERS.map((tier) => `'${tier}'`);
39
40
  const STEER_PRIORITY_UNION = STEER_PRIORITY_WORDS.join(" | ");
40
41
  const STEER_PRIORITY_CHOICES = STEER_PRIORITY_WORDS.length <= 2 ? STEER_PRIORITY_WORDS.join(" or ") : `${STEER_PRIORITY_WORDS.slice(0, -1).join(", ")}, or ${STEER_PRIORITY_WORDS[STEER_PRIORITY_WORDS.length - 1]}`;
@@ -81,7 +82,7 @@ async function subagentReadGate(req, res, ctx, runId, search) {
81
82
  sendPrincipalRefusal(res, req, deps.config);
82
83
  return null;
83
84
  }
84
- const trusted = explicitOperatorOk(principal, deps.config.operatorPrincipals);
85
+ const trusted = explicitOperatorOk(principal, deps.config);
85
86
  const run = await deps.runStore.getRun(runId);
86
87
  if (!run) {
87
88
  sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
@@ -399,18 +400,7 @@ export async function handleRuns(req, res, match, ctx) {
399
400
  return;
400
401
  }
401
402
  const taskId = match.params.taskId;
402
- let body;
403
- try {
404
- body = ((await readJson(req)) ?? {});
405
- }
406
- catch (e) {
407
- if (e instanceof HttpError) {
408
- sendHttpError(res, e);
409
- return;
410
- }
411
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
412
- return;
413
- }
403
+ const body = ((await readJson(req)) ?? {});
414
404
  if (typeof body.text !== "string" || body.text.length === 0) {
415
405
  sendError(res, 400, "request.body_shape", `body must be { text: string (non-empty), mode?: 'all' | 'one-at-a-time', priority?: ${STEER_PRIORITY_UNION} }`);
416
406
  return;
@@ -435,7 +425,7 @@ export async function handleRuns(req, res, match, ctx) {
435
425
  const steerIdemRaw = headerStr(req.headers["idempotency-key"]);
436
426
  const steerInputId = steerIdemRaw ? `idem-${idemKeyOf(steerIdemRaw, idemCallerOf(req, ctx), "run").slice(0, 32)}` : undefined;
437
427
  const messageId = steerInputId ?? uuidv7();
438
- const trusted = explicitOperatorOk(principal, deps.config.operatorPrincipals);
428
+ const trusted = explicitOperatorOk(principal, deps.config);
439
429
  const steerInput = () => ({
440
430
  text,
441
431
  trusted,
@@ -724,18 +714,7 @@ export async function handleRuns(req, res, match, ctx) {
724
714
  return;
725
715
  }
726
716
  const taskId = match.params.taskId;
727
- let interruptRaw;
728
- try {
729
- interruptRaw = await readJson(req);
730
- }
731
- catch (e) {
732
- if (e instanceof HttpError) {
733
- sendHttpError(res, e);
734
- return;
735
- }
736
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
737
- return;
738
- }
717
+ const interruptRaw = await readJson(req);
739
718
  const interruptNormalized = interruptRaw === null || interruptRaw === undefined ? {} : interruptRaw;
740
719
  if (typeof interruptNormalized !== "object" || Array.isArray(interruptNormalized)) {
741
720
  sendError(res, 400, "request.body_shape", "body must be {} (bare halt: cut the in-flight turn and stop the run at this boundary) or { text: string (non-empty) } (cut + steer: the text reaches the model after the cut)");
@@ -759,7 +738,7 @@ export async function handleRuns(req, res, match, ctx) {
759
738
  const interruptIdemRaw = headerStr(req.headers["idempotency-key"]);
760
739
  const interruptInputId = interruptIdemRaw ? `idem-${idemKeyOf(interruptIdemRaw, idemCallerOf(req, ctx), "run").slice(0, 32)}` : uuidv7();
761
740
  const interruptMessageId = interruptInputId;
762
- const trusted = explicitOperatorOk(principal, deps.config.operatorPrincipals);
741
+ const trusted = explicitOperatorOk(principal, deps.config);
763
742
  if (!interruptBare) {
764
743
  try {
765
744
  validatePendingSteer({ text, trusted, inputId: interruptInputId });
@@ -877,28 +856,17 @@ export async function handleRuns(req, res, match, ctx) {
877
856
  sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
878
857
  return;
879
858
  }
880
- const operator = explicitOperatorOk(principal, deps.config.operatorPrincipals);
859
+ const operator = explicitOperatorOk(principal, deps.config);
881
860
  if (!operator && !runOwnerOk(req, res, run.owner))
882
861
  return;
883
862
  if (!runSessionAcceptOk(req, res, run, "run.compact"))
884
863
  return;
885
- let compactBody;
886
- try {
887
- const parsed = await readJson(req);
888
- if (parsed === null || typeof parsed !== "object") {
889
- sendError(res, 400, "request.invalid_json", "body must be a JSON object when present");
890
- return;
891
- }
892
- compactBody = parsed;
893
- }
894
- catch (e) {
895
- if (e instanceof HttpError) {
896
- sendHttpError(res, e);
897
- return;
898
- }
899
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
864
+ const parsed = await readJson(req);
865
+ if (parsed === null || typeof parsed !== "object") {
866
+ sendHttpError(res, invalidJsonError("not_object"));
900
867
  return;
901
868
  }
869
+ const compactBody = parsed;
902
870
  if (compactBody.instructions !== undefined && (typeof compactBody.instructions !== "string" || compactBody.instructions.length === 0 || [...compactBody.instructions].length > 2_048)) {
903
871
  sendError(res, 400, "request.field_invalid", "instructions must be a non-empty string of at most 2048 characters (code points) when present — the engine caps compaction instructions there");
904
872
  return;
@@ -938,18 +906,7 @@ export async function handleRuns(req, res, match, ctx) {
938
906
  return;
939
907
  }
940
908
  const taskId = match.params.taskId;
941
- let body;
942
- try {
943
- body = ((await readJson(req)) ?? {});
944
- }
945
- catch (e) {
946
- if (e instanceof HttpError) {
947
- sendHttpError(res, e);
948
- return;
949
- }
950
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
951
- return;
952
- }
909
+ const body = ((await readJson(req)) ?? {});
953
910
  if (typeof body.toolCallId !== "string" || body.toolCallId.length === 0 || body.toolCallId.length > 256) {
954
911
  sendError(res, 400, "request.body_shape", "body must be { toolCallId: string (non-empty, ≤256 chars) }");
955
912
  return;
@@ -959,7 +916,7 @@ export async function handleRuns(req, res, match, ctx) {
959
916
  sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
960
917
  return;
961
918
  }
962
- const operator = explicitOperatorOk(principal, deps.config.operatorPrincipals);
919
+ const operator = explicitOperatorOk(principal, deps.config);
963
920
  if (!operator && !runOwnerOk(req, res, run.owner))
964
921
  return;
965
922
  if (!runSessionAcceptOk(req, res, run, "run.detach"))
@@ -1164,18 +1121,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1164
1121
  sendError(res, 400, "request.path_malformed", "malformed subagent path (invalid percent-encoding)");
1165
1122
  return;
1166
1123
  }
1167
- let body;
1168
- try {
1169
- body = ((await readJson(req)) ?? {});
1170
- }
1171
- catch (e) {
1172
- if (e instanceof HttpError) {
1173
- sendHttpError(res, e);
1174
- return;
1175
- }
1176
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
1177
- return;
1178
- }
1124
+ const body = ((await readJson(req)) ?? {});
1179
1125
  if (typeof body.content !== "string" || body.content.length === 0) {
1180
1126
  sendError(res, 400, "request.body_shape", "body must be { content: string (non-empty) }");
1181
1127
  return;
@@ -1191,7 +1137,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1191
1137
  sendError(res, 413, "steer.content_too_large", `content exceeds ${STEER_IN_MAX_REQUEST_CHARS} characters (got ${body.content.length}); note only the first ${STEER_IN_MAX_CHARS} are delivered anyway`);
1192
1138
  return;
1193
1139
  }
1194
- const trusted = explicitOperatorOk(principal, deps.config.operatorPrincipals);
1140
+ const trusted = explicitOperatorOk(principal, deps.config);
1195
1141
  const run = await runStore.getRun(runId);
1196
1142
  if (!run) {
1197
1143
  sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
@@ -1274,14 +1220,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1274
1220
  return;
1275
1221
  }
1276
1222
  const id = match.params.id;
1277
- let body;
1278
- try {
1279
- body = await readJson(req);
1280
- }
1281
- catch {
1282
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
1283
- return;
1284
- }
1223
+ const body = await readJson(req);
1285
1224
  const { status, body: respBody } = elicitFact.coordinator.respond(id, principal, body);
1286
1225
  sendJson(res, status, respBody);
1287
1226
  return;
@@ -1300,19 +1239,12 @@ export async function handleRunVerbs(req, res, match, ctx) {
1300
1239
  return;
1301
1240
  }
1302
1241
  const id = match.params.id;
1303
- let body;
1304
- try {
1305
- body = await readJson(req);
1306
- }
1307
- catch {
1308
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
1309
- return;
1310
- }
1242
+ const body = await readJson(req);
1311
1243
  const { status, body: respBody } = questionFact.coordinator.respond(id, principal, body);
1312
1244
  sendJson(res, status, respBody);
1313
1245
  return;
1314
1246
  }
1315
- if (match.decl.id === "tool-approval-respond") {
1247
+ if (match.decl.id === "tool-approval-respond" || match.decl.id === "tool-approval-read") {
1316
1248
  if (rateLimited(req, res))
1317
1249
  return;
1318
1250
  const approvalFact = facts.toolApproval(deps);
@@ -1326,15 +1258,13 @@ export async function handleRunVerbs(req, res, match, ctx) {
1326
1258
  return;
1327
1259
  }
1328
1260
  const id = match.params.id;
1329
- let body;
1330
- try {
1331
- body = await readJson(req);
1332
- }
1333
- catch {
1334
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
1261
+ if (match.decl.id === "tool-approval-read") {
1262
+ const { status, body: respBody } = await approvalFact.coordinator.readApproval(id, principal);
1263
+ sendJson(res, status, respBody);
1335
1264
  return;
1336
1265
  }
1337
- const { status, body: respBody } = await approvalFact.coordinator.respond(id, principal, body, req);
1266
+ const body = await readJson(req);
1267
+ const { status, body: respBody } = await approvalFact.coordinator.respond(id, principal, body, req, { readRootGrantAccepted: facts.readRootGrant(deps).available });
1338
1268
  const retryAfterSec = respBody.retryAfterSec;
1339
1269
  if (typeof retryAfterSec === "number" && Number.isFinite(retryAfterSec) && retryAfterSec >= 0) {
1340
1270
  res.setHeader("retry-after", String(Math.ceil(retryAfterSec)));
@@ -1356,14 +1286,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1356
1286
  sendPrincipalRefusal(res, req, deps.config);
1357
1287
  return;
1358
1288
  }
1359
- let rawBody;
1360
- try {
1361
- rawBody = await readJson(req);
1362
- }
1363
- catch {
1364
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
1365
- return;
1366
- }
1289
+ const rawBody = await readJson(req);
1367
1290
  const parsedBody = AskDecisionBodySchema.safeParse(rawBody);
1368
1291
  if (!parsedBody.success) {
1369
1292
  const retired = retiredDecisionKeyFacts(rawBody);
@@ -1401,7 +1324,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1401
1324
  return;
1402
1325
  }
1403
1326
  const ownerOk = row0.owner === null || (principal !== undefined && row0.owner === principal);
1404
- const operatorOk = explicitOperatorOk(principal, deps.config.operatorPrincipals);
1327
+ const operatorOk = explicitOperatorOk(principal, deps.config);
1405
1328
  if (!ownerOk && !operatorOk) {
1406
1329
  askNotFound();
1407
1330
  return;
@@ -1440,6 +1363,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1440
1363
  return true;
1441
1364
  };
1442
1365
  const decisionNoteEcho = (row) => (row.decisionNote === null ? {} : { decisionNote: row.decisionNote });
1366
+ const noteReceipt = (row) => noteRecordedReceipt(body.note, noteLandedOnRow(body.note, row.decisionNote));
1443
1367
  const replayDecided = (row) => {
1444
1368
  const storedActor = projectDecisionActor(row.decisionActor);
1445
1369
  sendJson(res, 200, {
@@ -1449,6 +1373,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1449
1373
  decidedAtMs: row.decidedAtMs,
1450
1374
  ...(storedActor ? { actor: storedActor } : {}),
1451
1375
  ...decisionNoteEcho(row),
1376
+ ...noteReceipt(row),
1452
1377
  });
1453
1378
  };
1454
1379
  const sendTerminal = (row) => {
@@ -1519,7 +1444,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1519
1444
  return;
1520
1445
  }
1521
1446
  if (body.decision === "approve" && policyCannotAnswer(heldAskOf(storedCardDemandsAPerson(row0.cardJson)), decidedBy)) {
1522
- sendError(res, 400, "request.field_conflict", POLICY_CANNOT_ALLOW_PERSON_ASK);
1447
+ sendError(res, 400, "request.field_conflict", POLICY_CANNOT_ALLOW_PERSON_ASK, fieldConflictFacts("policy_person_ask", ["decidedBy", "decision"]));
1523
1448
  return;
1524
1449
  }
1525
1450
  let outcome;
@@ -1606,6 +1531,7 @@ export async function handleRunVerbs(req, res, match, ctx) {
1606
1531
  ...(forwarded ? { updatedInputForwarded: true } : {}),
1607
1532
  ...(settled === 0 ? { consumerState: ASK_DECISION_CONSUMER_ABSENT } : {}),
1608
1533
  ...decisionNoteEcho(outcome.row),
1534
+ ...noteReceipt(outcome.row),
1609
1535
  });
1610
1536
  return;
1611
1537
  }
@@ -1675,6 +1601,7 @@ export const RUN_VERBS_ROUTES = [
1675
1601
  { id: "elicitation-respond", pattern: /^\/v1\/elicitations\/(?<id>[^/]+)\/respond$/, label: "/v1/elicitations/:id/respond", methods: ["POST"] },
1676
1602
  { id: "question-respond", pattern: /^\/v1\/questions\/(?<id>[^/]+)\/respond$/, label: "/v1/questions/:id/respond", methods: ["POST"] },
1677
1603
  { id: "tool-approval-respond", pattern: /^\/v1\/tool-approvals\/(?<id>[^/]+)\/respond$/, label: "/v1/tool-approvals/:id/respond", methods: ["POST"] },
1604
+ { id: "tool-approval-read", pattern: /^\/v1\/tool-approvals\/(?<id>[^/]+)$/, label: "/v1/tool-approvals/:id", methods: ["GET"] },
1678
1605
  { id: "task-ask-decision", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/asks\/(?<askId>[^/]+)\/decision$/, label: "/v1/tasks/:id/asks/:askId/decision", methods: ["POST"] },
1679
1606
  ];
1680
1607
  //# sourceMappingURL=runs.js.map
@@ -6,8 +6,7 @@ import { exportSessionManifest, fileHistoryImportFace, replayFileHistory, replay
6
6
  import * as facts from "../../capability-facts.js";
7
7
  import { classifySyncRelationshipByIds, SyncConflictError } from "../../session-sync-kernel.js";
8
8
  import { isUuidShape } from "../../security.js";
9
- import { sqlBlobCapRefusalText } from "../../plugins/blob-backend.js";
10
- import { sendJson, sendError, sendSessionError, sendSessionPolicyError, msg } from "../send.js";
9
+ import { sendJson, sendError, sendSessionError, sendSessionPolicyError, logRequestError, msg } from "../send.js";
11
10
  import { buildDisplaySafeUrl } from "../../trace/redact.js";
12
11
  import { gatedPrincipal, explicitOperatorOk, sendUnauthorized } from "../principal-gate.js";
13
12
  const SYNC_BLOB_MAX_BYTES = 64 * 1024 * 1024;
@@ -187,17 +186,16 @@ export async function handleSessionSync(req, res, match, ctx) {
187
186
  }
188
187
  const fs = blobs.historyStore;
189
188
  const body = await readRawBody(req, SYNC_BLOB_MAX_BYTES);
190
- const sqlCap = deps.snapshotBlobSqlCap?.();
191
- if (sqlCap !== undefined && body.byteLength > sqlCap.capBytes) {
192
- sendError(res, 413, "blob_too_large_for_sql", sqlBlobCapRefusalText(body.byteLength, sqlCap), { wallSource: sqlCap.source });
193
- return;
194
- }
195
189
  if (createHash("sha256").update(body).digest("hex") !== hash) {
196
190
  sendError(res, 400, "request.hash_mismatch", "blob hash mismatch");
197
191
  return;
198
192
  }
199
193
  const put = await fs.putBlob(hash, new Uint8Array(body));
200
194
  if (!put.ok) {
195
+ if (put.error.code === "blob_too_large_for_sql") {
196
+ sendError(res, 413, "blob_too_large_for_sql", put.error.message, { wallSource: put.error.wallSource });
197
+ return;
198
+ }
201
199
  sendError(res, 502, put.error.code, "blob store write failed");
202
200
  return;
203
201
  }
@@ -216,14 +214,7 @@ export async function handleSessionSync(req, res, match, ctx) {
216
214
  }
217
215
  }).catch(() => { });
218
216
  }
219
- let body;
220
- try {
221
- body = (await readJson(req));
222
- }
223
- catch {
224
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
225
- return;
226
- }
217
+ const body = (await readJson(req));
227
218
  if (!Array.isArray(body.entryIds) || !body.entryIds.every((x) => typeof x === "string")) {
228
219
  sendError(res, 400, "request.field_invalid", "entryIds must be an array of strings");
229
220
  return;
@@ -314,7 +305,7 @@ export async function handleSessionSync(req, res, match, ctx) {
314
305
  return;
315
306
  }
316
307
  }
317
- const opOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config.operatorPrincipals);
308
+ const opOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
318
309
  if (deps.sessionPolicyStore) {
319
310
  try {
320
311
  await replayPolicyRecords(deps.sessionPolicyStore, sessionId, policy, opOk);
@@ -389,7 +380,7 @@ export async function handleSessionSync(req, res, match, ctx) {
389
380
  }
390
381
  }
391
382
  const importingPrincipal = scope.fleetWide ? (owner ?? null) : scope.gateOwner;
392
- const operatorOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config.operatorPrincipals);
383
+ const operatorOk = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
393
384
  const token = randomBytes(8).toString("hex");
394
385
  const handle = sessionStorage.beginImportStaging(sessionId, token);
395
386
  const stagingId = handle.stagingId;
@@ -532,15 +523,18 @@ export async function handleSessionSync(req, res, match, ctx) {
532
523
  sendJson(res, 200, { relation: committed.relation });
533
524
  }
534
525
  catch (e) {
526
+ await pending.handle.abort().catch(() => undefined);
527
+ cleanupStaging(stagingId);
535
528
  if (e instanceof SyncConflictError) {
536
- await pending.handle.abort().catch(() => undefined);
537
- cleanupStaging(stagingId);
538
529
  sendError(res, 409, "conflict", "sync conflict", { relation: e.relation });
539
530
  return;
540
531
  }
541
- cleanupStaging(stagingId);
542
532
  if (sendSessionPolicyError(res, e))
543
533
  return;
534
+ if (sendSessionError(res, e, "import")) {
535
+ logRequestError(deps.logger, req, e);
536
+ return;
537
+ }
544
538
  throw e;
545
539
  }
546
540
  return;
@@ -548,14 +542,7 @@ export async function handleSessionSync(req, res, match, ctx) {
548
542
  if (match.decl.id === "session-sync-plan") {
549
543
  if (!pushGateOk())
550
544
  return;
551
- let body;
552
- try {
553
- body = (await readJson(req));
554
- }
555
- catch {
556
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
557
- return;
558
- }
545
+ const body = (await readJson(req));
559
546
  if (!Array.isArray(body.entryIds) || !body.entryIds.every((x) => typeof x === "string")) {
560
547
  sendError(res, 400, "request.field_invalid", "entryIds must be an array of strings");
561
548
  return;