@sema-agent/server 7.132.0 → 7.134.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 (473) hide show
  1. package/MIGRATION.md +353 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +301 -64
  5. package/deploy/sema-up/README.md +35 -1
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
  9. package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
  10. package/deploy/sema-up/chart/templates/server-v4pro.yaml +19 -2
  11. package/deploy/sema-up/chart/templates/server.yaml +19 -2
  12. package/deploy/sema-up/chart/values-full-single.yaml +5 -1
  13. package/deploy/sema-up/chart/values.yaml +34 -0
  14. package/deploy/sema-up/stack/compose.yaml +3 -0
  15. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  16. package/dist/adoption/plan.d.ts +3 -2
  17. package/dist/adoption/plan.js +7 -5
  18. package/dist/adoption/runner.js +3 -10
  19. package/dist/adoption/sql.d.ts +3 -2
  20. package/dist/adoption/sql.js +3 -5
  21. package/dist/adoption/wire.d.ts +4 -1
  22. package/dist/adoption/wire.js +1 -0
  23. package/dist/approval-ask-audit-store.d.ts +32 -14
  24. package/dist/approval-ask-audit-store.js +272 -74
  25. package/dist/approval-ask-machine.d.ts +15 -0
  26. package/dist/approval-ask-machine.js +6 -0
  27. package/dist/approval-ask-retention.d.ts +136 -0
  28. package/dist/approval-ask-retention.js +102 -0
  29. package/dist/approval-card.d.ts +83 -23
  30. package/dist/approval-card.js +45 -15
  31. package/dist/approval-content-kind.d.ts +5 -2
  32. package/dist/approval-content-kind.js +16 -3
  33. package/dist/approval-deny-reasons.d.ts +1 -1
  34. package/dist/approval-gate-currency.d.ts +72 -0
  35. package/dist/approval-gate-currency.js +94 -0
  36. package/dist/approval.d.ts +15 -0
  37. package/dist/approval.js +55 -17
  38. package/dist/audit.d.ts +27 -10
  39. package/dist/audit.js +12 -16
  40. package/dist/bake-runner/main.js +3 -2
  41. package/dist/boot/coordinators.d.ts +6 -1
  42. package/dist/boot/coordinators.js +6 -3
  43. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  44. package/dist/boot/execution-env.js +9 -7
  45. package/dist/boot/execution-lane.js +11 -0
  46. package/dist/boot/leader.d.ts +2 -0
  47. package/dist/boot/leader.js +4 -1
  48. package/dist/boot/memory-boundary.js +2 -2
  49. package/dist/boot/memory-consolidation.d.ts +5 -4
  50. package/dist/boot/memory-consolidation.js +7 -6
  51. package/dist/boot/org-delivery.d.ts +28 -0
  52. package/dist/boot/org-delivery.js +20 -0
  53. package/dist/boot/read-deny-anchor-audit.js +2 -2
  54. package/dist/boot/reapers.d.ts +3 -0
  55. package/dist/boot/reapers.js +21 -1
  56. package/dist/boot/resolve-spec.d.ts +3 -0
  57. package/dist/boot/resolve-spec.js +60 -81
  58. package/dist/boot/runner-deps.d.ts +18 -5
  59. package/dist/boot/runner-deps.js +10 -0
  60. package/dist/boot/session-faces.d.ts +1 -0
  61. package/dist/boot/session-faces.js +4 -2
  62. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  63. package/dist/boot/stage-06-runners.d.ts +6 -3
  64. package/dist/boot/stage-06-runners.js +20 -4
  65. package/dist/boot/stage-07-capability-layer.d.ts +4 -1
  66. package/dist/boot/stage-07-capability-layer.js +24 -3
  67. package/dist/boot/stage-08-reapers.d.ts +4 -1
  68. package/dist/boot/stage-08-reapers.js +2 -2
  69. package/dist/boot/stage-09-leader.d.ts +5 -1
  70. package/dist/boot/stage-09-leader.js +2 -2
  71. package/dist/boot/stage-10-http-server.d.ts +5 -1
  72. package/dist/boot/stage-10-http-server.js +6 -6
  73. package/dist/boot/stores.d.ts +8 -0
  74. package/dist/boot/stores.js +10 -14
  75. package/dist/boot/web-admin.d.ts +10 -0
  76. package/dist/boot/web-admin.js +162 -65
  77. package/dist/boot/workflow-orchestration.d.ts +2 -0
  78. package/dist/boot/workflow-orchestration.js +2 -1
  79. package/dist/brain.js +8 -3
  80. package/dist/breaker-key.d.ts +6 -0
  81. package/dist/breaker-key.js +29 -0
  82. package/dist/budget.js +5 -1
  83. package/dist/caller-text-echo.d.ts +11 -6
  84. package/dist/caller-text-echo.js +10 -12
  85. package/dist/canonical-json.d.ts +2 -41
  86. package/dist/canonical-json.js +2 -13
  87. package/dist/capabilities/center-plugins.d.ts +7 -0
  88. package/dist/capabilities/center-plugins.js +1 -1
  89. package/dist/capabilities/composite-members.d.ts +1 -1
  90. package/dist/capabilities/composite-members.js +1 -1
  91. package/dist/capabilities/execution-lane.js +2 -2
  92. package/dist/capabilities/hands-lane.d.ts +21 -0
  93. package/dist/capabilities/hands-lane.js +10 -0
  94. package/dist/capabilities/mcp-probe.d.ts +36 -4
  95. package/dist/capabilities/mcp-probe.js +29 -6
  96. package/dist/capabilities/scenarios.d.ts +63 -7
  97. package/dist/capabilities/scenarios.js +39 -7
  98. package/dist/capability-facts.d.ts +36 -4
  99. package/dist/capability-facts.js +30 -4
  100. package/dist/center-config-tier.d.ts +69 -0
  101. package/dist/center-config-tier.js +42 -0
  102. package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
  103. package/dist/checkpoint-ctx-seal-m28.js +19 -0
  104. package/dist/checkpoint-identity.d.ts +16 -0
  105. package/dist/checkpoint-identity.js +19 -0
  106. package/dist/config-catalog.d.ts +17 -10
  107. package/dist/config-catalog.js +43 -28
  108. package/dist/config-d-migration.d.ts +3 -1
  109. package/dist/config-d-migration.js +2 -2
  110. package/dist/config-dir-trust.d.ts +114 -0
  111. package/dist/config-dir-trust.js +388 -0
  112. package/dist/config-invariants.d.ts +18 -5
  113. package/dist/config-invariants.js +35 -3
  114. package/dist/config-provider.d.ts +6 -1
  115. package/dist/config-provider.js +6 -2
  116. package/dist/config-types.d.ts +71 -14
  117. package/dist/config-types.js +8 -0
  118. package/dist/config.d.ts +13 -0
  119. package/dist/config.js +121 -59
  120. package/dist/delegated-session-owner.d.ts +185 -0
  121. package/dist/delegated-session-owner.js +119 -0
  122. package/dist/device-protocol.d.ts +5 -3
  123. package/dist/device-protocol.js +1 -1
  124. package/dist/device-ws-hub.js +21 -2
  125. package/dist/device-ws-protocol.d.ts +70 -6
  126. package/dist/device-ws-protocol.js +50 -23
  127. package/dist/elicitation.js +3 -2
  128. package/dist/entry-problems.d.ts +34 -0
  129. package/dist/entry-problems.js +14 -0
  130. package/dist/execution-lane-caps.d.ts +49 -10
  131. package/dist/execution-lane-caps.js +43 -4
  132. package/dist/field-conflict.d.ts +44 -0
  133. package/dist/field-conflict.js +21 -0
  134. package/dist/file-history-disclosure.d.ts +34 -5
  135. package/dist/file-history-disclosure.js +2 -2
  136. package/dist/fleet/fleet-bus.d.ts +84 -6
  137. package/dist/fleet/fleet-bus.js +42 -9
  138. package/dist/hooks/classic-stations.d.ts +10 -5
  139. package/dist/hooks/classic-stations.js +4 -4
  140. package/dist/hooks/command-spawn.d.ts +57 -0
  141. package/dist/hooks/command-spawn.js +139 -0
  142. package/dist/hooks/hook-llm.js +2 -2
  143. package/dist/hooks/hook-runner.d.ts +127 -25
  144. package/dist/hooks/hook-runner.js +668 -287
  145. package/dist/hooks/hook-source.d.ts +44 -0
  146. package/dist/hooks/hook-source.js +40 -0
  147. package/dist/http/active-run-conflict.d.ts +5 -13
  148. package/dist/http/active-run-conflict.js +17 -27
  149. package/dist/http/admission.js +111 -60
  150. package/dist/http/approval-sweeps.js +58 -19
  151. package/dist/http/caller-trust.d.ts +77 -0
  152. package/dist/http/caller-trust.js +143 -0
  153. package/dist/http/checkpoint-ctx.d.ts +173 -18
  154. package/dist/http/checkpoint-ctx.js +171 -12
  155. package/dist/http/claimed-run.d.ts +4 -3
  156. package/dist/http/device-placement.d.ts +2 -4
  157. package/dist/http/device-placement.js +2 -1
  158. package/dist/http/dispatch.js +13 -7
  159. package/dist/http/durable-run-leg.d.ts +4 -32
  160. package/dist/http/durable-run-leg.js +37 -12
  161. package/dist/http/idempotency.d.ts +2 -2
  162. package/dist/http/idempotency.js +2 -2
  163. package/dist/http/owner-access.d.ts +56 -0
  164. package/dist/http/owner-access.js +42 -0
  165. package/dist/http/principal-gate.d.ts +78 -27
  166. package/dist/http/principal-gate.js +64 -14
  167. package/dist/http/readiness.d.ts +11 -5
  168. package/dist/http/readiness.js +10 -3
  169. package/dist/http/refusal-body.d.ts +12 -0
  170. package/dist/http/refusal-body.js +11 -0
  171. package/dist/http/request-guards.d.ts +16 -32
  172. package/dist/http/request-guards.js +31 -30
  173. package/dist/http/resume-ctx-read.d.ts +50 -6
  174. package/dist/http/resume-ctx-read.js +33 -7
  175. package/dist/http/resume-legs.d.ts +5 -5
  176. package/dist/http/resume-legs.js +163 -91
  177. package/dist/http/retired-service-deps.d.ts +43 -0
  178. package/dist/http/retired-service-deps.js +18 -0
  179. package/dist/http/route-ctx.d.ts +44 -37
  180. package/dist/http/route-ctx.js +4 -0
  181. package/dist/http/route-table.js +2 -0
  182. package/dist/http/routes/a2a-serve.js +3 -4
  183. package/dist/http/routes/admin-config-refresh.js +1 -1
  184. package/dist/http/routes/admin-drain.js +1 -1
  185. package/dist/http/routes/admin-memory-optout.js +5 -1
  186. package/dist/http/routes/adoption.js +2 -9
  187. package/dist/http/routes/agents-roster.js +2 -3
  188. package/dist/http/routes/approvals-assistant.js +91 -56
  189. package/dist/http/routes/background.js +3 -2
  190. package/dist/http/routes/capabilities.js +20 -4
  191. package/dist/http/routes/config-catalog.d.ts +3 -3
  192. package/dist/http/routes/config-catalog.js +1 -1
  193. package/dist/http/routes/devices.js +3 -17
  194. package/dist/http/routes/diagnostics.d.ts +3 -3
  195. package/dist/http/routes/diagnostics.js +6 -2
  196. package/dist/http/routes/fleet.js +4 -4
  197. package/dist/http/routes/images.js +6 -7
  198. package/dist/http/routes/leader.js +1 -8
  199. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  200. package/dist/http/routes/mcp-reconnect.js +3 -2
  201. package/dist/http/routes/memory-bundle.js +1 -1
  202. package/dist/http/routes/memory-compliance.js +1 -1
  203. package/dist/http/routes/memory-consolidation.js +1 -1
  204. package/dist/http/routes/memory-origin.d.ts +1 -1
  205. package/dist/http/routes/memory-origin.js +1 -1
  206. package/dist/http/routes/memory-policy.d.ts +1 -1
  207. package/dist/http/routes/memory-policy.js +3 -2
  208. package/dist/http/routes/notify-wake.js +8 -21
  209. package/dist/http/routes/observability.js +2 -2
  210. package/dist/http/routes/principal-inbox.d.ts +39 -0
  211. package/dist/http/routes/principal-inbox.js +76 -0
  212. package/dist/http/routes/retention-ops.js +2 -9
  213. package/dist/http/routes/rules.js +9 -22
  214. package/dist/http/routes/runs.d.ts +5 -0
  215. package/dist/http/routes/runs.js +63 -115
  216. package/dist/http/routes/session-sync.d.ts +3 -2
  217. package/dist/http/routes/session-sync.js +53 -48
  218. package/dist/http/routes/sessions-list.d.ts +1 -1
  219. package/dist/http/routes/sessions-list.js +3 -4
  220. package/dist/http/routes/sessions.js +33 -43
  221. package/dist/http/routes/side-query.js +6 -4
  222. package/dist/http/routes/tasks.js +71 -30
  223. package/dist/http/routes/trace-usage.js +7 -9
  224. package/dist/http/routes/workflows.d.ts +351 -0
  225. package/dist/http/routes/workflows.js +153 -119
  226. package/dist/http/run-declared-families.d.ts +16 -0
  227. package/dist/http/run-declared-families.js +12 -0
  228. package/dist/http/send.d.ts +24 -3
  229. package/dist/http/send.js +14 -2
  230. package/dist/http/server.d.ts +23 -18
  231. package/dist/http/server.js +20 -15
  232. package/dist/http/stored-body-replay.js +17 -4
  233. package/dist/http/submit-ctx.d.ts +4 -3
  234. package/dist/http/submit-ctx.js +23 -6
  235. package/dist/http/submit-replay.d.ts +4 -3
  236. package/dist/http/submit-replay.js +5 -4
  237. package/dist/http/wire-types.d.ts +17 -10
  238. package/dist/index.d.ts +3 -1
  239. package/dist/index.js +1 -1
  240. package/dist/lane-home-probe.d.ts +78 -9
  241. package/dist/lane-home-probe.js +78 -12
  242. package/dist/leader/endpoint.d.ts +4 -1
  243. package/dist/leader/endpoint.js +11 -10
  244. package/dist/leader/wire.d.ts +4 -0
  245. package/dist/leader/wire.js +8 -7
  246. package/dist/limit-refusal.d.ts +17 -5
  247. package/dist/limit-refusal.js +4 -1
  248. package/dist/main.js +1 -1
  249. package/dist/mcp-assertion-header.d.ts +31 -10
  250. package/dist/mcp-assertion-header.js +10 -3
  251. package/dist/memory-origin-fence.js +2 -2
  252. package/dist/memory-project-layer.d.ts +37 -0
  253. package/dist/memory-project-layer.js +46 -0
  254. package/dist/memory-scope.d.ts +23 -16
  255. package/dist/memory-scope.js +24 -8
  256. package/dist/memory-sync-client.d.ts +27 -13
  257. package/dist/memory-sync-client.js +107 -18
  258. package/dist/model-compat.d.ts +1 -1
  259. package/dist/model-entry-refusal.d.ts +9 -1
  260. package/dist/model-entry-refusal.js +6 -1
  261. package/dist/model-plane-face.d.ts +51 -0
  262. package/dist/model-plane-face.js +24 -0
  263. package/dist/model-provider.d.ts +5 -0
  264. package/dist/model-provider.js +4 -2
  265. package/dist/model-route-endpoint.d.ts +8 -11
  266. package/dist/model-route-endpoint.js +4 -7
  267. package/dist/model-route-env.d.ts +22 -0
  268. package/dist/model-route-env.js +2 -0
  269. package/dist/model-route-gap.d.ts +60 -30
  270. package/dist/model-route-gap.js +21 -15
  271. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  272. package/dist/observability/corrupt-read-seat.js +9 -0
  273. package/dist/observability/err-text.d.ts +6 -0
  274. package/dist/observability/err-text.js +18 -4
  275. package/dist/observability/fail-open.d.ts +35 -9
  276. package/dist/observability/fail-open.js +35 -9
  277. package/dist/observability/metrics.js +1 -0
  278. package/dist/observability/prompt-manifest.d.ts +22 -25
  279. package/dist/observability/prompt-manifest.js +54 -50
  280. package/dist/observability/tool-trace.js +9 -10
  281. package/dist/operator-ask.d.ts +10 -0
  282. package/dist/operator-ask.js +3 -0
  283. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  284. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  285. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  286. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  287. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  288. package/dist/orchestration/workflow-notify-journal.js +27 -34
  289. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  290. package/dist/orchestration/workflow-park-decision.js +119 -0
  291. package/dist/org-delivery-gate.d.ts +81 -0
  292. package/dist/org-delivery-gate.js +59 -0
  293. package/dist/panel-tool-names.d.ts +23 -0
  294. package/dist/panel-tool-names.js +8 -0
  295. package/dist/parked-decide.d.ts +43 -11
  296. package/dist/parked-decide.js +100 -51
  297. package/dist/parked-revive-surface.d.ts +9 -2
  298. package/dist/parked-revive-surface.js +11 -8
  299. package/dist/permission-rule-list.d.ts +1 -1
  300. package/dist/permission-rule-list.js +2 -2
  301. package/dist/permission-rule-vocab.d.ts +1 -23
  302. package/dist/permission-rule-vocab.js +0 -13
  303. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  304. package/dist/plugins/approval-ask-store-file.js +21 -0
  305. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  306. package/dist/plugins/approval-ask-store-memory.js +34 -2
  307. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  308. package/dist/plugins/approval-ask-store-sql.js +37 -1
  309. package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
  310. package/dist/plugins/approval-payload-fingerprint.js +1 -1
  311. package/dist/plugins/blob-backend.d.ts +38 -25
  312. package/dist/plugins/blob-backend.js +29 -19
  313. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  314. package/dist/plugins/breaker-state-sql.js +4 -4
  315. package/dist/plugins/caching-session-store.d.ts +4 -1
  316. package/dist/plugins/caching-session-store.js +7 -3
  317. package/dist/plugins/checkpoint-store-sql.d.ts +36 -1
  318. package/dist/plugins/checkpoint-store-sql.js +65 -3
  319. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  320. package/dist/plugins/file-history-store-sql.js +3 -1
  321. package/dist/plugins/file-run-store.d.ts +5 -13
  322. package/dist/plugins/file-run-store.js +9 -0
  323. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  324. package/dist/plugins/fork-routing-session-store.js +12 -1
  325. package/dist/plugins/host-platform.d.ts +2 -0
  326. package/dist/plugins/host-platform.js +2 -1
  327. package/dist/plugins/local-checkpoint-store.d.ts +15 -2
  328. package/dist/plugins/local-checkpoint-store.js +32 -1
  329. package/dist/plugins/local-session-store.d.ts +13 -10
  330. package/dist/plugins/local-session-store.js +23 -14
  331. package/dist/plugins/local-session-window.d.ts +45 -0
  332. package/dist/plugins/local-session-window.js +38 -0
  333. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  334. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  335. package/dist/plugins/mailbox-store-sql.js +77 -52
  336. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  337. package/dist/plugins/memory-run-store.d.ts +5 -13
  338. package/dist/plugins/memory-run-store.js +8 -0
  339. package/dist/plugins/one-time-migrations.d.ts +121 -5
  340. package/dist/plugins/one-time-migrations.js +332 -8
  341. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  342. package/dist/plugins/org-delivery-quota-store.js +228 -0
  343. package/dist/plugins/permission-rule-store-file.js +10 -6
  344. package/dist/plugins/permission-rule-store-sql.js +8 -8
  345. package/dist/plugins/pg-pool.js +39 -7
  346. package/dist/plugins/pg-session-storage.d.ts +18 -5
  347. package/dist/plugins/pg-session-storage.js +68 -23
  348. package/dist/plugins/remote-env-adb.d.ts +6 -12
  349. package/dist/plugins/remote-env-adb.js +12 -2
  350. package/dist/plugins/remote-env-device.d.ts +14 -7
  351. package/dist/plugins/remote-env-device.js +23 -15
  352. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  353. package/dist/plugins/remote-env-k8s.js +23 -5
  354. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  355. package/dist/plugins/remote-env-local-docker.js +12 -9
  356. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  357. package/dist/plugins/remote-env-ssh.js +17 -11
  358. package/dist/plugins/run-store-sql.d.ts +16 -14
  359. package/dist/plugins/run-store-sql.js +22 -2
  360. package/dist/plugins/schema-indexes.js +2 -0
  361. package/dist/plugins/send-user-file.js +2 -2
  362. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  363. package/dist/plugins/session-epoch-anchor.js +2 -3
  364. package/dist/plugins/session-ownership.d.ts +11 -0
  365. package/dist/plugins/session-ownership.js +11 -0
  366. package/dist/plugins/session-placement.d.ts +12 -14
  367. package/dist/plugins/session-placement.js +2 -15
  368. package/dist/plugins/session-store.d.ts +18 -8
  369. package/dist/plugins/session-store.js +15 -4
  370. package/dist/plugins/sql-driver.d.ts +74 -11
  371. package/dist/plugins/sql-driver.js +210 -12
  372. package/dist/plugins/sql-errors.d.ts +23 -0
  373. package/dist/plugins/sql-errors.js +21 -0
  374. package/dist/plugins/store-backend.d.ts +36 -1
  375. package/dist/plugins/store-backend.js +40 -14
  376. package/dist/plugins/store-contracts.d.ts +42 -0
  377. package/dist/plugins/store-contracts.js +1 -0
  378. package/dist/plugins/tidb-pool.d.ts +6 -1
  379. package/dist/plugins/tidb-pool.js +44 -10
  380. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  381. package/dist/plugins/tidb-session-storage.js +2 -2
  382. package/dist/plugins/tidb-session-store.d.ts +25 -5
  383. package/dist/plugins/tidb-session-store.js +67 -21
  384. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  385. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  386. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  387. package/dist/plugins/workflow-run-store-sql.js +50 -9
  388. package/dist/posture-source.d.ts +18 -10
  389. package/dist/posture-source.js +4 -1
  390. package/dist/project-identity.d.ts +45 -6
  391. package/dist/project-identity.js +162 -8
  392. package/dist/project-layer-key.d.ts +28 -0
  393. package/dist/project-layer-key.js +29 -0
  394. package/dist/question.js +3 -2
  395. package/dist/read-deny-entry.d.ts +25 -0
  396. package/dist/read-deny-entry.js +12 -0
  397. package/dist/read-face-posture.d.ts +37 -11
  398. package/dist/read-face-posture.js +32 -3
  399. package/dist/request-key-closure.d.ts +7 -0
  400. package/dist/request-key-closure.js +9 -1
  401. package/dist/request-tool-axes.d.ts +12 -0
  402. package/dist/request-tool-axes.js +20 -0
  403. package/dist/request-value-closure.d.ts +5 -0
  404. package/dist/request-value-closure.js +11 -3
  405. package/dist/rule-entry-list.d.ts +26 -2
  406. package/dist/rule-entry-list.js +72 -12
  407. package/dist/rules-consent.js +3 -4
  408. package/dist/run-acceptance.d.ts +19 -3
  409. package/dist/run-acceptance.js +13 -1
  410. package/dist/run-local.js +37 -6
  411. package/dist/runs.d.ts +12 -10
  412. package/dist/runs.js +25 -6
  413. package/dist/runtime-caps-resolver.d.ts +16 -6
  414. package/dist/runtime-caps-resolver.js +18 -5
  415. package/dist/sandbox-pkg-source.d.ts +19 -1
  416. package/dist/sandbox-pkg-source.js +29 -7
  417. package/dist/sealed-key.d.ts +32 -0
  418. package/dist/sealed-key.js +55 -1
  419. package/dist/security.d.ts +95 -15
  420. package/dist/security.js +52 -9
  421. package/dist/session-error-wire.d.ts +31 -7
  422. package/dist/session-error-wire.js +9 -2
  423. package/dist/session-sync-kernel.d.ts +37 -10
  424. package/dist/session-sync-kernel.js +10 -0
  425. package/dist/session-titled-frame.d.ts +33 -0
  426. package/dist/session-titled-frame.js +4 -0
  427. package/dist/session-titler.d.ts +9 -1
  428. package/dist/session-titler.js +15 -4
  429. package/dist/spec-fields.js +21 -2
  430. package/dist/sql-engine-posture.d.ts +3 -1
  431. package/dist/task-a2a.js +4 -3
  432. package/dist/task-cwd.d.ts +1 -1
  433. package/dist/task-mcp.d.ts +5 -5
  434. package/dist/task-mcp.js +27 -74
  435. package/dist/task-settings.d.ts +93 -88
  436. package/dist/task-settings.js +71 -63
  437. package/dist/text-bidi.d.ts +0 -4
  438. package/dist/text-bidi.js +1 -3
  439. package/dist/tighten-only-seats.d.ts +150 -0
  440. package/dist/tighten-only-seats.js +196 -0
  441. package/dist/tool-approval.d.ts +451 -136
  442. package/dist/tool-approval.js +733 -256
  443. package/dist/tool-rule-names.d.ts +6 -0
  444. package/dist/trace/core-keyset-guard.d.ts +108 -25
  445. package/dist/trace/exit-seat.d.ts +40 -0
  446. package/dist/trace/exit-seat.js +130 -0
  447. package/dist/trace/ledger-events.d.ts +6 -3
  448. package/dist/trace/project.d.ts +98 -13
  449. package/dist/trace/project.js +57 -32
  450. package/dist/trace/projection-table.d.ts +100 -0
  451. package/dist/trace/projection-table.js +130 -0
  452. package/dist/trace/redact.d.ts +57 -0
  453. package/dist/trace/redact.js +962 -168
  454. package/dist/trace/self-minted-wire.d.ts +349 -1
  455. package/dist/trace/self-minted-wire.js +118 -1
  456. package/dist/trace/wire-projection-faces.d.ts +304 -2
  457. package/dist/trace/wire-projection-faces.js +160 -13
  458. package/dist/url-refusal.js +2 -0
  459. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  460. package/dist/web-admin-client/apply-effective.js +56 -5
  461. package/dist/web-admin-client/facade.d.ts +1 -1
  462. package/dist/web-admin-client/facade.js +1 -1
  463. package/dist/web-admin-client/read-face.js +5 -9
  464. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  465. package/dist/web-admin-client/skills-mcp.js +6 -8
  466. package/dist/web-admin-client/types.d.ts +1 -1
  467. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  468. package/package.json +8 -4
  469. package/scripts/drain-check-local.mjs +34 -2
  470. package/scripts/drain-check.mysql.sql +20 -2
  471. package/scripts/drain-check.pg.sql +20 -2
  472. package/dist/mcp-tool-faces.d.ts +0 -69
  473. package/dist/mcp-tool-faces.js +0 -106
