@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
@@ -2,12 +2,11 @@ import { hookNoticeWire } from "../../fleet/fleet-bus.js";
2
2
  import { FLEET_SNAPSHOT_TERMINAL_MAX_ROWS, isTerminalWorkflowRowStatus, recentTerminalWorkflowRows } from "../../fleet/fleet-terminal-window.js";
3
3
  import { taskNotificationFoldKey } from "../../orchestration/workflow-completion-inbox.js";
4
4
  import { sendJson, sendError, sseHeaders } from "../send.js";
5
- import { gatedPrincipal, sendPrincipalRefusal } from "../principal-gate.js";
5
+ import { fleetViewOf, gatedPrincipal, sendPrincipalRefusal } from "../principal-gate.js";
6
6
  import { assertNever } from "../route-ctx.js";
7
7
  import * as facts from "../../capability-facts.js";
8
8
  export async function handleFleet(req, res, match, ctx) {
9
9
  const { deps } = ctx;
10
- const { sessionOwnerScope } = ctx.helpers;
11
10
  switch (match.decl.id) {
12
11
  case "fleet-stream": {
13
12
  const fleet = facts.fleetStream(deps);
@@ -15,7 +14,7 @@ export async function handleFleet(req, res, match, ctx) {
15
14
  sendError(res, 501, "capability.self_orchestration_required", "fleet stream requires self-orchestration / fleet wiring");
16
15
  return;
17
16
  }
18
- const { fleetWide } = sessionOwnerScope(req);
17
+ const { fleetWide } = fleetViewOf(req, deps, "read");
19
18
  const principal = gatedPrincipal(req, deps.config);
20
19
  if (deps.config.requirePrincipal && !principal && !fleetWide) {
21
20
  sendPrincipalRefusal(res, req, deps.config);
@@ -77,7 +76,7 @@ function streamFleet(req, res, bus, callerScope, callerSession = null, completio
77
76
  return rest;
78
77
  };
79
78
  const SCOPED_WORKFLOW_KEY_DISPOSITION = {
80
- id: "keep", status: "keep", doneCount: "keep", totalCount: "keep", failedCount: "keep",
79
+ id: "keep", status: "keep", errorCode: "keep", doneCount: "keep", totalCount: "keep", failedCount: "keep",
81
80
  startedCount: "keep", elapsedMs: "keep", tokens: "keep",
82
81
  name: "rewrite", scope: "strip", sessionId: "strip",
83
82
  description: "scrub",
@@ -90,6 +89,7 @@ function streamFleet(req, res, bus, callerScope, callerSession = null, completio
90
89
  id: rest.id,
91
90
  status: rest.status,
92
91
  name: "(unattributed)",
92
+ ...(rest.errorCode !== undefined ? { errorCode: rest.errorCode } : {}),
93
93
  ...(rest.doneCount !== undefined ? { doneCount: rest.doneCount } : {}),
94
94
  ...(rest.totalCount !== undefined ? { totalCount: rest.totalCount } : {}),
95
95
  ...(rest.failedCount !== undefined ? { failedCount: rest.failedCount } : {}),
@@ -49,8 +49,7 @@ export async function handleImages(req, res, match, ctx) {
49
49
  const bakes = deps.imageBakes;
50
50
  const idx = deps.imageIndex;
51
51
  const principal = gatedPrincipal(req, deps.config);
52
- const operators = deps.config.operatorPrincipals;
53
- const isExplicitOperator = explicitOperatorOk(principal, operators);
52
+ const isExplicitOperator = explicitOperatorOk(principal, deps.config);
54
53
  const operatorLane = facts.operatorLane(deps);
55
54
  const cfg = deps.config.imageBakes;
56
55
  const isRunner = source !== undefined && source !== null && source === cfg.runnerPrincipal;
@@ -239,12 +238,12 @@ export async function handleImages(req, res, match, ctx) {
239
238
  if (line.event === "heartbeat") {
240
239
  const fresh = await bakes.getBake(bakeId);
241
240
  if (!fresh || fresh.status !== "running") {
242
- sendJson(res, 409, { accepted: false, leaseValid: false, cancelRequested: fresh?.cancelRequested ?? false, errorCode: "conflict.bake_not_running" });
241
+ sendError(res, 409, "conflict.bake_not_running", "bake is not running", { accepted: false, leaseValid: false, cancelRequested: fresh?.cancelRequested ?? false });
243
242
  return;
244
243
  }
245
244
  const ok = bake.runnerId ? await bakes.heartbeatLease(bakeId, bake.runnerId, cfg.leaseMs) : false;
246
245
  if (!ok) {
247
- sendJson(res, 409, { accepted: false, leaseValid: false, cancelRequested: fresh.cancelRequested, errorCode: "conflict.bake_lease_lost" });
246
+ sendError(res, 409, "conflict.bake_lease_lost", "bake lease lost", { accepted: false, leaseValid: false, cancelRequested: fresh.cancelRequested });
248
247
  return;
249
248
  }
250
249
  sendJson(res, 200, { accepted: true, leaseValid: true, cancelRequested: fresh.cancelRequested });
@@ -252,7 +251,7 @@ export async function handleImages(req, res, match, ctx) {
252
251
  }
253
252
  const fresh = await bakes.getBake(bakeId);
254
253
  if (!fresh || fresh.status !== "running") {
255
- sendJson(res, 409, { accepted: false, leaseValid: false, cancelRequested: fresh?.cancelRequested ?? false, errorCode: "conflict.bake_not_running" });
254
+ sendError(res, 409, "conflict.bake_not_running", "bake is not running", { accepted: false, leaseValid: false, cancelRequested: fresh?.cancelRequested ?? false });
256
255
  return;
257
256
  }
258
257
  if (fresh.runnerId) {
@@ -291,7 +290,7 @@ export async function handleImages(req, res, match, ctx) {
291
290
  if (pool.available && isIndexRouteId(match.decl.id)) {
292
291
  const idx = pool.imageIndex;
293
292
  const principal = gatedPrincipal(req, deps.config);
294
- const operator = explicitOperatorOk(principal, deps.config.operatorPrincipals);
293
+ const operator = explicitOperatorOk(principal, deps.config);
295
294
  const viewer = { operator, tenantId: principal ?? null };
296
295
  const q = new URLSearchParams(match.search);
297
296
  if (match.decl.id === "images-index") {
@@ -345,7 +344,7 @@ export async function handleImages(req, res, match, ctx) {
345
344
  sendOperatorPrincipalsRequired(res);
346
345
  return;
347
346
  }
348
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
347
+ if (!explicitOperatorOk(principal, deps.config)) {
349
348
  sendError(res, 403, "auth.operator_only", "operator only");
350
349
  return;
351
350
  }
@@ -30,14 +30,7 @@ export async function handleLeader(req, res, match, ctx) {
30
30
  if (match.decl.id === "leader-submit") {
31
31
  if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)) || (await usageWindowDenied(req, res)))
32
32
  return;
33
- let body;
34
- try {
35
- body = await readJson(req);
36
- }
37
- catch {
38
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
39
- return;
40
- }
33
+ const body = await readJson(req);
41
34
  const laneRefusal = leaderEntryRefusal(leaderRunEntry(deps.config.autonomy));
42
35
  if (laneRefusal !== undefined) {
43
36
  sendError(res, 422, "request.autonomy_lane_refused", laneRefusal);
@@ -34,7 +34,7 @@
34
34
  * 404 无 oracle,与 `POST /v1/sessions/:id/notify` 逐字同形)→ `getActiveTaskId` 取本会话的活 run →
35
35
  * `steerableRuns` 取本副本活流。非 live 的四臂一码 409 `steering.not_running`,判据取词表属主
36
36
  * (`isParkedRunStatus` / `isTerminalRunStatus`)与 `runProvenElsewhere`(手抄已收编成一只谓词,S-430 起同住 `plugins/store-contracts.ts`)。
37
- * 显式 operator 可重拨任何租户的会话(监督动作,与 notify / steer 同臂;**不是** bare `isOperator`)。
37
+ * 显式 operator 可重拨任何租户的会话(监督动作,与 notify / steer 同臂;「谁是 operator」的唯一读法 `explicitOperatorOk`)。
38
38
  *
39
39
  * ── 应答期限(S-431)────────────────────────────────────────────────────────────────────────────
40
40
  * 修前这一口对 `live.reconnectMcpServer(server)` 是裸 `await`:server 侧没有期限,上界只来自 core 自己的启动期钟
@@ -7,6 +7,7 @@ import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal } from "../pri
7
7
  import {} from "../route-ctx.js";
8
8
  import { assertNever, SESSION_NOT_FOUND_MESSAGE } from "../route-ctx.js";
9
9
  import * as facts from "../../capability-facts.js";
10
+ import { sessionOwnerCellOf } from "../../security.js";
10
11
  const BodySchema = z.object({ server: z.string().min(1).max(190) }).strict();
11
12
  const NEUTRALIZED_TEXT_MAX = 200;
12
13
  const humanText = (s) => redactSecrets(s).slice(0, NEUTRALIZED_TEXT_MAX);
@@ -93,8 +94,8 @@ export async function handleMcpReconnect(req, res, match, ctx) {
93
94
  sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
94
95
  return;
95
96
  }
96
- const isOperator = explicitOperatorOk(principal, deps.config.operatorPrincipals);
97
- if (!isOperator && !ctx.helpers.sessionOwnerOk(req, res, owner))
97
+ const operator = explicitOperatorOk(principal, deps.config);
98
+ if (!operator && !ctx.helpers.sessionOwnerOk(req, res, await sessionOwnerCellOf(sessionStorage, sessionId, owner)))
98
99
  return;
99
100
  const activeTaskId = await runStore.getActiveTaskId(sessionId);
100
101
  const live = activeTaskId === undefined ? undefined : ctx.registry.steerableRuns.get(activeTaskId);
@@ -73,7 +73,7 @@ export async function handleMemoryBundle(req, res, match, ctx) {
73
73
  sendOperatorPrincipalsRequired(res);
74
74
  return;
75
75
  }
76
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
76
+ if (!explicitOperatorOk(principal, deps.config)) {
77
77
  sendError(res, 403, "auth.operator_only", "memory governance bundles are an operator-only deployment action");
78
78
  return;
79
79
  }
@@ -29,7 +29,7 @@ export async function handleMemoryCompliance(req, res, match, ctx) {
29
29
  sendOperatorPrincipalsRequired(res);
30
30
  return;
31
31
  }
32
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
32
+ if (!explicitOperatorOk(principal, deps.config)) {
33
33
  sendError(res, 403, "auth.operator_only", "memory provenance and erasure are operator-only deployment actions");
34
34
  return;
35
35
  }
@@ -92,7 +92,7 @@ export async function handleMemoryConsolidation(req, res, match, ctx) {
92
92
  }
93
93
  }
94
94
  const faces = fact.valve;
95
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
95
+ if (!explicitOperatorOk(principal, deps.config)) {
96
96
  sendError(res, 403, "auth.operator_only", "memory consolidation is operator-only: the caller principal is not in OPERATOR_PRINCIPALS");
97
97
  return;
98
98
  }
@@ -114,7 +114,7 @@ export declare function buildClearanceRowWire(r: OriginClearanceRow): {
114
114
  baseRev: string;
115
115
  origin: {
116
116
  at: number;
117
- cause?: "static" | "unattributed" | "observed" | "derived" | undefined;
117
+ cause?: "static" | "observed" | "unattributed" | "derived" | undefined;
118
118
  taint: "external";
119
119
  };
120
120
  };
@@ -122,7 +122,7 @@ export async function handleMemoryOrigin(req, res, match, ctx) {
122
122
  sendOperatorPrincipalsRequired(res);
123
123
  return;
124
124
  }
125
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
125
+ if (!explicitOperatorOk(principal, deps.config)) {
126
126
  sendError(res, 403, "auth.operator_only", "memory origin marking and clearance are operator-only deployment actions");
127
127
  return;
128
128
  }
@@ -2,7 +2,7 @@
2
2
  * [ref] A9 域模块 —— memory 导出/同步 + 只读策略面。
3
3
  *
4
4
  * 路由:`GET /v1/memory/export`、`POST /v1/memory/sync/:scope`、`GET /v1/policy`。
5
- * owner 门 = 「本人 user scope / 显式 operator / `org:` 键的目录成员」(见 {@link gateMemoryScope}),
5
+ * owner 门 = 「本人 user scope / 本人的项目层 / 显式 operator / `org:` 键的目录成员」(见 {@link gateMemoryScope}),
6
6
  * 越界一律 404(零存在性 oracle)。本域零可变状态。
7
7
  */
8
8
  import type { IncomingMessage, ServerResponse } from "node:http";
@@ -2,6 +2,7 @@ import { formatUserScope } from "@sema-agent/core";
2
2
  import { parseMemorySyncRequest } from "../../memory-sync.js";
3
3
  import { sendJson, sendError } from "../send.js";
4
4
  import { buildOriginFence, readOriginAware } from "../../memory-origin-fence.js";
5
+ import { parseProjectLayerKey } from "../../project-layer-key.js";
5
6
  import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal, sendUnauthorized } from "../principal-gate.js";
6
7
  import { assertNever } from "../route-ctx.js";
7
8
  const ORG_PREFIX = "org:";
@@ -33,9 +34,9 @@ function directoryDecidesThisFace(mode) {
33
34
  }
34
35
  }
35
36
  async function gateMemoryScope(deps, principal, scope, need) {
36
- if (scope === formatUserScope(principal))
37
+ if (scope === formatUserScope(principal) || parseProjectLayerKey(scope)?.owner === principal)
37
38
  return { kind: "allow" };
38
- if (explicitOperatorOk(principal, deps.config.operatorPrincipals))
39
+ if (explicitOperatorOk(principal, deps.config))
39
40
  return { kind: "allow" };
40
41
  const directory = deps.orgMemoryDirectory;
41
42
  if (!scope.startsWith(ORG_PREFIX) || directory === undefined || !directoryDecidesThisFace(deps.config.memoryOrgAdmissionMode)) {
@@ -1,6 +1,7 @@
1
- import { taskNotificationInboxEntry } from "../../orchestration/workflow-completion-inbox.js";
1
+ import { externalNotificationInboxEntry } from "../../orchestration/workflow-completion-inbox.js";
2
2
  import { sendJson, sendError } from "../send.js";
3
- import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal } from "../principal-gate.js";
3
+ import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal, sessionCallerOf } from "../principal-gate.js";
4
+ import { ownerlessRowOpen, sessionOwnerCellOf } from "../../security.js";
4
5
  import { sendResumeOutcome } from "../route-ctx.js";
5
6
  import { assertNever, SESSION_NOT_FOUND_MESSAGE } from "../route-ctx.js";
6
7
  import * as facts from "../../capability-facts.js";
@@ -23,14 +24,7 @@ export async function handleNotifyWake(req, res, match, ctx) {
23
24
  sendError(res, 400, "request.path_malformed", "session id segment is not valid percent-encoding");
24
25
  return;
25
26
  }
26
- let nb;
27
- try {
28
- nb = (await readJson(req));
29
- }
30
- catch {
31
- sendError(res, 400, "request.body_shape", "body must be JSON: { task_id, status, summary, result?, seq?, source? }");
32
- return;
33
- }
27
+ const nb = (await readJson(req));
34
28
  if (typeof nb.task_id !== "string" || nb.task_id.trim().length === 0 || nb.task_id.length > 190) {
35
29
  sendError(res, 400, "request.field_invalid", "task_id must be a non-empty string of at most 190 characters");
36
30
  return;
@@ -68,8 +62,8 @@ export async function handleNotifyWake(req, res, match, ctx) {
68
62
  sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
69
63
  return;
70
64
  }
71
- const notifyOperator = explicitOperatorOk(principal, deps.config.operatorPrincipals);
72
- if (!notifyOperator && notifyOwner !== null && notifyOwner !== principal) {
65
+ const notifyOperator = explicitOperatorOk(principal, deps.config);
66
+ if (!notifyOperator && notifyOwner !== principal && !ownerlessRowOpen(await sessionOwnerCellOf(owned.sessionStorage, notifySession, notifyOwner), sessionCallerOf(req, deps))) {
73
67
  sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
74
68
  return;
75
69
  }
@@ -101,7 +95,7 @@ export async function handleNotifyWake(req, res, match, ctx) {
101
95
  sendError(res, 501, "capability.workflow_store_required", "external notify requires the workflow completion inbox (WORKFLOW_RUN_STORE)");
102
96
  return;
103
97
  }
104
- await deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(notifySession, notifyOwner ?? principal ?? null, { task_id: payload.task_id, task_type: "external", status: payload.status, summary: payload.summary, ...(payload.result !== undefined ? { result: payload.result } : {}), ...(payload.seq !== undefined ? { seq: payload.seq } : {}), ...(payload.source !== undefined ? { source: payload.source } : {}) }, Date.now()));
98
+ await deps.workflowCompletionInbox.enqueue(externalNotificationInboxEntry(notifySession, notifyOwner ?? principal ?? null, { task_type: "external", ...payload }, Date.now()));
105
99
  sendJson(res, 202, { sessionId: notifySession, delivery: "parked", note: "no live stream — parked in the session inbox; drained as a task_notification on the next stream open" });
106
100
  return;
107
101
  }
@@ -122,14 +116,7 @@ export async function handleNotifyWake(req, res, match, ctx) {
122
116
  sendError(res, 400, "request.path_malformed", "session id segment is not valid percent-encoding");
123
117
  return;
124
118
  }
125
- let wakeBody;
126
- try {
127
- wakeBody = (await readJson(req));
128
- }
129
- catch {
130
- sendError(res, 400, "request.body_shape", "body must be JSON: { message?: string }");
131
- return;
132
- }
119
+ const wakeBody = (await readJson(req));
133
120
  if (wakeBody.message !== undefined && (typeof wakeBody.message !== "string" || wakeBody.message.length === 0)) {
134
121
  sendError(res, 400, "request.field_invalid", "message must be a non-empty string when present");
135
122
  return;
@@ -1,5 +1,5 @@
1
1
  import { sendJson, sendError } from "../send.js";
2
- import { gatedPrincipal, isOperator, explicitOperatorOk, sendOperatorPrincipalsRequired, sendPrincipalRefusal } from "../principal-gate.js";
2
+ import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sendPrincipalRefusal } from "../principal-gate.js";
3
3
  import { assertNever } from "../route-ctx.js";
4
4
  import * as facts from "../../capability-facts.js";
5
5
  import { quotaWindowResetsAt } from "../../observability/cost-quota.js";
@@ -14,7 +14,7 @@ export async function handleObservability(req, res, match, ctx) {
14
14
  }
15
15
  if (deps.config.requirePrincipal) {
16
16
  const principal = gatedPrincipal(req, deps.config);
17
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
17
+ if (!explicitOperatorOk(principal, deps.config)) {
18
18
  sendError(res, 403, "auth.operator_only", "outcomes view is operator-only on a multi-tenant worker");
19
19
  return;
20
20
  }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * 跨主体投递门的**受理口**:`POST /v1/principal-inbox/messages`。
3
+ *
4
+ * 本口只做三件事,其余全归门(`src/org-delivery-gate.ts`,规则全文在它的头注):
5
+ * ① 取发件人 —— **只**取自验过的身份面(`gatedPrincipal`),交给门的 `authedFrom` 就是 `{ scope: <那位主体> }`;
6
+ * 体里没有发件人这个键(写了 = 词表外键,400)。没有验过的身份 ⇒ 401(身份面那一句),不论部署是否要求 principal ——
7
+ * 门要一个发件人 scope,匿名者没有。无凭证部署上 principal 头只是调用方自报 ⇒ 本口在分派器的无凭证写门内
8
+ * (声明行 `credentialGated`,503 `auth.service_token_required`;本地开发显式 `ALLOW_UNAUTHED_WRITES=true` 才放行);
9
+ * ② 判体形 —— `{ to: 非空串, content: 非空串(≤ {@link PRINCIPAL_INBOX_CONTENT_MAX_CHARS} 字), urgent?: 布尔 }`,
10
+ * 键闭集与提交口同一只组句器(`principalInboxBodyKeyIssue`);
11
+ * ③ 调门、投影门的答案 —— 回执 ⇒ 200 `{ receiptId }`;拒绝 ⇒ core 的词原样做 `errorCode`、门的那一句原样做 `error`。
12
+ * 本口**不碰**任何店:一个店名、一个 `.append` 都没有(`test/org-delivery-gate-single-path.test.ts` 按源码钉)。
13
+ *
14
+ * 回执**不**带门回执里的 `seq`:那是收件人箱的序号,原样交给发件人就是把「收件人这只箱收过多少封」泄给 org 里的任何人。
15
+ *
16
+ * 拒绝词 → HTTP 状态(穷举 `switch`,core 加词 ⇒ 编译红):
17
+ * · `not_member` → 404:「不同 org」「查无此人」「目录答不上来」同一份字节(门保证),404 与本仓反枚举的既有形一致;
18
+ * · `rate_limited` → 429;
19
+ * · `inbox_full` → 409(收件人那一侧的状态,不是发件人的速率;与 `steering.queue_full` 同档);
20
+ * · `recipient_tombstoned` → 410(收件人正在被删除,这条路关了)。
21
+ * 门缺席(本部署没声明收件箱消费方)⇒ 501 `capability.unavailable`,能力位 `principalInboxDelivery` 读同一只事实。
22
+ */
23
+ import type { IncomingMessage, ServerResponse } from "node:http";
24
+ import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
25
+ /**
26
+ * 一封信正文的字符上界。全局请求体上界(8 MiB)对一只收件箱太宽:箱里最多 50 封,而读它的是收件人的助理 ——
27
+ * 一封信是一段话,不是一份附件(要转一份长文,发它的出处)。
28
+ */
29
+ export declare const PRINCIPAL_INBOX_CONTENT_MAX_CHARS = 32000;
30
+ export declare function handlePrincipalInbox(req: IncomingMessage, res: ServerResponse, match: RouteMatch<PrincipalInboxRouteId>, ctx: RouteCtx): Promise<void>;
31
+ export declare const PRINCIPAL_INBOX_ROUTES: readonly [{
32
+ readonly id: "principal-inbox-messages";
33
+ readonly path: "/v1/principal-inbox/messages";
34
+ readonly credentialGated: readonly ["POST"];
35
+ readonly methods: readonly ["POST"];
36
+ }];
37
+ /** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽。 */
38
+ export type PrincipalInboxRouteId = RouteIdsOf<typeof PRINCIPAL_INBOX_ROUTES>;
39
+ //# sourceMappingURL=principal-inbox.d.ts.map
@@ -0,0 +1,76 @@
1
+ import { sendJson, sendError } from "../send.js";
2
+ import { gatedPrincipal, sendUnauthorized } from "../principal-gate.js";
3
+ import { assertNever } from "../route-ctx.js";
4
+ import * as facts from "../../capability-facts.js";
5
+ import { principalInboxBodyKeyIssue } from "../../request-key-closure.js";
6
+ export const PRINCIPAL_INBOX_CONTENT_MAX_CHARS = 32_000;
7
+ function sendRefusal(res, outcome) {
8
+ switch (outcome.code) {
9
+ case "org_delivery.not_member":
10
+ sendError(res, 404, "org_delivery.not_member", outcome.message);
11
+ return;
12
+ case "org_delivery.rate_limited":
13
+ sendError(res, 429, "org_delivery.rate_limited", outcome.message);
14
+ return;
15
+ case "org_delivery.inbox_full":
16
+ sendError(res, 409, "org_delivery.inbox_full", outcome.message);
17
+ return;
18
+ case "org_delivery.recipient_tombstoned":
19
+ sendError(res, 410, "org_delivery.recipient_tombstoned", outcome.message);
20
+ return;
21
+ default:
22
+ return assertNever(outcome.code);
23
+ }
24
+ }
25
+ export async function handlePrincipalInbox(req, res, match, ctx) {
26
+ const { deps } = ctx;
27
+ const { readJson } = ctx.helpers;
28
+ switch (match.decl.id) {
29
+ case "principal-inbox-messages": {
30
+ const principal = gatedPrincipal(req, deps.config);
31
+ if (principal === undefined) {
32
+ sendUnauthorized(res, "identity");
33
+ return;
34
+ }
35
+ const fact = facts.principalInboxDelivery(deps);
36
+ if (!fact.available) {
37
+ sendError(res, 501, "capability.unavailable", "cross-principal delivery is not available on this deployment (it declares no principal-inbox consumer, so no organization delivery gate is mounted)");
38
+ return;
39
+ }
40
+ const raw = await readJson(req);
41
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
42
+ sendError(res, 400, "request.field_invalid", "body must be a JSON object { to: string, content: string, urgent?: boolean }");
43
+ return;
44
+ }
45
+ const keyIssue = principalInboxBodyKeyIssue(raw);
46
+ if (keyIssue) {
47
+ sendError(res, 400, "request.body_shape", keyIssue.message, { unknownKeys: keyIssue.unknownKeys, unsupportedKeys: keyIssue.unsupportedKeys });
48
+ return;
49
+ }
50
+ const body = raw;
51
+ if (typeof body.to !== "string" || body.to === "") {
52
+ sendError(res, 400, "request.field_invalid", "to must be a non-empty string naming the recipient principal");
53
+ return;
54
+ }
55
+ if (typeof body.content !== "string" || body.content === "" || body.content.length > PRINCIPAL_INBOX_CONTENT_MAX_CHARS) {
56
+ sendError(res, 400, "request.field_invalid", `content must be a non-empty string of at most ${PRINCIPAL_INBOX_CONTENT_MAX_CHARS} characters`);
57
+ return;
58
+ }
59
+ if (body.urgent !== undefined && typeof body.urgent !== "boolean") {
60
+ sendError(res, 400, "request.field_invalid", "urgent must be a boolean when present");
61
+ return;
62
+ }
63
+ const outcome = await fact.gate.deliverCrossPrincipal({ scope: principal }, body.to, { content: body.content, ...(body.urgent !== undefined ? { urgent: body.urgent } : {}) });
64
+ if (!outcome.ok) {
65
+ sendRefusal(res, outcome);
66
+ return;
67
+ }
68
+ sendJson(res, 200, { receiptId: outcome.receipt.receiptId });
69
+ return;
70
+ }
71
+ default:
72
+ return assertNever(match.decl.id);
73
+ }
74
+ }
75
+ export const PRINCIPAL_INBOX_ROUTES = [{ id: "principal-inbox-messages", path: "/v1/principal-inbox/messages", credentialGated: ["POST"], methods: ["POST"] }];
76
+ //# sourceMappingURL=principal-inbox.js.map
@@ -36,7 +36,7 @@ export async function handleRetention(req, res, match, ctx) {
36
36
  sendOperatorPrincipalsRequired(res);
37
37
  return;
38
38
  }
39
- if (!explicitOperatorOk(principal, deps.config.operatorPrincipals)) {
39
+ if (!explicitOperatorOk(principal, deps.config)) {
40
40
  sendError(res, 403, "auth.operator_only", OPERATOR_ONLY_MESSAGE);
41
41
  return;
42
42
  }
@@ -71,14 +71,7 @@ async function handleHold(req, res, ctx, store, rawDomain, principal, held) {
71
71
  }
72
72
  let note;
73
73
  if (held) {
74
- let raw;
75
- try {
76
- raw = await ctx.helpers.readJson(req);
77
- }
78
- catch {
79
- sendError(res, 400, "request.invalid_json", "invalid JSON body");
80
- return;
81
- }
74
+ const raw = await ctx.helpers.readJson(req);
82
75
  if (raw !== undefined && raw !== null && raw !== "") {
83
76
  if (typeof raw !== "object" || Array.isArray(raw)) {
84
77
  sendError(res, 400, "request.body_shape", "invalid retention hold body — expected an object with an optional `note` string");
@@ -1,14 +1,13 @@
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";
10
- import { MAX_RULE_TEXT_CHARS, RULE_BEHAVIORS, isValidDurableScope } from "@sema-agent/core";
11
- import { PERSISTED_RULE_MATCHES, isPersistedRuleTool, isDirectWritableRuleBehavior } from "../../permission-rule-vocab.js";
8
+ import { hasControlOrBidi } from "@sema-agent/settings-schema";
9
+ import { IMPORTED_SETTINGS_LAYERS, MAX_RULE_TEXT_CHARS, PERSISTED_RULE_MATCHES, RULE_ADD_ORIGINS, RULE_BEHAVIORS, isValidDurableScope } from "@sema-agent/core";
10
+ import { isPersistedRuleTool, isDirectWritableRuleBehavior } from "../../permission-rule-vocab.js";
12
11
  const logger = createLogger();
13
12
  export const RULES_CC_IMPORT_PREPARE_PATH = "/v1/rules/cc-import/prepare";
14
13
  export const RULES_CC_IMPORT_REDEEM_PATH = "/v1/rules/cc-import/redeem";
@@ -24,7 +23,7 @@ const CcImportPrepareBodySchema = z
24
23
  layers: z
25
24
  .array(z
26
25
  .object({
27
- layer: z.enum(["userSettings", "projectSettings", "localSettings"]),
26
+ layer: z.enum(IMPORTED_SETTINGS_LAYERS),
28
27
  path: z.string().min(1).max(1024),
29
28
  root: z.string().max(1024),
30
29
  content: z.string().max(MAX_LAYER_CONTENT_CHARS),
@@ -37,13 +36,12 @@ 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({
45
43
  dot: z.object({ actor: z.string().min(1).max(190), counter: z.number().int().nonnegative().safe() }).strict(),
46
- origin: z.enum(["user", "imported-cc", "starter"]),
44
+ origin: z.enum(RULE_ADD_ORIGINS),
47
45
  createdAt: z.string().min(1).max(64),
48
46
  })
49
47
  .strict();
@@ -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;