@@ -12,8 +12,8 @@ export function bodyCarriesAllowList(body) {
12
12
  const allow = permissions["allow"];
13
13
  return Array.isArray(allow) && allow.length > 0;
14
14
  }
15
- export function buildCheckpointCtx(fields) {
16
- return {
15
+ export function buildCheckpointCtx(fields, sealer, sessionId) {
16
+ const ctx = {
17
17
  body: fields.body,
18
18
  writerVersion: fields.writerVersion,
19
19
  ...(fields.memoryScope !== undefined ? { memoryScope: fields.memoryScope } : {}),
@@ -21,6 +21,7 @@ export function buildCheckpointCtx(fields) {
21
21
  ...(bodyCarriesAllowList(fields.body) ? { permissionsAllowReading: "allow_layer" } : {}),
22
22
  permissionModeReading: "entry_word",
23
23
  };
24
+ return sealCheckpointCtx(ctx, sealer, sessionId);
24
25
  }
25
26
  export function withPermissionModeRewritten(ctx, body) {
26
27
  return { ...ctx, body, permissionModeReading: "entry_word" };
@@ -32,10 +33,10 @@ export function permissionModeReadingStated(ctx) {
32
33
  export function permissionModeReadingRefusal() {
33
34
  return {
34
35
  status: 409,
35
- body: {
36
- error: "this task was suspended by an earlier server version that re-applied this deployment's AUTONOMY on every resume instead of recording it in the task; this version records the operator's plan floor once, when a task is submitted, so continuing would run this task under the permission mode it was submitted with rather than the one it ran under. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel); to let it finish with read-only hands instead, set AUTONOMY=read-only until it does.",
36
+ body: refusalBody({
37
37
  errorCode: "checkpoint.unsupported_version",
38
- },
38
+ message: "this task was suspended by an earlier server version that re-applied this deployment's AUTONOMY on every resume instead of recording it in the task; this version records the operator's plan floor once, when a task is submitted, so continuing would run this task under the permission mode it was submitted with rather than the one it ran under. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel); to let it finish with read-only hands instead, set AUTONOMY=read-only until it does.",
39
+ }),
39
40
  };
40
41
  }
41
42
  export function allowListReadingUnstated(ctx) {
@@ -53,18 +54,18 @@ export function allowListReadingRefusal(era) {
53
54
  case "list":
54
55
  return {
55
56
  status: 409,
56
- body: {
57
- error: "this task was suspended by an earlier server version that did not record how it read settings.permissions.allow (7.114.0 and earlier read it as a whitelist: every tool not on the list was refused); this version hands that list to the engine's allow layer, where each entry is a standing yes for the calls it covers, so continuing would give the task more tools than it was submitted with. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel). To allow only certain tools, use the session rules' toolAllow (PUT /v1/sessions/:id/policy) or the request's excludeTools.",
57
+ body: refusalBody({
58
58
  errorCode: "checkpoint.unsupported_version",
59
- },
59
+ message: "this task was suspended by an earlier server version that did not record how it read settings.permissions.allow (7.114.0 and earlier read it as a whitelist: every tool not on the list was refused); this version hands that list to the engine's allow layer, where each entry is a standing yes for the calls it covers, so continuing would give the task more tools than it was submitted with. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel). To allow only certain tools, use the session rules' toolAllow (PUT /v1/sessions/:id/policy) or the request's excludeTools.",
60
+ }),
60
61
  };
61
62
  case "statement":
62
63
  return {
63
64
  status: 409,
64
- body: {
65
- error: "this task was suspended by an earlier server version (7.115.0 to 7.116.x) that read settings.permissions.allow as a statement that the named tools are allowed, which answered only the question nobody else had answered and never cleared an ordinary question such as a file write or a shell command; this version hands that list to the engine's allow layer, where an entry also clears those ordinary questions, so continuing would run calls without asking that the task was submitted to ask about. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel).",
65
+ body: refusalBody({
66
66
  errorCode: "checkpoint.unsupported_version",
67
- },
67
+ message: "this task was suspended by an earlier server version (7.115.0 to 7.116.x) that read settings.permissions.allow as a statement that the named tools are allowed, which answered only the question nobody else had answered and never cleared an ordinary question such as a file write or a shell command; this version hands that list to the engine's allow layer, where an entry also clears those ordinary questions, so continuing would run calls without asking that the task was submitted to ask about. Nothing was decided and nothing was resumed, and retrying will be refused the same way: submit the work again as a new task, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel).",
68
+ }),
68
69
  };
69
70
  default: {
70
71
  const unhandled = era;
@@ -78,9 +79,12 @@ export function buildCheckpointVersionKeys(writerVersion, readerVersion) {
78
79
  export function resumeBlockedByPolicyAnswer(inner) {
79
80
  return {
80
81
  status: 409,
81
- body: refusalBody({ errorCode: "resume_blocked_by_policy", message: `resume blocked by an admission policy change: ${inner.message}`, facts: { blockedBy: inner.errorCode, ...inner.facts } }),
82
+ body: refusalBody({ errorCode: "resume_blocked_by_policy", message: `resume blocked by an admission policy change: ${inner.message} — nothing was resumed; if the task is still suspended on its approval, cancel it (POST /v1/runs/:id/cancel) to end it without another model turn`, facts: { blockedBy: inner.errorCode, ...inner.facts } }),
82
83
  };
83
84
  }
85
+ export function isResumeBlockedByPolicy(answer) {
86
+ return answer.status === 409 && typeof answer.body === "object" && answer.body !== null && answer.body.errorCode === "resume_blocked_by_policy";
87
+ }
84
88
  export function resumeRefusalWithCard(answer, cardPending) {
85
89
  return cardPending ? { status: answer.status, body: { ...answer.body, retriable: true } } : answer;
86
90
  }
@@ -119,4 +123,159 @@ function storedBodyReplayArmAnswer(refusal, readerVersion) {
119
123
  }
120
124
  }
121
125
  }
126
+ export const CHECKPOINT_CTX_SEAL_ALG = "checkpoint-ctx-sealedbox-v1";
127
+ export const CHECKPOINT_CTX_CREDENTIAL_SLOTS = [
128
+ { path: ["mcpServers", "*", "transport", "headers"], holds: "map" },
129
+ { path: ["mcpServers", "*", "transport", "env"], holds: "map" },
130
+ { path: ["a2aPeers", "*", "headers"], holds: "map" },
131
+ { path: ["settings", "env"], holds: "map" },
132
+ { path: ["settings", "webSearch", "apiKey"], holds: "value" },
133
+ { path: ["settings", "hooks", "*", "*", "hooks", "*", "headers"], holds: "map" },
134
+ ];
135
+ export const CHECKPOINT_CTX_UNSEALABLE_REASONS = ["no_key_store", "key_not_held", "unopenable", "plaintext", "unrecognized_seal"];
136
+ export class CheckpointCtxUnsealableError extends Error {
137
+ field;
138
+ reason;
139
+ constructor(field, reason) {
140
+ super(`checkpoint ctx credential at ${field} cannot be ${reason === "no_key_store" ? "sealed or opened without a sealed-key store" : `opened (${reason})`}`);
141
+ this.name = "CheckpointCtxUnsealableError";
142
+ this.field = field;
143
+ this.reason = reason;
144
+ }
145
+ }
146
+ function mintSealedCheckpointCtx(sealed) {
147
+ return sealed;
148
+ }
149
+ export const CHECKPOINT_CTX_SEALING_REQUIRED = "a durable checkpoint store is wired but checkpointCtxSealing is not: suspended tasks keep the request's credentials (MCP / A2A headers and env values, settings.env, settings.webSearch.apiKey, http hook headers) in their resume context, and they are stored sealed or not at all — give the service a sealed-key store for them (this service builds it under <data root>/sealed-key/checkpoint-ctx-keys/ at boot; a failure there is the earlier checkpoint_ctx_sealing_unavailable warning — make that directory creatable and chmod-able by the service, or repair or remove a key file there whose public and private halves do not belong together), or, when embedding, pass checkpointCtxSealing: await ensureCheckpointCtxSealing(sealedKeyDir); refusing to start rather than write credentials in plaintext";
150
+ const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
151
+ export function isSealedCheckpointValue(v) {
152
+ if (!isRecord(v))
153
+ return false;
154
+ const keys = Object.keys(v);
155
+ return keys.length === 3 && v["alg"] === CHECKPOINT_CTX_SEAL_ALG && typeof v["publicKeyId"] === "string" && typeof v["sealed"] === "string";
156
+ }
157
+ function defineOwn(target, key, value) {
158
+ Object.defineProperty(target, key, { value, enumerable: true, writable: true, configurable: true });
159
+ }
160
+ function mapCredentialSlots(body, visit) {
161
+ let out = body;
162
+ for (const slot of CHECKPOINT_CTX_CREDENTIAL_SLOTS)
163
+ out = mapAt(out, slot.path, 0, slot.holds, "", visit);
164
+ return out;
165
+ }
166
+ function mapAt(node, path, i, holds, field, visit) {
167
+ if (i === path.length) {
168
+ if (holds === "value")
169
+ return visit(node, field);
170
+ if (!isRecord(node) || isSealedCheckpointValue(node))
171
+ return visit(node, field);
172
+ let copy;
173
+ for (const [k, v] of Object.entries(node)) {
174
+ const next = visit(v, memberField(field, k));
175
+ if (next !== v)
176
+ defineOwn((copy ??= { ...node }), k, next);
177
+ }
178
+ return copy ?? node;
179
+ }
180
+ const seg = path[i];
181
+ if (seg === "*") {
182
+ if (Array.isArray(node)) {
183
+ let copy;
184
+ node.forEach((el, idx) => {
185
+ const next = mapAt(el, path, i + 1, holds, `${field}[${idx}]`, visit);
186
+ if (next !== el)
187
+ (copy ??= [...node])[idx] = next;
188
+ });
189
+ return copy ?? node;
190
+ }
191
+ if (!isRecord(node))
192
+ return node;
193
+ let copy;
194
+ for (const [k, v] of Object.entries(node)) {
195
+ const next = mapAt(v, path, i + 1, holds, memberField(field, k), visit);
196
+ if (next !== v)
197
+ defineOwn((copy ??= { ...node }), k, next);
198
+ }
199
+ return copy ?? node;
200
+ }
201
+ if (!isRecord(node) || !Object.hasOwn(node, seg))
202
+ return node;
203
+ const child = node[seg];
204
+ const next = mapAt(child, path, i + 1, holds, memberField(field, seg), visit);
205
+ if (next === child)
206
+ return node;
207
+ const copy = { ...node };
208
+ defineOwn(copy, seg, next);
209
+ return copy;
210
+ }
211
+ function memberField(field, key) {
212
+ return field === "" ? key : `${field}.${key}`;
213
+ }
214
+ function sealBody(body, sealer, sessionId) {
215
+ let valuesSealed = 0;
216
+ const sealed = mapCredentialSlots(body, (value, field) => {
217
+ if (sealer === undefined)
218
+ throw new CheckpointCtxUnsealableError(field, "no_key_store");
219
+ valuesSealed += 1;
220
+ return sealer.seal(value, sessionId);
221
+ });
222
+ return { body: sealed, valuesSealed };
223
+ }
224
+ export function sealCheckpointCtx(ctx, sealer, sessionId) {
225
+ const { body } = sealBody(ctx.body, sealer, sessionId);
226
+ return mintSealedCheckpointCtx({ ...ctx, body: body, credentialSeal: CHECKPOINT_CTX_SEAL_ALG });
227
+ }
228
+ export function openCheckpointCtx(stored, opener, sessionId) {
229
+ const { credentialSeal, ...rest } = stored;
230
+ const stamp = credentialSeal;
231
+ try {
232
+ const body = mapCredentialSlots(stored.body, (value, field) => {
233
+ if (stamp === undefined)
234
+ throw new CheckpointCtxUnsealableError(field, "plaintext");
235
+ if (stamp !== CHECKPOINT_CTX_SEAL_ALG)
236
+ throw new CheckpointCtxUnsealableError(field, "unrecognized_seal");
237
+ if (isSealedCheckpointValue(value)) {
238
+ if (opener === undefined)
239
+ throw new CheckpointCtxUnsealableError(field, "no_key_store");
240
+ if (!opener.holds(value.publicKeyId))
241
+ throw new CheckpointCtxUnsealableError(field, "key_not_held");
242
+ try {
243
+ return opener.open(value, sessionId);
244
+ }
245
+ catch {
246
+ throw new CheckpointCtxUnsealableError(field, "unopenable");
247
+ }
248
+ }
249
+ if (isRecord(value) && Object.hasOwn(value, "sealed"))
250
+ throw new CheckpointCtxUnsealableError(field, "unrecognized_seal");
251
+ throw new CheckpointCtxUnsealableError(field, "plaintext");
252
+ });
253
+ return { kind: "ok", ctx: { ...rest, body: body } };
254
+ }
255
+ catch (e) {
256
+ if (e instanceof CheckpointCtxUnsealableError)
257
+ return { kind: "unsealable", field: e.field, reason: e.reason };
258
+ throw e;
259
+ }
260
+ }
261
+ export function sealedCredentialFieldOf(stored) {
262
+ if (!isRecord(stored))
263
+ return undefined;
264
+ let first;
265
+ mapCredentialSlots(stored["body"], (value, field) => {
266
+ if (first === undefined && isSealedCheckpointValue(value))
267
+ first = field;
268
+ return value;
269
+ });
270
+ return first;
271
+ }
272
+ export function sealStoredCheckpointCtxM28(stored, sealer, sessionId) {
273
+ if (stored.credentialSeal !== undefined)
274
+ return undefined;
275
+ const body = stored.body;
276
+ if (!isRecord(body))
277
+ return undefined;
278
+ const out = sealBody(body, sealer, sessionId);
279
+ return out.valuesSealed === 0 ? undefined : { ctx: mintSealedCheckpointCtx({ ...stored, body: out.body, credentialSeal: CHECKPOINT_CTX_SEAL_ALG }), valuesSealed: out.valuesSealed };
280
+ }
122
281
  //# sourceMappingURL=checkpoint-ctx.js.map
@@ -1,11 +1,12 @@
1
1
  /**
2
- * 一条提交腿**刚认领**的 run 在起跑之前就收场 —— 撤掉本请求建的东西的**唯一**写法。两个调用点:device 落点拒
3
- * (`device-placement.ts` `commitPlacement`)与续跑输入写不进(`submit-ctx.ts` `persistSubmitCtx`)。
2
+ * 一条提交腿**刚认领**的 run 在起跑之前就收场 —— 撤掉本请求建的东西的**唯一**写法。三个调用点:device 落点拒
3
+ * (`device-placement.ts` `commitPlacement`)、续跑输入写不进(`submit-ctx.ts` `persistSubmitCtx`)与 workflow 决定行没落成
4
+ * (`durable-run-leg.ts` 的 fresh 投递腿;此刻认领可能已被收割归了别人 —— 两步都按这一跑自己的 taskId,碰不到别人的认领)。
4
5
  *
5
6
  * 撤两步,**各自独立**(一步失败不拦另一步,残余最小):
6
7
  * · 终结这条 run 行(`setTerminal` 是按 taskId 的 CAS,首写者赢 ⇒ 重复调用是 no-op)—— 随之释放它的 `task_active` 认领;
7
8
  * · 放开它占的提交幂等键(拒绝答复邀请重试;同键重试必须真跑,不是回放这次拒绝 —— `RunStore.releaseIdemKey`)。
8
- * 撤不掉不致命、但要响:每一步的失败各交给调用方按自己的名字留痕(`onFailure`)。终结没落下 ⇒ 此刻心跳还没起来,`reapStale`
9
+ * 撤不掉不致命、但要响:每一步的失败各交给调用方按自己的名字留痕(`onFailure`)。终结没落下 ⇒ 起跑前的心跳随调用腿收场停下(或从没起过),`reapStale`
9
10
  * 在 `REAP_RUN_STALE_SEC` 之后把这条行翻 failed 并释放会话;幂等键没放开 ⇒ 同键重提回放这条行的回执(两形都是修前每一次的样子)。
10
11
  */
11
12
  import type { RunStore } from "../plugins/store-backend.js";
@@ -53,6 +53,7 @@ import { type DeviceOwner } from "../device-store.js";
53
53
  import { type DeviceEnrollment, type DeviceRejection } from "../device-enrollment.js";
54
54
  import type { ServiceConfig } from "../config.js";
55
55
  import type { RunStore } from "../plugins/store-backend.js";
56
+ import { type RefusalBody } from "./refusal-body.js";
56
57
  /**
57
58
  * 调用方 device 域的**唯一铸造点**。`undefined` = 判不出域(无 principal,或凭据不带 tenant claim)——
58
59
  * 消费点必须响亮拒,禁静默空视图。
@@ -170,8 +171,5 @@ export declare function placementWriteDeadlineMs(runStaleSec: number | undefined
170
171
  */
171
172
  export declare function commitPlacement(ctx: PlacementCommitCtx, runStore: RunStore, taskId: string, intent: DevicePlacementIntent | undefined): Promise<DeviceRejection | null>;
172
173
  /** 拒绝的**唯一** wire 体铸点(四个消费点各自用自己协议的发送姿势,但体的键集只有这一份)。 */
173
- export declare function devicePlacementErrorBody(rej: DeviceRejection): {
174
- error: string;
175
- errorCode: string;
176
- };
174
+ export declare function devicePlacementErrorBody(rej: DeviceRejection): RefusalBody;
177
175
  //# sourceMappingURL=device-placement.d.ts.map
@@ -3,6 +3,7 @@ import { gatedPrincipal } from "./principal-gate.js";
3
3
  import { DEVICE_ERROR_CODES, assertDeviceIdShape, } from "../device-store.js";
4
4
  import { buildDeviceRejection } from "../device-enrollment.js";
5
5
  import { releaseClaimedRun } from "./claimed-run.js";
6
+ import { refusalBody } from "./refusal-body.js";
6
7
  export function deviceOwnerDomainOf(req, config) {
7
8
  const subject = gatedPrincipal(req, config);
8
9
  if (subject === undefined)
@@ -139,6 +140,6 @@ export async function commitPlacement(ctx, runStore, taskId, intent) {
139
140
  return rejection;
140
141
  }
141
142
  export function devicePlacementErrorBody(rej) {
142
- return { error: rej.message, errorCode: rej.code };
143
+ return refusalBody({ errorCode: rej.code, message: rej.message });
143
144
  }
144
145
  //# sourceMappingURL=device-placement.js.map
@@ -1,21 +1,21 @@
1
1
  import { createHash } from "node:crypto";
2
- import { setSsoPrincipal, ssoVerifiedPrincipal, setSsoScope, isDestructiveSessionWrite, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../security.js";
2
+ import { setSsoPrincipal, ssoVerifiedPrincipal, setSsoScope, setSsoRole, isDestructiveSessionWrite, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../security.js";
3
3
  import { publicStoreProbeError } from "../store-live-probe.js";
4
4
  import { looksLikeJwt } from "@sema-agent/settings-schema/api/auth-bridge";
5
5
  import { ROUTE_METHOD_ORDER } from "./route-ctx.js";
6
6
  import { READ_CREDENTIAL_ROUTES, PUBLIC_ROUTES, POST_CREDENTIAL_ROUTES, routeLabel, isBillableSubmitPath, billableKindOf, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, lookupRoute, isProbePath, isSubscriptionRequest } from "./route-table.js";
7
7
  import { sendJson, sendError, isSseResponse, endSseWithError } from "./send.js";
8
- import { admissionRefusalOf, readinessOf, healthReadinessKeys, sendReadyz, sendBillableRefusal, billableRefusalOf } from "./readiness.js";
8
+ import { admissionRefusalOf, readinessOf, healthReadinessKeys, sendReadyz, sendBillableRefusal, billableRefusalOf, billableRefusalFrame } from "./readiness.js";
9
9
  import { ENGINE_SIGNAL_KEY, buildEngineSignal, fleetMembershipKeys, healthConfigLedgerKeys, healthDrainingKeys, mintEngineSignal, restartActionable } from "../fleet/engine-signal.js";
10
10
  import { buildHealthSelfReport } from "./health-self-report.js";
11
- import { authorized, systemFor, gatedPrincipal, sendPrincipalRefusal, sendUnauthorized, verifiedIdentitySource, hasServiceAuth, devOpenDeployment } from "./principal-gate.js";
11
+ import { actsForDeployment, authorized, systemFor, gatedPrincipal, sendPrincipalRefusal, sendUnauthorized, traceTokenPresented, verifiedIdentitySource, hasServiceAuth, devOpenDeployment } from "./principal-gate.js";
12
12
  const PROCESS_STARTED_AT_MS = Date.now() - Math.round(process.uptime() * 1000);
13
13
  export function readCredentialOk(req, config) {
14
14
  if (!hasServiceAuth(config))
15
15
  return true;
16
16
  if (verifiedIdentitySource(req, config) !== undefined)
17
17
  return true;
18
- return config.traceToken !== undefined && config.traceToken !== "" && authorized(req, config.traceToken);
18
+ return traceTokenPresented(req, config);
19
19
  }
20
20
  function cors(res, req, origins, principalHeader) {
21
21
  if (!origins || origins.length === 0)
@@ -51,10 +51,10 @@ export function createDispatch(ctx) {
51
51
  };
52
52
  deps.drainState.lastAttachEndedAt = () => lastAttachEndedAt;
53
53
  deps.drainState.endSubscriptions = () => {
54
- const { errorCode, message } = billableRefusalOf("draining").body;
54
+ const frame = billableRefusalFrame(billableRefusalOf("draining"));
55
55
  for (const r of [...openSubscriptions])
56
56
  if (isSseResponse(r))
57
- endSseWithError(r, { errorCode, message });
57
+ endSseWithError(r, frame);
58
58
  };
59
59
  }
60
60
  async function dispatchSegment(rows, req, res, url, search, method, allow, ctx, admit) {
@@ -159,6 +159,10 @@ export function createDispatch(ctx) {
159
159
  const credential = deps.centerCredentialState?.();
160
160
  return credential ? { centerCredential: credential } : {};
161
161
  })(),
162
+ ...(() => {
163
+ const identityNotice = deps.centerIdentityNoticeState?.();
164
+ return identityNotice ? { centerIdentityNotice: identityNotice } : {};
165
+ })(),
162
166
  ...(() => {
163
167
  const modelRefusals = deps.modelRefusalsState?.();
164
168
  return modelRefusals ? { modelRefusals } : {};
@@ -187,7 +191,7 @@ export function createDispatch(ctx) {
187
191
  }
188
192
  const mt = deps.config.metricsToken;
189
193
  const devOpen = devOpenDeployment(deps) && !mt;
190
- const ok = devOpen || systemFor(req, deps.config) !== undefined || (!!mt && authorized(req, mt));
194
+ const ok = devOpen || (!!mt && authorized(req, mt)) || actsForDeployment(req, deps.config, () => gatedPrincipal(req, deps.config));
191
195
  if (!ok) {
192
196
  sendUnauthorized(res, "operator");
193
197
  return;
@@ -214,6 +218,8 @@ export function createDispatch(ctx) {
214
218
  req.headers[deps.config.principalHeader.toLowerCase()] = v.identity.principal;
215
219
  if (v.identity.scope)
216
220
  setSsoScope(req, v.identity.scope);
221
+ if (v.identity.role)
222
+ setSsoRole(req, v.identity.role);
217
223
  deps.logger?.info?.("auth_bridge_principal_accepted", { principal: v.identity.principal, ...(v.identity.scope ? { scope: v.identity.scope } : {}) });
218
224
  }
219
225
  }
@@ -1,35 +1,6 @@
1
- /**
2
- * **一条 durable run 的「建行 + 驱动」单一属主**(S-218 提取;此前整段住在 `routes/runs.ts` 的
3
- * `createDurableRun` 里,只服务 HTTP/A2A 两条提交门)。
4
- *
5
- * 🔴 为什么提成模块:`/decide` 的 workflow 第三条车道在**宿主不在 park 上**时,同样要在宿主会话上起
6
- * 一跑新 turn 把决定交给宿主的模型(S-218)。这条链上挂着 `createRun` 的会话 claim(以及它唯一诚实的
7
- * 409 出路)、checkpoint ctx 落库、fleet 行发布、resume/rewind 两族锚点捕获、审批 ALS、通告投递……
8
- * 手抄第二份 = 把这十来件事复制成两份会漂的实现,而漂开的那天没有任何东西会说话(`createDurableRun`
9
- * 当年从路由体里提取出来时,头注写的就是同一条判词)。方向:`routes/runs.ts` 与 `http/server.ts`
10
- * 都 import 本模块,本模块谁都不 import —— 与 `http/run-meta.ts` 同一条「两个域共用一件 ⇒ 单独成文件」。
11
- *
12
- * 边界(本腿**不**含的东西,留给各自的门):同键重放的回执(`http/submit-replay.ts`)、`Idempotency-Key` 的在飞合流、
13
- * lease / 治理窗 pre-admission、属主门。它们是**提交面**的判据(读请求、写响应),而本腿只吃已经备好的
14
- * `PreparedTaskSubmission` 并交回一份收据 —— 这正是它能被一条没有 `ServerResponse` 的内部车道复用的原因。
15
- */
16
- import { type RunInternals } from "@sema-agent/core";
17
1
  import type { RunStore } from "../plugins/store-backend.js";
18
2
  import type { RunIdemBinding, RunRecord } from "../plugins/store-contracts.js";
19
- import type { PreparedTaskSubmission, RouteCtxBase } from "./route-ctx.js";
20
- /**
21
- * 🔴 **TRUSTED run internals** —— 由**部署方**(不是模型、不是请求体、不是工具参数)铸给这一跑的
22
- * core 内部席位。今天唯一成员 `workflowParkedResume` = 人对一条 parked workflow 子代的决定
23
- * (语义属主 = core `RunInternals.workflowParkedResume` 的 d.ts 顶注:「A host that decided a workflow
24
- * child's parked checkpoint launches the run that re-invokes `Workflow({resumeFromRunId})` with the
25
- * decision here」)。
26
- *
27
- * 为什么单独命名而不是直接摊 `RunInternals`:`RunInternals` 里绝大多数席位是**执行腿自己**铸的
28
- * (onForwardEvent / onTaskNotification / onActivity …),把整只类型开给调用方等于邀请第二个写者;
29
- * 本类型只开「部署方可以决定的那一格」,新增一格时**必须**在这里显式点名,编译期看得见。
30
- * 缺席 ⇒ 对两条腿都是完整 no-op。
31
- */
32
- export type TrustedRunInternals = Pick<RunInternals, "workflowParkedResume">;
3
+ import type { PreparedTaskSubmission, RouteCtxBase, WorkflowDecisionDelivery } from "./route-ctx.js";
33
4
  export interface DurableRunLegArgs {
34
5
  /** `prepareSpec` 的产物,或内部车道按同一条 `resolveSpec` 装配出来的等价形。 */
35
6
  prepared: PreparedTaskSubmission;
@@ -49,8 +20,9 @@ export interface DurableRunLegArgs {
49
20
  elicitOwner: string | null;
50
21
  /** run 行元数据的 `source` 列(调用方的系统身份;内部车道传自己的车道名)。 */
51
22
  source: string | null;
52
- /** 见 {@link TrustedRunInternals}。缺席 ⇒ 与本位存在之前逐字相同。 */
53
- trustedInternals?: TrustedRunInternals;
23
+ /** `/decide` 第三条车道的 fresh 投递腿交来的那一件决定投递(带着的决定 + 起跑之前落行的那一笔;语义与 TRUSTED 纪律的属主 =
24
+ * `route-ctx.ts` 的 {@link WorkflowDecisionDelivery} 顶注)。缺席 ⇒ 只摊本会话已受理的决定行。 */
25
+ workflowDecision?: WorkflowDecisionDelivery;
54
26
  }
55
27
  /**
56
28
  * 本腿的结局:一份收据,或「这次提交的一把幂等钥匙已经指向一条行」(店的原子赢或观察的**观察**臂 —— 本腿不碰
@@ -1,20 +1,23 @@
1
1
  import { uuidv7 } from "@sema-agent/core";
2
- import { runInBackground } from "../runs.js";
2
+ import { heldWorkflowParkDecisions } from "../parked-decide.js";
3
+ import { HEARTBEAT_MS, runInBackground } from "../runs.js";
3
4
  import { fleetRunPublisher, fleetRunLabels } from "../fleet/fleet-bus.js";
4
5
  import { cascadeConfig, runMeta } from "./run-meta.js";
5
- import { resolveStreamApprovalGate } from "../tool-approval.js";
6
+ import { declaredApprovalFrameFamilies, resolveStreamApprovalGate } from "../tool-approval.js";
6
7
  import { buildActiveRunConflict } from "./active-run-conflict.js";
7
8
  import { commitPlacement, devicePlacementErrorBody } from "./device-placement.js";
8
9
  import { commitSessionInheritEnv } from "./session-inherit-env.js";
9
10
  import { clearTurnActivity, readTurnActivityMs } from "../turn-activity.js";
10
11
  import { recordResourceWindow } from "../resource-window.js";
11
12
  import { persistSubmitCtx } from "./submit-ctx.js";
13
+ import { releaseClaimedRun } from "./claimed-run.js";
12
14
  import { serviceVersion } from "../service-version.js";
13
15
  export async function mintAndDriveDurableRun(ctx, runStore, args) {
14
16
  const { deps } = ctx;
15
17
  const { inflightRuns, preemptableRuns, steerableRuns } = ctx.registry;
16
18
  const sessionId = args.prepared.spec.sessionId ?? uuidv7();
17
19
  const taskId = args.clientTaskId ?? uuidv7();
20
+ const trustedInternals = await heldWorkflowParkDecisions(deps, sessionId, args.workflowDecision?.carried);
18
21
  const created = await runStore.createRun(taskId, sessionId, args.prepared.auth?.principal ?? null, deps.instanceId ?? "default", { ...runMeta(args.prepared, args.source), idem: args.idem ?? null });
19
22
  if (created.ok)
20
23
  clearTurnActivity(taskId);
@@ -25,13 +28,34 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
25
28
  if (!created.ok) {
26
29
  return { status: 409, body: await buildActiveRunConflict({ runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, sessionId, created.activeTaskId) };
27
30
  }
28
- const placementReject = await commitPlacement(deps, runStore, taskId, args.prepared.bindingIntent);
29
- if (placementReject)
30
- return { status: placementReject.status, body: devicePlacementErrorBody(placementReject) };
31
- if (deps.checkpointStore) {
32
- const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, { runStore, taskId }, sessionId, { body: args.prepared.body, memoryScope: args.prepared.auth?.memoryScope, writerVersion: serviceVersion() });
33
- if (ctxRefusal)
34
- return ctxRefusal;
31
+ const owner = args.prepared.auth?.principal ?? null;
32
+ const preLaunchHeartbeat = setInterval(() => {
33
+ void runStore.heartbeat(taskId, owner).catch(() => { deps.metrics?.inc("run_signal_poll_errors_total", { kind: "heartbeat" }); });
34
+ }, HEARTBEAT_MS);
35
+ preLaunchHeartbeat.unref?.();
36
+ try {
37
+ const placementReject = await commitPlacement(deps, runStore, taskId, args.prepared.bindingIntent);
38
+ if (placementReject)
39
+ return { status: placementReject.status, body: devicePlacementErrorBody(placementReject) };
40
+ if (deps.checkpointStore) {
41
+ const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, { runStore, taskId }, sessionId, { body: args.prepared.body, memoryScope: args.prepared.auth?.memoryScope, writerVersion: serviceVersion() });
42
+ if (ctxRefusal)
43
+ return ctxRefusal;
44
+ }
45
+ if (args.workflowDecision !== undefined) {
46
+ try {
47
+ await args.workflowDecision.commitBeforeLaunch(taskId);
48
+ }
49
+ catch (err) {
50
+ await releaseClaimedRun(runStore, taskId, `the workflow decision this run delivers could not be recorded: ${err instanceof Error ? err.message : String(err)}`, (releaseErr, step) => {
51
+ deps.logger?.warn?.("workflow_decision_run_release_failed", { taskId, sessionId, step, err: releaseErr instanceof Error ? releaseErr.message : String(releaseErr) });
52
+ });
53
+ throw err;
54
+ }
55
+ }
56
+ }
57
+ finally {
58
+ clearInterval(preLaunchHeartbeat);
35
59
  }
36
60
  commitSessionInheritEnv(deps, args.prepared.spec.sessionId, args.prepared.body);
37
61
  const anchorOwner = args.prepared.auth?.principal ?? null;
@@ -60,12 +84,13 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
60
84
  toolApprovalEnabled: true,
61
85
  streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
62
86
  backend: deps.backend,
63
- parkFacility: deps.checkpointStore !== undefined,
87
+ checkpointStore: deps.checkpointStore,
64
88
  }).active,
65
89
  windowMs: deps.config.streamApproval?.windowMs,
66
90
  windowMarginMs: deps.config.streamAskWindowMarginMs,
91
+ declaredFamilies: declaredApprovalFrameFamilies(args.prepared.body.settings),
67
92
  }
68
- : undefined, deps.checkpointStore, args.prepared.engineNotices, args.trustedInternals, deps.userInputLedger, args.prepared.acceptance);
69
- return { status: 202, body: { taskId, sessionId, status: "running" } };
93
+ : undefined, deps.checkpointStore, args.prepared.engineNotices, trustedInternals, deps.userInputLedger, args.prepared.acceptance);
94
+ return { status: 202, body: { taskId, sessionId, status: "running", ...(args.prepared.warnings !== undefined ? { warnings: args.prepared.warnings } : {}) } };
70
95
  }
71
96
  //# sourceMappingURL=durable-run-leg.js.map
@@ -80,11 +80,11 @@ export declare function idemIdentityOf(caller: IdemCaller): string;
80
80
  export declare function idemKeyOf(raw: string, caller: IdemCaller, family: IdemFamily): string;
81
81
  /**
82
82
  * 一次提交的**请求体指纹** —— HTTP 三条提交腿(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`)同一只规范化函数:
83
- * `sha256(canonicalJson(体 − taskId))` 的 hex(定宽 64)。
83
+ * `sha256(canonicalJsonStringify(体 − taskId))` 的 hex(定宽 64)。
84
84
  *
85
85
  * 幂等 = 同一调用方、同一键、**同一请求**:账本行记下绑定 `Idempotency-Key` 的那次请求的指纹(`task_run.idem_body_fingerprint`),
86
86
  * 同键再投而指纹不同 ⇒ 唯一回执函数答 409(`http/submit-replay.ts`)。规范化只有两步:
87
- * · JSON 按键递归排序(唯一序列化器 `canonicalJson`;值为 `undefined` 的键与缺席同义)—— 键序不同的同一份体是同一请求;
87
+ * · JSON 按键递归排序(唯一序列化器 core `canonicalJsonStringify`;值为 `undefined` 的键与缺席同义)—— 键序不同的同一份体是同一请求;
88
88
  * · 去掉 `taskId` —— 它是同一条律的**另一把钥匙**(调用方自铸的主键),由回执函数的「钥匙指向别的行 ⇒ `conflict.run_exists`」判,
89
89
  * 不是请求内容(换腿重投:流式腿不带 → durable 腿带回 `x-task-id`,仍是同一请求)。
90
90
  * 头一概不进:身份已在键里(`idemKeyOf` 的身份位),其余头(`Idempotency-Key` 本身、`x-detach-on-disconnect` 一类连接语义)不是提交内容。
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { canonicalJson } from "../canonical-json.js";
2
+ import { canonicalJsonStringify } from "@sema-agent/core";
3
3
  import { gatedPrincipal } from "./principal-gate.js";
4
4
  export class IdempotencyCache {
5
5
  ttlMs;
@@ -80,7 +80,7 @@ export function idemKeyOf(raw, caller, family) {
80
80
  }
81
81
  export function submissionFingerprintOf(body) {
82
82
  const content = body !== null && typeof body === "object" && !Array.isArray(body) ? { ...body, taskId: undefined } : body;
83
- return createHash("sha256").update(canonicalJson(content)).digest("hex");
83
+ return createHash("sha256").update(canonicalJsonStringify(content)).digest("hex");
84
84
  }
85
85
  export function submissionIdemOf(raw, caller, body) {
86
86
  return { key: idemKeyOf(raw, caller, "run"), bodyFingerprint: submissionFingerprintOf(body) };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * 🔴 **属主存取器**(S-487 RH-3 第一期)——「这个调用方读得到这一行 run / 会话吗」的行只经这里取得。
3
+ *
4
+ * ## 律(一条)
5
+ * 判官只有一只:run 行 = `principal-gate.ts` 的 `runOwnerReadable`(三条放行臂,含 [ref] C8 窄互认),会话行 = `sessionOwnerReadable`
6
+ * (dev-open 不钉人;无主行经 `security.ts` 的 `ownerlessRowOpen`;有主行就是 run 那一只)。本模块**不判第二遍、不另写一条**:它只做三件事 ——
7
+ * · 取行(或收下调用点已读到的行)并把行上的属主铸成 `DurableOwnerKey`(品牌铸点之一,见 `security.ts`);
8
+ * · 过判官,读不到 ⇒ `undefined` —— 与「没有这一行」**同一个值**,路由手里拿不到它无权看的行,也就没有第二种拒绝形可漏存在性;
9
+ * · operator 臂由调用点以闭集 {@link OwnerArm} 声明,这里统一并 `explicitOperatorOk`(此前各口手抄 `explicitOperatorOk(...) || owner === principal`)。
10
+ *
11
+ * ## 射程(第一期)
12
+ * 迁进来的口:leader 登记表的读与幂等重放、A2A `tasks/get`、preempt、审批豁免面;`request-guards.ts` 的 `runOwnerOk` 与提交撞键的回执函数
13
+ * (`submit-replay.ts`)经 {@link runRowReadable} 读同一只判官。其余按 run / 会话寻址的口(`runOwnerOk` 16 处、`sessionOwnerOk` 10 处)第二期整体换成
14
+ * {@link readOwnedRun} / {@link readOwnedSession} 并删两只 helper;裸 store 读口按文件计数钉在 `test/owner-gate-single-owner.test.ts`(增即红)。
15
+ */
16
+ import type { ServiceConfig } from "../config-types.js";
17
+ import type { RunRecord } from "../plugins/store-contracts.js";
18
+ import { type OwnerAwareSessionStore, type Principal, type SessionCaller, type SessionOwnerCell } from "../security.js";
19
+ import { type IdentityWiring, type OperatorRoster } from "./principal-gate.js";
20
+ /** 调用点挂哪条臂(闭集):`owner` = 只有属主判官;`owner_or_operator` = 属主判官 ∨ 显式运维(`explicitOperatorOk`,唯一读法)。 */
21
+ export type OwnerArm = "owner" | "owner_or_operator";
22
+ /** 存取器读的配置格:判官要 `requirePrincipal`(C8 臂的单用户条件),operator 臂要运维名册。 */
23
+ export type OwnerAccessConfig = Pick<ServiceConfig, "requirePrincipal"> & OperatorRoster;
24
+ /**
25
+ * 一行 run 行的属主过判官。`owner`:串 = 有主,`null` = 无主(开放);**`undefined` = 属主格坏了**(型上是 `string | null`,盘上的 run.json 少了这个键时
26
+ * 运行期会读成缺席 —— 文件店的形判据不验它)⇒ 谁都读不到(fail-closed,不猜成无主;operator 臂照常并)。leader 登记行的 `owner` 是可选键、缺席 = 无主,
27
+ * 那是 leader 记录型自己的语义,由 {@link createLeaderRunVisibility} 在 leader 边界上显式折成 `null`,不在这里混读。
28
+ */
29
+ export declare function runRowReadable(config: OwnerAccessConfig, principal: Principal | undefined, owner: string | null | undefined, arm: OwnerArm): boolean;
30
+ /**
31
+ * 按**会话**寻址的面上读一行 run 行(会话面板的上一腿 MCP 投影:读的是这只会话最新那条 run 的账本行):判官 = 会话面那一只(`sessionOwnerReadable`:
32
+ * dev-open 不钉人,与会话列表同读);run 行不是委派子代的 placed 会话行 ⇒ 无主时 `placed: false`(与 run 面对无主 run 的读法同)。
33
+ */
34
+ export declare function runRowReadableOnSessionFace(w: IdentityWiring & {
35
+ readonly config: OwnerAccessConfig;
36
+ }, caller: SessionCaller, owner: string | null, arm: OwnerArm): boolean;
37
+ /** run 行读口:行 | `undefined`(没有这一行 ≡ 读不到,同一个值)。 */
38
+ export declare function readOwnedRun(config: OwnerAccessConfig, runStore: {
39
+ getRun(taskId: string): Promise<RunRecord | undefined>;
40
+ }, principal: Principal | undefined, taskId: string, arm: OwnerArm): Promise<RunRecord | undefined>;
41
+ /**
42
+ * 会话行读口:属主一读 + 无主时 placement 一格(`sessionOwnerCellOf`,S-1770)+ 会话面判官。`undefined` = 没有这只会话(`ownerOf` 答 `undefined`)≡ 读不到。
43
+ * 读回的那一格交给调用点(要按属主作答的口用它)。店的读失败照常抛(500,绝不当成「读不到」或「读得到」)。
44
+ */
45
+ export declare function readOwnedSession(w: IdentityWiring & {
46
+ readonly config: OwnerAccessConfig;
47
+ }, store: Pick<OwnerAwareSessionStore, "placementOf"> & {
48
+ ownerOf(sessionId: string): Promise<string | null | undefined>;
49
+ }, caller: SessionCaller, sessionId: string, arm: OwnerArm): Promise<SessionOwnerCell | undefined>;
50
+ /**
51
+ * leader 登记表的判官形(boot 装配一次,`createLeaderEndpoint` 的必填席)—— leader 模块不再自判属主(修前它手抄 `owner == null || owner === requester`,
52
+ * 缺 C8 窄互认臂而注称 mirrors runOwnerOk)。leader 腿的调用方身份经幂等身份结构(`IdemCaller.principal`,即 `gatedPrincipal` 的回值)转手而来,
53
+ * 这里是 `Principal` 的「上游已验」适配铸点(第二期随那只结构带品牌而删)。`config` 是活的配置对象(每次调用现读)。
54
+ */
55
+ export declare function createLeaderRunVisibility(config: OwnerAccessConfig): (principal: string | null | undefined, owner: string | null | undefined) => boolean;
56
+ //# sourceMappingURL=owner-access.d.ts.map
@@ -0,0 +1,42 @@
1
+ import { mintDurableOwnerKey, mintPrincipal, sessionOwnerCellOf } from "../security.js";
2
+ import { explicitOperatorOk, runOwnerReadable, sessionOwnerReadable } from "./principal-gate.js";
3
+ function operatorArmHolds(config, principal, arm) {
4
+ switch (arm) {
5
+ case "owner":
6
+ return false;
7
+ case "owner_or_operator":
8
+ return explicitOperatorOk(principal, config);
9
+ default: {
10
+ const unknownArm = arm;
11
+ throw new Error(`owner access: unknown arm ${String(unknownArm)}`);
12
+ }
13
+ }
14
+ }
15
+ export function runRowReadable(config, principal, owner, arm) {
16
+ if (operatorArmHolds(config, principal, arm))
17
+ return true;
18
+ if (owner === undefined)
19
+ return false;
20
+ return runOwnerReadable(principal, owner === null ? null : mintDurableOwnerKey(owner), config);
21
+ }
22
+ export function runRowReadableOnSessionFace(w, caller, owner, arm) {
23
+ if (operatorArmHolds(w.config, caller.principal, arm))
24
+ return true;
25
+ const cell = owner === null ? { owner: null, placed: false } : { owner: mintDurableOwnerKey(owner) };
26
+ return sessionOwnerReadable(caller, cell, w);
27
+ }
28
+ export async function readOwnedRun(config, runStore, principal, taskId, arm) {
29
+ const row = await runStore.getRun(taskId);
30
+ return row !== undefined && runRowReadable(config, principal, row.owner, arm) ? row : undefined;
31
+ }
32
+ export async function readOwnedSession(w, store, caller, sessionId, arm) {
33
+ const owner = await store.ownerOf(sessionId);
34
+ if (owner === undefined)
35
+ return undefined;
36
+ const cell = await sessionOwnerCellOf(store, sessionId, owner);
37
+ return operatorArmHolds(w.config, caller.principal, arm) || sessionOwnerReadable(caller, cell, w) ? cell : undefined;
38
+ }
39
+ export function createLeaderRunVisibility(config) {
40
+ return (principal, owner) => runRowReadable(config, principal == null ? undefined : mintPrincipal(principal), owner ?? null, "owner");
41
+ }
42
+ //# sourceMappingURL=owner-access.js.map