@north-light/cli 0.3.530 → 0.3.532

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 (495) hide show
  1. package/dist/clients/attach/session/connection.js +1 -1
  2. package/dist/clients/attach/session/reconnect.js +1 -1
  3. package/dist/clients/attach/viewer.js +508 -508
  4. package/dist/core/async-array.d.ts +7 -0
  5. package/dist/core/async-array.js +1 -0
  6. package/dist/core/audit.d.ts +1 -1
  7. package/dist/core/audit.js +2 -2
  8. package/dist/core/canvas/attention.d.ts +4 -4
  9. package/dist/core/canvas/attention.js +1 -1
  10. package/dist/core/canvas/boot.d.ts +4 -4
  11. package/dist/core/canvas/boot.js +1 -1
  12. package/dist/core/canvas/canvas.d.ts +59 -59
  13. package/dist/core/canvas/canvas.js +19 -19
  14. package/dist/core/canvas/context-strip.js +2 -2
  15. package/dist/core/canvas/crons.d.ts +27 -27
  16. package/dist/core/canvas/crons.js +11 -11
  17. package/dist/core/canvas/daemon-actions.d.ts +10 -10
  18. package/dist/core/canvas/daemon-actions.js +8 -8
  19. package/dist/core/canvas/daemon-owner.d.ts +3 -3
  20. package/dist/core/canvas/daemon-owner.js +2 -2
  21. package/dist/core/canvas/db.d.ts +19 -30
  22. package/dist/core/canvas/db.js +3 -2
  23. package/dist/core/canvas/deliveries.d.ts +16 -16
  24. package/dist/core/canvas/deliveries.js +24 -24
  25. package/dist/core/canvas/executions.d.ts +8 -8
  26. package/dist/core/canvas/executions.js +1 -1
  27. package/dist/core/canvas/focuses.d.ts +8 -8
  28. package/dist/core/canvas/focuses.js +1 -1
  29. package/dist/core/canvas/history.d.ts +3 -3
  30. package/dist/core/canvas/history.js +9 -9
  31. package/dist/core/canvas/install-id.d.ts +1 -1
  32. package/dist/core/canvas/install-id.js +1 -1
  33. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
  34. package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
  35. package/dist/core/canvas/memory-reads.d.ts +6 -6
  36. package/dist/core/canvas/memory-reads.js +1 -1
  37. package/dist/core/canvas/nav-model.d.ts +13 -13
  38. package/dist/core/canvas/nav-model.js +1 -1
  39. package/dist/core/canvas/node-agent-paths.d.ts +6 -6
  40. package/dist/core/canvas/node-agent-paths.js +1 -1
  41. package/dist/core/canvas/node-tokens.d.ts +7 -7
  42. package/dist/core/canvas/node-tokens.js +3 -3
  43. package/dist/core/canvas/outcome-actions.d.ts +5 -5
  44. package/dist/core/canvas/outcome-actions.js +3 -3
  45. package/dist/core/canvas/recovery.d.ts +26 -26
  46. package/dist/core/canvas/recovery.js +2 -2
  47. package/dist/core/canvas/render-source.d.ts +1 -1
  48. package/dist/core/canvas/render-source.js +1 -1
  49. package/dist/core/canvas/sessions.d.ts +10 -10
  50. package/dist/core/canvas/sessions.js +4 -4
  51. package/dist/core/canvas/source.js +1 -1
  52. package/dist/core/canvas/structured-requests.d.ts +15 -15
  53. package/dist/core/canvas/structured-requests.js +5 -5
  54. package/dist/core/canvas/tree.d.ts +9 -9
  55. package/dist/core/canvas/tree.js +5 -5
  56. package/dist/core/canvas/waits.d.ts +13 -13
  57. package/dist/core/canvas/waits.js +6 -6
  58. package/dist/core/canvas/worktrees.d.ts +15 -15
  59. package/dist/core/canvas/worktrees.js +1 -1
  60. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  61. package/dist/core/conversation-store/file-store.d.ts +7 -7
  62. package/dist/core/conversation-store/file-store.js +9 -9
  63. package/dist/core/conversation-store/index.d.ts +16 -14
  64. package/dist/core/conversation-store/index.js +1 -1
  65. package/dist/core/conversation-store/listener.js +5 -5
  66. package/dist/core/conversation-store/patch.d.ts +3 -1
  67. package/dist/core/conversation-store/patch.js +1 -1
  68. package/dist/core/feed/feed.js +3 -3
  69. package/dist/core/feed/inbox.d.ts +2 -2
  70. package/dist/core/feed/inbox.js +1 -1
  71. package/dist/core/feed/messages.d.ts +11 -12
  72. package/dist/core/feed/messages.js +5 -5
  73. package/dist/core/feed/reports.d.ts +4 -4
  74. package/dist/core/feed/reports.js +2 -2
  75. package/dist/core/grants/cover.d.ts +1 -1
  76. package/dist/core/grants/cover.js +1 -1
  77. package/dist/core/grants/local.d.ts +1 -1
  78. package/dist/core/grants/local.js +1 -1
  79. package/dist/core/grants/mirror.d.ts +19 -19
  80. package/dist/core/grants/mirror.js +2 -2
  81. package/dist/core/grants/on-sync.d.ts +1 -1
  82. package/dist/core/grants/on-sync.js +1 -1
  83. package/dist/core/grants/remove.js +1 -1
  84. package/dist/core/grants/sync.js +1 -1
  85. package/dist/core/graph/access.d.ts +17 -17
  86. package/dist/core/graph/access.js +3 -3
  87. package/dist/core/graph/custom.d.ts +16 -16
  88. package/dist/core/graph/custom.js +9 -9
  89. package/dist/core/graph/deletion.d.ts +3 -7
  90. package/dist/core/graph/deletion.js +4 -4
  91. package/dist/core/graph/documents.d.ts +24 -27
  92. package/dist/core/graph/documents.js +7 -7
  93. package/dist/core/graph/edges.d.ts +13 -13
  94. package/dist/core/graph/edges.js +1 -1
  95. package/dist/core/graph/events.d.ts +7 -9
  96. package/dist/core/graph/events.js +8 -8
  97. package/dist/core/graph/exposures.d.ts +6 -6
  98. package/dist/core/graph/exposures.js +4 -4
  99. package/dist/core/graph/jobs.d.ts +6 -8
  100. package/dist/core/graph/jobs.js +2 -2
  101. package/dist/core/graph/kinds/action.js +1 -1
  102. package/dist/core/graph/kinds/custom.js +2 -2
  103. package/dist/core/graph/kinds/document.d.ts +1 -0
  104. package/dist/core/graph/kinds/document.js +4 -4
  105. package/dist/core/graph/kinds/dto.d.ts +2 -2
  106. package/dist/core/graph/kinds/dto.js +1 -1
  107. package/dist/core/graph/kinds/job.js +2 -2
  108. package/dist/core/graph/kinds/kind.d.ts +6 -8
  109. package/dist/core/graph/kinds/kind.js +1 -1
  110. package/dist/core/graph/kinds/node.js +5 -5
  111. package/dist/core/graph/kinds/owner.js +2 -2
  112. package/dist/core/graph/kinds/registry.d.ts +6 -9
  113. package/dist/core/graph/kinds/registry.js +1 -1
  114. package/dist/core/graph/names.d.ts +6 -6
  115. package/dist/core/graph/names.js +3 -3
  116. package/dist/core/graph/object-waits.d.ts +4 -7
  117. package/dist/core/graph/object-waits.js +1 -1
  118. package/dist/core/graph/objects.d.ts +14 -14
  119. package/dist/core/graph/objects.js +9 -9
  120. package/dist/core/graph/package-docs.d.ts +2 -7
  121. package/dist/core/graph/package-docs.js +5 -5
  122. package/dist/core/graph/package-kinds.d.ts +2 -5
  123. package/dist/core/graph/package-kinds.js +1 -1
  124. package/dist/core/graph/package-reconcile.d.ts +2 -5
  125. package/dist/core/graph/package-reconcile.js +1 -1
  126. package/dist/core/graph/reader.d.ts +18 -18
  127. package/dist/core/graph/reader.js +3 -3
  128. package/dist/core/graph/receivers.d.ts +4 -4
  129. package/dist/core/graph/receivers.js +5 -5
  130. package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
  131. package/dist/core/graph/repo-sync/exchange.js +2 -2
  132. package/dist/core/graph/repo-sync/repos.d.ts +7 -5
  133. package/dist/core/graph/repo-sync/repos.js +3 -3
  134. package/dist/core/graph/repo-sync/sync.d.ts +3 -6
  135. package/dist/core/graph/repo-sync/sync.js +2 -2
  136. package/dist/core/graph/rules.d.ts +5 -5
  137. package/dist/core/graph/rules.js +3 -3
  138. package/dist/core/graph/spaces/app.js +1 -1
  139. package/dist/core/graph/spaces/index.d.ts +4 -5
  140. package/dist/core/graph/spaces/index.js +1 -1
  141. package/dist/core/graph/spaces/own-memory.d.ts +4 -4
  142. package/dist/core/graph/spaces/own-memory.js +1 -1
  143. package/dist/core/graph/spaces/person.js +3 -3
  144. package/dist/core/graph/spaces/repo.d.ts +1 -1
  145. package/dist/core/graph/spaces/repo.js +1 -1
  146. package/dist/core/graph/watches.d.ts +15 -15
  147. package/dist/core/graph/watches.js +10 -10
  148. package/dist/core/human/feedback-companion.d.ts +2 -2
  149. package/dist/core/human/feedback-companion.js +1 -1
  150. package/dist/core/human/feedback.d.ts +3 -3
  151. package/dist/core/human/feedback.js +1 -1
  152. package/dist/core/human/requests.d.ts +34 -33
  153. package/dist/core/human/requests.js +20 -20
  154. package/dist/core/human/scan.d.ts +2 -2
  155. package/dist/core/human/scan.js +1 -1
  156. package/dist/core/human/tickets.d.ts +9 -9
  157. package/dist/core/human/tickets.js +1 -1
  158. package/dist/core/llm/app-rungs.d.ts +1 -1
  159. package/dist/core/llm/app-rungs.js +1 -1
  160. package/dist/core/llm/run.js +2 -2
  161. package/dist/core/peer/directory.d.ts +1 -1
  162. package/dist/core/peer/directory.js +1 -1
  163. package/dist/core/peer/envelope.d.ts +3 -3
  164. package/dist/core/peer/envelope.js +1 -1
  165. package/dist/core/peer/home.d.ts +13 -7
  166. package/dist/core/peer/home.js +2 -2
  167. package/dist/core/peer/ingest.d.ts +6 -6
  168. package/dist/core/peer/ingest.js +1 -1
  169. package/dist/core/peer/outbox-store.d.ts +14 -14
  170. package/dist/core/peer/outbox-store.js +5 -5
  171. package/dist/core/peer/receiver.d.ts +2 -2
  172. package/dist/core/peer/receiver.js +1 -1
  173. package/dist/core/peer/stubs.d.ts +10 -10
  174. package/dist/core/peer/stubs.js +1 -1
  175. package/dist/core/providers/approval.d.ts +2 -2
  176. package/dist/core/providers/approval.js +2 -2
  177. package/dist/core/providers/audit.d.ts +3 -3
  178. package/dist/core/providers/audit.js +2 -2
  179. package/dist/core/providers/bundles.js +2 -2
  180. package/dist/core/providers/call.d.ts +2 -2
  181. package/dist/core/providers/call.js +1 -1
  182. package/dist/core/providers/files.d.ts +1 -1
  183. package/dist/core/providers/files.js +1 -1
  184. package/dist/core/providers/mint.js +1 -1
  185. package/dist/core/providers/receipts.d.ts +1 -1
  186. package/dist/core/providers/receipts.js +2 -2
  187. package/dist/core/review/birth.js +1 -1
  188. package/dist/core/review/comments.d.ts +19 -19
  189. package/dist/core/review/comments.js +5 -5
  190. package/dist/core/review/companion.d.ts +1 -1
  191. package/dist/core/review/companion.js +1 -1
  192. package/dist/core/review/document.d.ts +3 -3
  193. package/dist/core/review/document.js +2 -2
  194. package/dist/core/review/fork.js +2 -2
  195. package/dist/core/review/realize.js +1 -1
  196. package/dist/core/review/remap.d.ts +2 -2
  197. package/dist/core/review/remap.js +4 -4
  198. package/dist/core/review/stage.d.ts +1 -1
  199. package/dist/core/review/stage.js +1 -1
  200. package/dist/core/review/store.d.ts +21 -21
  201. package/dist/core/review/store.js +1 -1
  202. package/dist/core/runs/activity.d.ts +1 -1
  203. package/dist/core/runs/activity.js +5 -5
  204. package/dist/core/runs/confinement.d.ts +7 -7
  205. package/dist/core/runs/confinement.js +2 -2
  206. package/dist/core/runs/events.d.ts +12 -12
  207. package/dist/core/runs/events.js +4 -4
  208. package/dist/core/runs/operations.d.ts +11 -11
  209. package/dist/core/runs/operations.js +5 -5
  210. package/dist/core/runs/questions.d.ts +10 -10
  211. package/dist/core/runs/questions.js +3 -3
  212. package/dist/core/runtime/auth-reload.js +1 -1
  213. package/dist/core/runtime/bearings.d.ts +5 -5
  214. package/dist/core/runtime/bearings.js +6 -6
  215. package/dist/core/runtime/broker-inventory.js +1 -1
  216. package/dist/core/runtime/broker-request.js +1 -1
  217. package/dist/core/runtime/broker.js +1 -1
  218. package/dist/core/runtime/close.d.ts +3 -3
  219. package/dist/core/runtime/close.js +1 -1
  220. package/dist/core/runtime/deliver-live.js +1 -1
  221. package/dist/core/runtime/fleet.d.ts +2 -2
  222. package/dist/core/runtime/host.d.ts +3 -3
  223. package/dist/core/runtime/host.js +3 -3
  224. package/dist/core/runtime/kickoff.d.ts +12 -12
  225. package/dist/core/runtime/kickoff.js +17 -17
  226. package/dist/core/runtime/launch-target.d.ts +1 -1
  227. package/dist/core/runtime/launch-target.js +1 -1
  228. package/dist/core/runtime/ledger.d.ts +3 -3
  229. package/dist/core/runtime/ledger.js +3 -3
  230. package/dist/core/runtime/lifecycle.d.ts +1 -1
  231. package/dist/core/runtime/lifecycle.js +2 -2
  232. package/dist/core/runtime/memory-admission.js +1 -1
  233. package/dist/core/runtime/model-swap.d.ts +2 -2
  234. package/dist/core/runtime/model-swap.js +1 -1
  235. package/dist/core/runtime/node-read.d.ts +1 -1
  236. package/dist/core/runtime/node-read.js +2 -2
  237. package/dist/core/runtime/nodes.d.ts +6 -6
  238. package/dist/core/runtime/nodes.js +1 -1
  239. package/dist/core/runtime/outcome-document.d.ts +1 -1
  240. package/dist/core/runtime/outcome-document.js +1 -1
  241. package/dist/core/runtime/persona.d.ts +3 -3
  242. package/dist/core/runtime/persona.js +2 -2
  243. package/dist/core/runtime/placement.d.ts +11 -11
  244. package/dist/core/runtime/placement.js +1 -1
  245. package/dist/core/runtime/promote.d.ts +3 -3
  246. package/dist/core/runtime/promote.js +1 -1
  247. package/dist/core/runtime/recycle.js +1 -1
  248. package/dist/core/runtime/reopen.d.ts +5 -5
  249. package/dist/core/runtime/reopen.js +1 -1
  250. package/dist/core/runtime/reset.d.ts +4 -4
  251. package/dist/core/runtime/reset.js +1 -1
  252. package/dist/core/runtime/revive-all.d.ts +2 -2
  253. package/dist/core/runtime/revive-all.js +1 -1
  254. package/dist/core/runtime/revive.d.ts +4 -4
  255. package/dist/core/runtime/revive.js +2 -2
  256. package/dist/core/runtime/roadmap.d.ts +6 -6
  257. package/dist/core/runtime/roadmap.js +5 -5
  258. package/dist/core/runtime/session-branch.d.ts +1 -1
  259. package/dist/core/runtime/session-branch.js +1 -1
  260. package/dist/core/runtime/session-list-cache.js +1 -1
  261. package/dist/core/runtime/situational-live.js +1 -1
  262. package/dist/core/runtime/spawn.d.ts +2 -2
  263. package/dist/core/runtime/spawn.js +2 -2
  264. package/dist/core/runtime/stop-guard.d.ts +2 -2
  265. package/dist/core/runtime/stop-guard.js +3 -3
  266. package/dist/core/runtime/warm-pool.d.ts +2 -2
  267. package/dist/core/runtime/warm-pool.js +1 -1
  268. package/dist/core/spaces/mounts.d.ts +2 -2
  269. package/dist/core/spaces/mounts.js +1 -1
  270. package/dist/core/spaces/permissions.d.ts +1 -1
  271. package/dist/core/spaces/permissions.js +1 -1
  272. package/dist/core/spaces/process.d.ts +1 -1
  273. package/dist/core/spaces/process.js +1 -1
  274. package/dist/core/spaces/space.js +1 -1
  275. package/dist/core/spaces/stop.d.ts +3 -3
  276. package/dist/core/spaces/stop.js +2 -2
  277. package/dist/core/spaces/users.d.ts +6 -6
  278. package/dist/core/spaces/users.js +1 -1
  279. package/dist/core/storage/attachments.d.ts +2 -2
  280. package/dist/core/storage/attachments.js +1 -1
  281. package/dist/core/storage/shares.d.ts +2 -2
  282. package/dist/core/storage/shares.js +1 -1
  283. package/dist/core/storage/tables.d.ts +21 -21
  284. package/dist/core/storage/tables.js +3 -3
  285. package/dist/core/substrate/delivery/corpus.d.ts +5 -8
  286. package/dist/core/substrate/delivery/corpus.js +3 -3
  287. package/dist/core/substrate/delivery/deliver.d.ts +10 -15
  288. package/dist/core/substrate/delivery/deliver.js +3 -3
  289. package/dist/core/substrate/delivery/plan.d.ts +2 -12
  290. package/dist/core/substrate/delivery/plan.js +3 -3
  291. package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
  292. package/dist/core/substrate/delivery/render-boot.js +18 -18
  293. package/dist/core/substrate/delivery/render-event.d.ts +7 -14
  294. package/dist/core/substrate/delivery/render-event.js +4 -4
  295. package/dist/core/substrate/subject.d.ts +2 -2
  296. package/dist/core/substrate/subject.js +1 -1
  297. package/dist/core/usage/ledger.d.ts +6 -6
  298. package/dist/core/usage/ledger.js +4 -4
  299. package/dist/core/worktree-close.js +4 -4
  300. package/dist/core/worktree-mutation-async.js +7 -7
  301. package/dist/core/worktree-quarantine.js +1 -1
  302. package/dist/core/worktree-sweep.d.ts +1 -1
  303. package/dist/core/worktree-sweep.js +6 -6
  304. package/dist/core/worktree.d.ts +5 -5
  305. package/dist/core/worktree.js +13 -13
  306. package/dist/daemon/analytics/compute.d.ts +2 -2
  307. package/dist/daemon/analytics/compute.js +1 -1
  308. package/dist/daemon/api/app-listener.d.ts +4 -4
  309. package/dist/daemon/api/app-listener.js +13 -13
  310. package/dist/daemon/api/bridge.js +5 -5
  311. package/dist/daemon/api/document-listener.js +6 -6
  312. package/dist/daemon/api/handlers/analytics.js +1 -1
  313. package/dist/daemon/api/handlers/attach.js +1 -1
  314. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  315. package/dist/daemon/api/handlers/bash.js +1 -1
  316. package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
  317. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  318. package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
  319. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  320. package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
  321. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  322. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  323. package/dist/daemon/api/handlers/canvas.js +4 -4
  324. package/dist/daemon/api/handlers/chat-inventory.js +1 -1
  325. package/dist/daemon/api/handlers/crons.js +1 -1
  326. package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
  327. package/dist/daemon/api/handlers/custom-objects.js +3 -3
  328. package/dist/daemon/api/handlers/delivery-retry.js +1 -1
  329. package/dist/daemon/api/handlers/delivery.js +1 -1
  330. package/dist/daemon/api/handlers/docs.d.ts +4 -4
  331. package/dist/daemon/api/handlers/docs.js +1 -1
  332. package/dist/daemon/api/handlers/feedback-comments.js +3 -3
  333. package/dist/daemon/api/handlers/files.js +1 -1
  334. package/dist/daemon/api/handlers/focus.js +1 -1
  335. package/dist/daemon/api/handlers/health.js +3 -3
  336. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  337. package/dist/daemon/api/handlers/human-requests.js +1 -1
  338. package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
  339. package/dist/daemon/api/handlers/inbox-page.js +1 -1
  340. package/dist/daemon/api/handlers/inbox.d.ts +1 -1
  341. package/dist/daemon/api/handlers/inbox.js +1 -1
  342. package/dist/daemon/api/handlers/llm.d.ts +1 -1
  343. package/dist/daemon/api/handlers/llm.js +3 -3
  344. package/dist/daemon/api/handlers/memory-reads.js +1 -1
  345. package/dist/daemon/api/handlers/memory.d.ts +5 -5
  346. package/dist/daemon/api/handlers/memory.js +5 -5
  347. package/dist/daemon/api/handlers/messages.js +2 -2
  348. package/dist/daemon/api/handlers/node-events.d.ts +2 -2
  349. package/dist/daemon/api/handlers/node-events.js +3 -3
  350. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  351. package/dist/daemon/api/handlers/node-records.js +2 -2
  352. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  353. package/dist/daemon/api/handlers/nodes.js +1 -1
  354. package/dist/daemon/api/handlers/objects.js +3 -3
  355. package/dist/daemon/api/handlers/package-docs.js +1 -1
  356. package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
  357. package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
  358. package/dist/daemon/api/handlers/profiles.d.ts +3 -3
  359. package/dist/daemon/api/handlers/profiles.js +1 -1
  360. package/dist/daemon/api/handlers/providers.d.ts +1 -1
  361. package/dist/daemon/api/handlers/providers.js +1 -1
  362. package/dist/daemon/api/handlers/questions.js +1 -1
  363. package/dist/daemon/api/handlers/reports.d.ts +1 -1
  364. package/dist/daemon/api/handlers/reports.js +5 -5
  365. package/dist/daemon/api/handlers/review-comments.js +1 -1
  366. package/dist/daemon/api/handlers/reviews.js +1 -1
  367. package/dist/daemon/api/handlers/runs.js +1 -1
  368. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  369. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  370. package/dist/daemon/api/handlers/transfer.js +1 -1
  371. package/dist/daemon/api/map.d.ts +3 -3
  372. package/dist/daemon/api/map.js +1 -1
  373. package/dist/daemon/api/principal.d.ts +1 -1
  374. package/dist/daemon/api/principal.js +1 -1
  375. package/dist/daemon/api/reader.d.ts +5 -5
  376. package/dist/daemon/api/reader.js +1 -1
  377. package/dist/daemon/api/router.d.ts +5 -5
  378. package/dist/daemon/api/router.js +1 -1
  379. package/dist/daemon/api/server.js +1 -1
  380. package/dist/daemon/broker-signals/bus.d.ts +1 -1
  381. package/dist/daemon/broker-signals/bus.js +1 -1
  382. package/dist/daemon/companion-retire.js +1 -1
  383. package/dist/daemon/cron/armed-context.d.ts +2 -2
  384. package/dist/daemon/cron/armed-context.js +1 -1
  385. package/dist/daemon/cron/authority.d.ts +2 -2
  386. package/dist/daemon/cron/authority.js +1 -1
  387. package/dist/daemon/cron/disposition.js +1 -1
  388. package/dist/daemon/cron/ended.d.ts +1 -1
  389. package/dist/daemon/cron/ended.js +2 -2
  390. package/dist/daemon/cron/escalation.js +3 -3
  391. package/dist/daemon/cron/folders.d.ts +1 -1
  392. package/dist/daemon/cron/folders.js +1 -1
  393. package/dist/daemon/cron/held.d.ts +1 -1
  394. package/dist/daemon/cron/held.js +1 -1
  395. package/dist/daemon/cron/lease-recovery.d.ts +1 -1
  396. package/dist/daemon/cron/lease-recovery.js +1 -1
  397. package/dist/daemon/cron/passes.d.ts +2 -2
  398. package/dist/daemon/cron/passes.js +1 -1
  399. package/dist/daemon/cron/run-socket.d.ts +1 -1
  400. package/dist/daemon/cron/run-socket.js +1 -1
  401. package/dist/daemon/cron/settle.js +1 -1
  402. package/dist/daemon/cron/sinks.d.ts +1 -1
  403. package/dist/daemon/cron/sinks.js +2 -2
  404. package/dist/daemon/cron-run.d.ts +12 -3
  405. package/dist/daemon/cron-run.js +2 -2
  406. package/dist/daemon/crtrd.js +6 -6
  407. package/dist/daemon/delivery/run-delivery.js +1 -1
  408. package/dist/daemon/due-sources.d.ts +3 -3
  409. package/dist/daemon/due-sources.js +1 -1
  410. package/dist/daemon/due.d.ts +3 -3
  411. package/dist/daemon/due.js +7 -7
  412. package/dist/daemon/fleet.d.ts +2 -2
  413. package/dist/daemon/fleet.js +11 -11
  414. package/dist/daemon/human/finish.js +3 -3
  415. package/dist/daemon/human/settle.d.ts +1 -1
  416. package/dist/daemon/human/settle.js +1 -1
  417. package/dist/daemon/human/sweep.js +1 -1
  418. package/dist/daemon/joined-owner.d.ts +2 -2
  419. package/dist/daemon/joined-owner.js +1 -1
  420. package/dist/daemon/messaging/node-message.js +1 -1
  421. package/dist/daemon/park-activity.d.ts +2 -2
  422. package/dist/daemon/park-activity.js +1 -1
  423. package/dist/daemon/peer/authority.js +1 -1
  424. package/dist/daemon/peer/forward.d.ts +13 -6
  425. package/dist/daemon/peer/forward.js +1 -1
  426. package/dist/daemon/peer/handlers.js +1 -1
  427. package/dist/daemon/peer/ingress.d.ts +4 -4
  428. package/dist/daemon/peer/ingress.js +1 -1
  429. package/dist/daemon/peer/outbox.d.ts +2 -2
  430. package/dist/daemon/peer/outbox.js +1 -1
  431. package/dist/daemon/peer/relay-service.js +1 -1
  432. package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
  433. package/dist/daemon/plugin-objects/read-leaf.js +2 -2
  434. package/dist/daemon/profile-delete.js +1 -1
  435. package/dist/daemon/readiness.d.ts +2 -2
  436. package/dist/daemon/readiness.js +1 -1
  437. package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
  438. package/dist/daemon/reconcilers/action-lane.js +1 -1
  439. package/dist/daemon/reconcilers/bash-deadline.js +2 -2
  440. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  441. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  442. package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
  443. package/dist/daemon/reconcilers/controller-death.js +1 -1
  444. package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
  445. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  446. package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
  447. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  448. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
  449. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  450. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
  451. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  452. package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
  453. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  454. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  455. package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
  456. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  457. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  458. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
  459. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
  460. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
  461. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  462. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
  463. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  464. package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
  465. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  466. package/dist/daemon/reconcilers/storage-due-work.js +1 -1
  467. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
  468. package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
  469. package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
  470. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  471. package/dist/daemon/review/comment-notify.js +2 -2
  472. package/dist/daemon/review/companion.d.ts +3 -3
  473. package/dist/daemon/review/companion.js +1 -1
  474. package/dist/daemon/review/finish.js +1 -1
  475. package/dist/daemon/review/sweep.js +1 -1
  476. package/dist/daemon/run-notices.d.ts +4 -4
  477. package/dist/daemon/run-notices.js +1 -1
  478. package/dist/daemon/runs/append-section.d.ts +2 -2
  479. package/dist/daemon/runs/append-section.js +2 -2
  480. package/dist/daemon/runs/observer.d.ts +2 -2
  481. package/dist/daemon/runs/observer.js +2 -2
  482. package/dist/daemon/structured-requests/boot.d.ts +1 -1
  483. package/dist/daemon/structured-requests/boot.js +1 -1
  484. package/dist/daemon/structured-requests/effects.js +1 -1
  485. package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
  486. package/dist/daemon/structured-requests/sidecar.js +1 -1
  487. package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
  488. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  489. package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
  490. package/dist/migrations/004-canvas-documents/index.js +2 -2
  491. package/dist/migrations/activation.js +2 -2
  492. package/docs/public-api.md +11 -0
  493. package/package.json +3 -2
  494. package/packages/crouter-identity/package.json +1 -1
  495. package/runtime.lock.json +12 -12
@@ -1,8 +1,8 @@
1
- var w=Object.defineProperty;var a=(r,e)=>w(r,"name",{value:e,configurable:!0});import{prepared as l}from"../sqlite-statements.js";import{existsSync as E,mkdirSync as N,renameSync as I,writeFileSync as v}from"node:fs";import{randomBytes as b,randomUUID as k}from"node:crypto";import{join as S}from"node:path";import{cancelCronsOnWake as m}from"../canvas/crons.js";import{withCanvasWrite as u}from"../canvas/db.js";import{getRow as h}from"../canvas/canvas.js";import{messagesDir as R}from"../canvas/paths.js";import{syncDirectory as A,syncFile as D}from"../fs-utils.js";import{settleDeadControllerWait as T,settleMatchingControllerWait as O}from"../canvas/waits.js";import{generateOperationId as x,operationIdContext as L,validateOperationId as J}from"../events/operation-id.js";import{clipBody as C}from"../../shared/inbox-entry-body.js";function y(){let r;do r=b(16).toString("hex");while(r==="00000000000000000000000000000000");return r}a(y,"newId");function M(r,e){const n=JSON.stringify(r);if(n===void 0)throw new TypeError(`${e} must be JSON-serializable`);return n}a(M,"stringify");function W(r,e){return e!=="normal"&&e!=="deferred"?e:h(r)?.lifecycle==="terminal"?"urgent":e}a(W,"effectiveTier");function q(r,e,n){const t=R(r);E(t)||N(t,{recursive:!0});const d=e.replace(/[^0-9]/g,""),o=S(t,`${d}-${k().slice(0,6)}.md`),i=`${o}.tmp`;return v(i,n,"utf8"),D(i),I(i,o),A(t),o}a(q,"writeMessageBody");function U(r){if(typeof r!="object"||r===null)return"";const e=r.body;return typeof e=="string"?e.trim():""}a(U,"inlineBody");function f(r,e){const n=e.messageId??y(),t=Number(l(r,"UPDATE message_sequence SET seq = seq + 1 WHERE id = 1 RETURNING seq").get().seq);return l(r,`INSERT INTO messages
1
+ var p=Object.defineProperty;var s=(r,e)=>p(r,"name",{value:e,configurable:!0});import{existsSync as _,mkdirSync as E,renameSync as N,writeFileSync as I}from"node:fs";import{randomBytes as v,randomUUID as b}from"node:crypto";import{join as k}from"node:path";import{cancelCronsOnWake as u}from"../canvas/crons.js";import{withCanvasWrite as c,openDb as h}from"../canvas/db.js";import{getRow as S}from"../canvas/canvas.js";import{messagesDir as R}from"../canvas/paths.js";import{syncDirectory as D,syncFile as A}from"../fs-utils.js";import{settleDeadControllerWait as T,settleMatchingControllerWait as O}from"../canvas/waits.js";import{generateOperationId as x,operationIdContext as L,validateOperationId as J}from"../events/operation-id.js";import{clipBody as U}from"../../shared/inbox-entry-body.js";function y(){let r;do r=v(16).toString("hex");while(r==="00000000000000000000000000000000");return r}s(y,"newId");function C(r,e){const t=JSON.stringify(r);if(t===void 0)throw new TypeError(`${e} must be JSON-serializable`);return t}s(C,"stringify");async function M(r,e){return e!=="normal"&&e!=="deferred"?e:(await S(r))?.lifecycle==="terminal"?"urgent":e}s(M,"effectiveTier");function W(r,e,t){const n=R(r);_(n)||E(n,{recursive:!0});const a=e.replace(/[^0-9]/g,""),d=k(n,`${a}-${b().slice(0,6)}.md`),i=`${d}.tmp`;return I(i,t,"utf8"),A(i),N(i,d),D(n),d}s(W,"writeMessageBody");function q(r){if(typeof r!="object"||r===null)return"";const e=r.body;return typeof e=="string"?e.trim():""}s(q,"inlineBody");async function m(r,e){const t=e.messageId??y(),n=Number((await r.prepare("UPDATE message_sequence SET seq = seq + 1 WHERE id = 1 RETURNING seq").get()).seq);return await r.prepare(`INSERT INTO messages
2
2
  (message_id, seq, operation_id, created_at, sender_node_id, sender_name, kind, label, body_ref, body_json, disposition,
3
3
  event, object_id, level, actor_id, cause_message_id, depth)
4
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(n,t,e.operationId,e.createdAt,e.senderNodeId,e.senderName,e.kind,e.label,e.bodyRef,e.bodyJson===void 0?null:M(e.bodyJson,"message body"),e.disposition,e.event?.event??null,e.event?.objectId??null,e.event?.level??null,e.event?.actorId??null,e.causeMessageId??null,e.depth??0),n}a(f,"insertMessage");function g(r,e,n,t,d,o,i){const s=y();return l(r,`INSERT INTO deliveries
4
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(t,n,e.operationId,e.createdAt,e.senderNodeId,e.senderName,e.kind,e.label,e.bodyRef,e.bodyJson===void 0?null:C(e.bodyJson,"message body"),e.disposition,e.event?.event??null,e.event?.objectId??null,e.event?.level??null,e.event?.actorId??null,e.causeMessageId??null,e.depth??0),t}s(m,"insertMessage");async function f(r,e,t,n,a,d,i){const o=y();return await r.prepare(`INSERT INTO deliveries
5
5
  (delivery_id, message_id, destination_id, urgency, wake, state, idempotency_key, created_at, updated_at)
6
- VALUES (?, ?, ?, ?, ?, 'pending', ?, ?, ?)`).run(s,e,n,t,d,i??null,o,o),s}a(g,"insertNodeDelivery");function _(r,e){const n=new Date().toISOString(),t=r.operationId===void 0?L.current()??x():J(r.operationId);let d=r.bodyRef??null,o=r.bodyJson;if(d===null&&e!==null&&r.senderNodeId!=="human"){const i=U(o),s=C(i);s.clipped&&(d=q(e,n,i),o={...o,body:s.text})}return{createdAt:n,operationId:t,bodyRef:d,bodyJson:o}}a(_,"finalizeNodeMail");function j(r,e){const n=_(e,r);return u(t=>{const d=l(t,"SELECT run_id FROM nodes WHERE node_id = ?").get(r);if(d?.run_id&&l(t,"SELECT deleting_at FROM nodes WHERE node_id = ?").get(d.run_id)?.deleting_at)throw new Error("run is deleting");if(e.idempotencyKey!==void 0){const c=l(t,`SELECT d.delivery_id, d.message_id, d.urgency, m.created_at
7
- FROM deliveries d JOIN messages m ON m.message_id = d.message_id WHERE d.idempotency_key = ?`).get(e.idempotencyKey);if(c!==void 0)return{messageId:c.message_id,deliveryId:c.delivery_id,urgency:c.urgency,createdAt:c.created_at}}const o=Date.now(),i=W(r,e.urgency),s=f(t,{messageId:e.messageId,operationId:n.operationId,createdAt:n.createdAt,senderNodeId:e.senderNodeId??null,senderName:e.senderName??null,kind:e.kind,label:e.label,bodyRef:n.bodyRef,bodyJson:n.bodyJson,disposition:e.disposition??null}),p=g(t,s,r,i,e.wake,o,e.idempotencyKey);return O(r,e.senderNodeId??null,o,t),e.withinEnqueue?.(t,s),e.wake===1&&i!=="deferred"&&m(r),{messageId:s,deliveryId:p,urgency:i,createdAt:n.createdAt}})}a(j,"enqueueNodeMail");function ee(r){switch(r){case"interrupt":return{urgency:"critical",wake:1};case"steer":return{urgency:"urgent",wake:1};case"after-turn":return{urgency:"normal",wake:1};case"next-turn":return{urgency:"deferred",wake:0}}}a(ee,"listenDeliveryTier");function re(r,e,n){const t={kind:"update",label:n.label??"notice",bodyJson:{body:n.body},urgency:n.tier,wake:n.wake},d=_(t,e),o=Date.now(),i=f(r,{operationId:d.operationId,createdAt:d.createdAt,senderNodeId:null,senderName:null,kind:t.kind,label:t.label,bodyRef:d.bodyRef,bodyJson:d.bodyJson,disposition:null}),s=g(r,i,e,n.tier,n.wake,o);return n.wake===1&&n.tier!=="deferred"&&m(e),{messageId:i,deliveryId:s,urgency:n.tier,createdAt:d.createdAt}}a(re,"queueNodeNotice");function ne(r,e=Date.now()){return u(n=>Number(l(n,"UPDATE deliveries SET canceled_at = ?, updated_at = ? WHERE delivery_id = ? AND canceled_at IS NULL").run(e,e,r).changes)===1)}a(ne,"cancelDelivery");function te(r,e={}){return u(n=>{const t=["d.destination_id = ?","d.canceled_at IS NULL","d.state IN ('pending', 'handed_off')"],d=[r];e.senderNodeId!==void 0&&(t.push("m.sender_node_id IS ?"),d.push(e.senderNodeId)),e.kind!==void 0&&(t.push("m.kind = ?"),d.push(e.kind));const o=n.prepare(`SELECT d.delivery_id FROM deliveries d JOIN messages m ON m.message_id = d.message_id WHERE ${t.join(" AND ")}`).all(...d);if(o.length===0)return[];const i=Date.now();return n.prepare(`UPDATE deliveries SET canceled_at = ?, updated_at = ? WHERE delivery_id IN (${o.map(()=>"?").join(",")})`).run(i,i,...o.map(s=>s.delivery_id)),o.map(s=>s.delivery_id)})}a(te,"cancelPendingNodeMail");function de(r,e){return u(n=>{const t=Date.now(),d=l(n,`SELECT target.status AS controller_status FROM waits w LEFT JOIN nodes target ON target.node_id = w.target_id
8
- WHERE w.node_id = ? AND w.kind = 'controller' AND w.target_id = ? AND w.satisfied_at IS NULL`).get(r,e);if(d===void 0||d.controller_status==="active"||d.controller_status==="idle")return null;const o=j(r,{kind:"urgent",label:"declared controller is no longer live",bodyJson:{body:`Controller ${e} is no longer live; the declared message wait was cleared.`},urgency:"urgent",wake:1});if(!T(r,e,t,n))throw new Error(`controller wait changed while notifying ${r}`);return o})}a(de,"enqueueControllerDeathNotice");export{ne as cancelDelivery,te as cancelPendingNodeMail,W as effectiveTier,de as enqueueControllerDeathNotice,j as enqueueNodeMail,_ as finalizeNodeMail,f as insertMessage,ee as listenDeliveryTier,y as newId,re as queueNodeNotice};
6
+ VALUES (?, ?, ?, ?, ?, 'pending', ?, ?, ?)`).run(o,e,t,n,a,i??null,d,d),o}s(f,"insertNodeDelivery");function g(r,e){const t=new Date().toISOString(),n=r.operationId===void 0?L.current()??x():J(r.operationId);let a=r.bodyRef??null,d=r.bodyJson;if(a===null&&e!==null&&r.senderNodeId!=="human"){const i=q(d),o=U(i);o.clipped&&(a=W(e,t,i),d={...d,body:o.text})}return{createdAt:t,operationId:n,bodyRef:a,bodyJson:d}}s(g,"finalizeNodeMail");async function j(r,e){const t=g(e,r);return await c(async n=>{const a=await n.prepare("SELECT run_id FROM nodes WHERE node_id = ?").get(r);if(a?.run_id&&(await n.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(a.run_id))?.deleting_at)throw new Error("run is deleting");if(e.idempotencyKey!==void 0){const l=await n.prepare(`SELECT d.delivery_id, d.message_id, d.urgency, m.created_at
7
+ FROM deliveries d JOIN messages m ON m.message_id = d.message_id WHERE d.idempotency_key = ?`).get(e.idempotencyKey);if(l!==void 0)return{messageId:l.message_id,deliveryId:l.delivery_id,urgency:l.urgency,createdAt:l.created_at}}const d=Date.now(),i=await M(r,e.urgency),o=await m(n,{messageId:e.messageId,operationId:t.operationId,createdAt:t.createdAt,senderNodeId:e.senderNodeId??null,senderName:e.senderName??null,kind:e.kind,label:e.label,bodyRef:t.bodyRef,bodyJson:t.bodyJson,disposition:e.disposition??null}),w=await f(n,o,r,i,e.wake,d,e.idempotencyKey);return await O(r,e.senderNodeId??null,d,n),await e.withinEnqueue?.(n,o),e.wake===1&&i!=="deferred"&&await u(r),{messageId:o,deliveryId:w,urgency:i,createdAt:t.createdAt}})}s(j,"enqueueNodeMail");function Z(r){switch(r){case"interrupt":return{urgency:"critical",wake:1};case"steer":return{urgency:"urgent",wake:1};case"after-turn":return{urgency:"normal",wake:1};case"next-turn":return{urgency:"deferred",wake:0}}}s(Z,"listenDeliveryTier");async function ee(r,e,t){const n={kind:"update",label:t.label??"notice",bodyJson:{body:t.body},urgency:t.tier,wake:t.wake},a=g(n,e),d=Date.now(),i=await m(r,{operationId:a.operationId,createdAt:a.createdAt,senderNodeId:null,senderName:null,kind:n.kind,label:n.label,bodyRef:a.bodyRef,bodyJson:a.bodyJson,disposition:null}),o=await f(r,i,e,t.tier,t.wake,d);return t.wake===1&&t.tier!=="deferred"&&await u(e),{messageId:i,deliveryId:o,urgency:t.tier,createdAt:a.createdAt}}s(ee,"queueNodeNotice");async function re(r,e=Date.now()){return Number((await(await h()).prepare("UPDATE deliveries SET canceled_at = ?, updated_at = ? WHERE delivery_id = ? AND canceled_at IS NULL").run(e,e,r)).changes)===1}s(re,"cancelDelivery");async function te(r,e={}){return await c(async t=>{const n=["d.destination_id = ?","d.canceled_at IS NULL","d.state IN ('pending', 'handed_off')"],a=[r];e.senderNodeId!==void 0&&(n.push("m.sender_node_id IS ?"),a.push(e.senderNodeId)),e.kind!==void 0&&(n.push("m.kind = ?"),a.push(e.kind));const d=await t.prepareUncached(`SELECT d.delivery_id FROM deliveries d JOIN messages m ON m.message_id = d.message_id WHERE ${n.join(" AND ")}`).all(...a);if(d.length===0)return[];const i=Date.now();return await t.prepareUncached(`UPDATE deliveries SET canceled_at = ?, updated_at = ? WHERE delivery_id IN (${d.map(()=>"?").join(",")})`).run(i,i,...d.map(o=>o.delivery_id)),d.map(o=>o.delivery_id)})}s(te,"cancelPendingNodeMail");async function ne(r,e){return await c(async t=>{const n=Date.now(),a=await t.prepare(`SELECT target.status AS controller_status FROM waits w LEFT JOIN nodes target ON target.node_id = w.target_id
8
+ WHERE w.node_id = ? AND w.kind = 'controller' AND w.target_id = ? AND w.satisfied_at IS NULL`).get(r,e);if(a===void 0||a.controller_status==="active"||a.controller_status==="idle")return null;const d=await j(r,{kind:"urgent",label:"declared controller is no longer live",bodyJson:{body:`Controller ${e} is no longer live; the declared message wait was cleared.`},urgency:"urgent",wake:1});if(!await T(r,e,n,t))throw new Error(`controller wait changed while notifying ${r}`);return d})}s(ne,"enqueueControllerDeathNotice");export{re as cancelDelivery,te as cancelPendingNodeMail,M as effectiveTier,ne as enqueueControllerDeathNotice,j as enqueueNodeMail,g as finalizeNodeMail,m as insertMessage,Z as listenDeliveryTier,y as newId,ee as queueNodeNotice};
@@ -1,10 +1,10 @@
1
1
  /** Whether `nodeId` owns any live report document — proof it already did work. */
2
- export declare function hasReportDocuments(nodeId: string): boolean;
2
+ export declare function hasReportDocuments(nodeId: string): Promise<boolean>;
3
3
  /** `<nodeId>/<name>` of `nodeId`'s newest live report document — the name
4
4
  * `crtr canvas read` takes — or null when it pushed none. */
5
- export declare function newestReportName(nodeId: string): string | null;
5
+ export declare function newestReportName(nodeId: string): Promise<string | null>;
6
6
  /** Body of `nodeId`'s newest live report document, trimmed; '' when it pushed none. */
7
- export declare function newestReportBody(nodeId: string): string;
7
+ export declare function newestReportBody(nodeId: string): Promise<string>;
8
8
  /** Body of the report document a push's `<nodeId>/reports/<name>` ref names;
9
9
  * null when the ref is not that shape or the document is gone. */
10
- export declare function reportBodyByName(ref: string): string | null;
10
+ export declare function reportBodyByName(ref: string): Promise<string | null>;
@@ -1,2 +1,2 @@
1
- var l=Object.defineProperty;var r=(t,e)=>l(t,"name",{value:e,configurable:!0});import{prepared as u}from"../sqlite-statements.js";import{openDb as d}from"../canvas/db.js";import{get as a}from"../graph/bodies.js";import{heads as p}from"../graph/documents.js";import{getById as c}from"../graph/objects.js";function R(t){const e=d(),n=c(e,t);return n===null||n.type!=="node"?!1:u(e,"SELECT 1 FROM objects WHERE owner = ? AND type = 'document' AND kind = 'report' AND deleted_at IS NULL LIMIT 1").get(n.rowid)!==void 0}r(R,"hasReportDocuments");function f(t){const e=d(),n=c(e,t);if(!(n===null||n.type!=="node"))return u(e,`SELECT * FROM objects WHERE owner = ? AND type = 'document' AND kind = 'report' AND deleted_at IS NULL
2
- ORDER BY created_at DESC, name DESC LIMIT 1`).get(n.rowid)}r(f,"newestReport");function L(t){const e=f(t);return e===void 0?null:`${t}/${e.name}`}r(L,"newestReportName");function b(t){const e=d(),n=f(t);if(n===void 0)return"";const o=p(e,n)[0];if(o===void 0)return"";try{return a(o.body_hash).trim()}catch{return""}}r(b,"newestReportBody");function w(t){const e=t.indexOf("/");if(e<=0||!t.startsWith("reports/",e+1))return null;const n=d(),o=c(n,t.slice(0,e));if(o===null||o.type!=="node")return null;const i=u(n,"SELECT * FROM objects WHERE owner = ? AND type = 'document' AND name = ? AND deleted_at IS NULL").get(o.rowid,t.slice(e+1)),s=i===void 0?void 0:p(n,i)[0];if(s===void 0)return null;try{return a(s.body_hash)}catch{return null}}r(w,"reportBodyByName");export{R as hasReportDocuments,b as newestReportBody,L as newestReportName,w as reportBodyByName};
1
+ var f=Object.defineProperty;var o=(t,e)=>f(t,"name",{value:e,configurable:!0});import{openDb as a}from"../canvas/db.js";import{get as u}from"../graph/bodies.js";import{heads as s}from"../graph/documents.js";import{getById as d}from"../graph/objects.js";async function D(t){const e=await a(),n=await d(e,t);return n===null||n.type!=="node"?!1:await e.prepare("SELECT 1 FROM objects WHERE owner = ? AND type = 'document' AND kind = 'report' AND deleted_at IS NULL LIMIT 1").get(n.rowid)!==void 0}o(D,"hasReportDocuments");async function p(t){const e=await a(),n=await d(e,t);if(!(n===null||n.type!=="node"))return await e.prepare(`SELECT * FROM objects WHERE owner = ? AND type = 'document' AND kind = 'report' AND deleted_at IS NULL
2
+ ORDER BY created_at DESC, name DESC LIMIT 1`).get(n.rowid)}o(p,"newestReport");async function N(t){const e=await p(t);return e===void 0?null:`${t}/${e.name}`}o(N,"newestReportName");async function h(t){const e=await a(),n=await p(t);if(n===void 0)return"";const r=(await s(e,n))[0];if(r===void 0)return"";try{return u(r.body_hash).trim()}catch{return""}}o(h,"newestReportBody");async function R(t){const e=t.indexOf("/");if(e<=0||!t.startsWith("reports/",e+1))return null;const n=await a(),r=await d(n,t.slice(0,e));if(r===null||r.type!=="node")return null;const i=await n.prepare("SELECT * FROM objects WHERE owner = ? AND type = 'document' AND name = ? AND deleted_at IS NULL").get(r.rowid,t.slice(e+1)),c=i===void 0?void 0:(await s(n,i))[0];if(c===void 0)return null;try{return u(c.body_hash)}catch{return null}}o(R,"reportBodyByName");export{D as hasReportDocuments,h as newestReportBody,N as newestReportName,R as reportBodyByName};
@@ -8,7 +8,7 @@ export type GrantSync = (options?: {
8
8
  export declare function ensureCovers(grantId: string, rev: number, syncGrants: GrantSync): Promise<void>;
9
9
  /** The mirrored grant a caller names, read now, when it is still the caller's: active, the same `sub` and
10
10
  * `grantee`, and not past `expires_at`. Otherwise 401 `grant_revoked`. */
11
- export declare function callerGrantOf(grantId: string, sub: string, grantee: string): ActiveGrant;
11
+ export declare function callerGrantOf(grantId: string, sub: string, grantee: string): Promise<ActiveGrant>;
12
12
  /** The grant a token's app link names: the mirror made to cover `rev`, then the grant itself checked against
13
13
  * `sub` and `grantee`. Errors are `ensureCovers`' and `callerGrantOf`'s `RunError`s. */
14
14
  export declare function coverGrant(grantId: string, rev: number, sub: string, grantee: string, syncGrants: GrantSync): Promise<ActiveGrant>;
@@ -1 +1 @@
1
- var l=Object.defineProperty;var r=(e,n)=>l(e,"name",{value:n,configurable:!0});import{emitEvent as w}from"../events/emit.js";import{RunError as a}from"../runs/operations.js";import{activeGrant as h,grantExpired as m,grantSyncState as s,grantsGeneration as g}from"./mirror.js";let c=new Map,f=-1;function u(e){const n=g();return n!==f&&(c=new Map,f=n),c.get(e)}r(u,"behindRev");const v=r((e,n)=>e!==null&&e.rev>=n,"covered");async function p(e,n,o){if(v(s(e),n))return;const t=u(e);if(t===void 0||n>t){try{await o({fresh:!0})}catch{throw new a(503,"service_unavailable","grant sync failed")}const i=s(e);if(v(i,n))return;u(e),c.set(e,Math.max(n,c.get(e)??0)),w({level:"error",event:"daemon.grants.behind_token",fields:{grant:e,token_rev:n,mirror_rev:i?.rev??0}})}throw s(e)?new a(503,"service_unavailable","the directory answered grant sync below the access token's grant revision"):new a(401,"grant_revoked","grant is not active")}r(p,"ensureCovers");function b(e,n,o){const t=h(e);if(!t||t.sub!==n||t.grantee!==o||m(t))throw new a(401,"grant_revoked","grant is not active");return t}r(b,"callerGrantOf");async function x(e,n,o,t,i){return await p(e,n,i),b(e,o,t)}r(x,"coverGrant");export{b as callerGrantOf,x as coverGrant,p as ensureCovers};
1
+ var v=Object.defineProperty;var r=(e,t)=>v(e,"name",{value:t,configurable:!0});import{emitEvent as l}from"../events/emit.js";import{RunError as o}from"../runs/operations.js";import{activeGrant as h,grantExpired as m,grantSyncState as s,grantsGeneration as g}from"./mirror.js";let c=new Map,w=-1;async function f(e){const t=await g();return t!==w&&(c=new Map,w=t),c.get(e)}r(f,"behindRev");const u=r((e,t)=>e!==null&&e.rev>=t,"covered");async function p(e,t,a){if(u(await s(e),t))return;const n=await f(e);if(n===void 0||t>n){try{await a({fresh:!0})}catch{throw new o(503,"service_unavailable","grant sync failed")}const i=await s(e);if(u(i,t))return;await f(e),c.set(e,Math.max(t,c.get(e)??0)),l({level:"error",event:"daemon.grants.behind_token",fields:{grant:e,token_rev:t,mirror_rev:i?.rev??0}})}throw await s(e)?new o(503,"service_unavailable","the directory answered grant sync below the access token's grant revision"):new o(401,"grant_revoked","grant is not active")}r(p,"ensureCovers");async function y(e,t,a){const n=await h(e);if(!n||n.sub!==t||n.grantee!==a||m(n))throw new o(401,"grant_revoked","grant is not active");return n}r(y,"callerGrantOf");async function x(e,t,a,n,i){return await p(e,t,i),await y(e,a,n)}r(x,"coverGrant");export{y as callerGrantOf,x as coverGrant,p as ensureCovers};
@@ -1,4 +1,4 @@
1
1
  /** The unjoined runtime's one grant; nodes created before join reference it by id. */
2
2
  export declare const LOCAL_TERMINAL_GRANT_ID = "local:terminal";
3
3
  /** An unjoined local runtime has exactly one grant, owned by its terminal app. */
4
- export declare function installLocalTerminalGrant(): void;
4
+ export declare function installLocalTerminalGrant(): Promise<void>;
@@ -1 +1 @@
1
- var l=Object.defineProperty;var r=(e,a)=>l(e,"name",{value:a,configurable:!0});import{replaceGrants as n}from"./mirror.js";const t=["crtr:llm","crtr:act","crtr:schedule","crtr:memory:rw:user","crtr:memory:manage:user","crtr:files:rw:user:."].map(e=>({scope:e,mode:"always"})),s="local:terminal";function p(){const e=new Date().toISOString();n([{id:s,runtime:"runtime:local",sub:"user:local",grantee:"app:terminal",rev:1,scopes:t,resolved_scopes:t,spend_cap:null,expires_at:null,status:"active",revoked_at:null,approved_at:e,payer:"user",dependencies:{},synced_at:e}],e,"local")}r(p,"installLocalTerminalGrant");export{s as LOCAL_TERMINAL_GRANT_ID,p as installLocalTerminalGrant};
1
+ var l=Object.defineProperty;var r=(e,t)=>l(e,"name",{value:t,configurable:!0});import{replaceGrants as n}from"./mirror.js";const a=["crtr:llm","crtr:act","crtr:schedule","crtr:memory:rw:user","crtr:memory:manage:user","crtr:files:rw:user:."].map(e=>({scope:e,mode:"always"})),s="local:terminal";async function p(){const e=new Date().toISOString();await n([{id:s,runtime:"runtime:local",sub:"user:local",grantee:"app:terminal",rev:1,scopes:a,resolved_scopes:a,spend_cap:null,expires_at:null,status:"active",revoked_at:null,approved_at:e,payer:"user",dependencies:{},synced_at:e}],e,"local")}r(p,"installLocalTerminalGrant");export{s as LOCAL_TERMINAL_GRANT_ID,p as installLocalTerminalGrant};
@@ -1,5 +1,5 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import { type Scope } from '@north-light/identity';
2
+ import { type CanvasDb } from '../canvas/db.js';
3
3
  import type { ProviderDependency } from '../../api/dto/grants.js';
4
4
  import type { ModelStrength } from '../../types.js';
5
5
  export interface GrantScope {
@@ -53,9 +53,9 @@ export declare function inferenceEndpointOf(value: unknown): InferenceEndpoint |
53
53
  * cascade, provider install, or run notice. */
54
54
  export declare function mirrorOnly(grant: Pick<GrantRecord, 'grantee'>): boolean;
55
55
  /** Every mirrored grant this machine acts on: `allGrants()` without the mirror-only ones. */
56
- export declare function localGrants(): GrantRecord[];
56
+ export declare function localGrants(): Promise<GrantRecord[]>;
57
57
  /** Every mirrored grant, whatever its status. */
58
- export declare function allGrants(): GrantRecord[];
58
+ export declare function allGrants(): Promise<GrantRecord[]>;
59
59
  /** Whether a grant's `expires_at` has passed. An unparsable time reads as expired (fail closed). */
60
60
  export declare function grantExpired(grant: Pick<GrantRecord, 'expires_at'>): boolean;
61
61
  /** The active form of a grant record read earlier, or null when it is not active, is past `expires_at`, or is unparsable. */
@@ -65,7 +65,7 @@ export declare function activeRecord(grant: GrantRecord): ActiveGrant | null;
65
65
  * `payer`, `inference_endpoint`, `dependencies`. `synced_at` and the token's claims are left out, so a
66
66
  * periodic sync with the same content (or a daemon restart) keeps it. */
67
67
  export declare function grantVersion(grant: Pick<GrantRecord, 'rev' | 'resolved_scopes' | 'spend_cap' | 'payer' | 'dependencies' | 'inference_endpoint'>): string;
68
- export declare function hasGrant(grantId: string): boolean;
68
+ export declare function hasGrant(grantId: string): Promise<boolean>;
69
69
  /** The grant state the freshness ordering reads (contract 1 "Grant sync"):
70
70
  * the mirrored grant's revision and status, whatever its status. */
71
71
  export interface GrantSyncState {
@@ -73,35 +73,35 @@ export interface GrantSyncState {
73
73
  status: GrantRecord['status'];
74
74
  }
75
75
  /** The mirrored state of grant `grantId`, or null when the mirror lacks it. */
76
- export declare function grantSyncState(grantId: string): GrantSyncState | null;
76
+ export declare function grantSyncState(grantId: string): Promise<GrantSyncState | null>;
77
77
  /** The mirrored state of the grant `sub` gave `grantee`, whatever its status, or null when the mirror lacks it. */
78
- export declare function grantSyncStateFor(grantee: string, sub: string): GrantSyncState | null;
78
+ export declare function grantSyncStateFor(grantee: string, sub: string): Promise<GrantSyncState | null>;
79
79
  /** The mirrored grant `grantId`, whatever its status, or null when the mirror lacks it or the row is unparsable. */
80
- export declare function grantRecord(grantId: string): GrantRecord | null;
80
+ export declare function grantRecord(grantId: string): Promise<GrantRecord | null>;
81
81
  /** Who a grant's model calls are charged to: `app` only for a mirrored grant the directory marked app-paid, else the person. */
82
- export declare function payerOfGrant(grantId: string | null | undefined): 'user' | 'app';
83
- export declare function activeGrant(grantId: string): ActiveGrant | null;
84
- export declare function grantFor(grantee: string, sub: string): ActiveGrant | null;
82
+ export declare function payerOfGrant(grantId: string | null | undefined): Promise<'user' | 'app'>;
83
+ export declare function activeGrant(grantId: string): Promise<ActiveGrant | null>;
84
+ export declare function grantFor(grantee: string, sub: string): Promise<ActiveGrant | null>;
85
85
  /** The app's own active grant on this machine. Null for a mirror-only grant: an
86
86
  * unsandboxed machine runs no app, so a fanned-out hosted grant is never "the
87
87
  * app's grant" for a local app caller, sandbox or install. */
88
- export declare function activeGrantForApp(grantee: string): ActiveGrant | null;
88
+ export declare function activeGrantForApp(grantee: string): Promise<ActiveGrant | null>;
89
89
  /** Where a run's notice goes: its grant's registered `run_notice_url`, with the grant's `sub` and `grantee`. Null when the run has no active grant or the grantee registered no URL. */
90
- export declare function runNoticeTarget(grantId: string): {
90
+ export declare function runNoticeTarget(grantId: string): Promise<{
91
91
  url: string;
92
92
  sub: string;
93
93
  grantee: string;
94
- } | null;
95
- export declare function terminalGrant(): ActiveGrant | null;
94
+ } | null>;
95
+ export declare function terminalGrant(): Promise<ActiveGrant | null>;
96
96
  /** Where the grant mirror came from: `'local'` for an unjoined runtime's own grant, the directory issuer once joined, null before any install. */
97
- export declare function grantsSource(): string | null;
98
- export declare function hasSyncedGrants(source: string): boolean;
97
+ export declare function grantsSource(): Promise<string | null>;
98
+ export declare function hasSyncedGrants(source: string): Promise<boolean>;
99
99
  /** OWN-11 for a joined runtime: the unjoined runtime's local mirror grants
100
100
  * `user:local` full local scopes and is not the directory's. Delete it so no
101
101
  * grant exists until grant sync installs the directory's mirror. */
102
- export declare function dropLocalGrantMirror(db: DatabaseSync): number;
102
+ export declare function dropLocalGrantMirror(db: CanvasDb): Promise<number>;
103
103
  /** The directory response is complete; commit it or keep the prior snapshot intact. */
104
- export declare function replaceGrants(grants: readonly GrantRecord[], syncedAt: string, source: string): void;
104
+ export declare function replaceGrants(grants: readonly GrantRecord[], syncedAt: string, source: string): Promise<void>;
105
105
  /** Bumped by every `replaceGrants`. A launch compiled against one generation
106
106
  * and started under another may hold mounts the new mirror no longer grants. */
107
- export declare function grantsGeneration(): number;
107
+ export declare function grantsGeneration(): Promise<number>;
@@ -1,4 +1,4 @@
1
- var y=Object.defineProperty;var t=(e,r)=>y(e,"name",{value:r,configurable:!0});import{createHash as g}from"node:crypto";import{prepared as o}from"../sqlite-statements.js";import{parseScope as S}from"@north-light/identity";import{openDb as u,withCanvasWrite as T}from"../canvas/db.js";import{isUnsandboxedMachine as m}from"../runtime/unsandboxed.js";const v=["not_started","pending","ready","failed","unavailable"],O=["ultra","strong","medium","light"];function p(e){if(!Array.isArray(e))throw new TypeError("grant scopes must be a list");return e.map(r=>{if(!r||typeof r!="object"||typeof r.scope!="string"||!["always","ask"].includes(r.mode))throw new TypeError("invalid grant scope entry");return{scope:r.scope,mode:r.mode}})}t(p,"entries");function x(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const{state:r,message:s,next:i,step:n}=e;return typeof r!="string"||!v.includes(r)||s!==void 0&&typeof s!="string"||n!==void 0&&typeof n!="string"||typeof i!="string"||!i?null:{state:r,...s===void 0?{}:{message:s},next:i,...n===void 0?{}:{step:n}}}t(x,"dependencyOf");function _(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const r={};for(const[s,i]of Object.entries(e)){const n=x(i);n&&(r[s]=n)}return r}t(_,"dependenciesOf");function R(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const{base_url:r,rungs:s}=e;if(typeof r!="string"||!r||!s||typeof s!="object"||Array.isArray(s))return null;const i={};for(const n of O){const c=s[n];typeof c=="string"&&c&&(i[n]=c)}return Object.keys(i).length?{base_url:r.replace(/\/+$/,""),rungs:i}:null}t(R,"inferenceEndpointOf");function f(e){return{id:e.id,runtime:e.runtime,sub:e.sub,grantee:e.grantee,rev:e.rev,scopes:p(JSON.parse(e.scopes_json)),resolved_scopes:p(JSON.parse(e.resolved_scopes_json)),spend_cap:e.spend_cap,expires_at:e.expires_at,status:e.status,revoked_at:e.revoked_at,approved_at:e.approved_at,payer:e.payer,dependencies:_(JSON.parse(e.dependencies_json)),run_notice_url:e.run_notice_url??null,inference_endpoint:e.inference_endpoint_json?R(JSON.parse(e.inference_endpoint_json)):null,synced_at:e.synced_at}}t(f,"record");function l(e){if(!e||e.status!=="active")return null;try{return h(f(e))}catch(r){if(r instanceof TypeError||r instanceof SyntaxError)return null;throw r}}t(l,"active");function d(e){return e.grantee!=="app:terminal"&&m()}t(d,"mirrorOnly");function H(){return N().filter(e=>!d(e))}t(H,"localGrants");function N(){return o(u(),"SELECT * FROM grants").all().flatMap(e=>{try{return[f(e)]}catch(r){if(r instanceof TypeError||r instanceof SyntaxError)return[];throw r}})}t(N,"allGrants");function A(e){return e.expires_at!==null&&!(Date.parse(e.expires_at)>Date.now())}t(A,"grantExpired");function h(e){if(e.status!=="active"||A(e))return null;try{const r=e.resolved_scopes.map(({scope:s})=>S(s));return{...e,resolved:e.resolved_scopes.flatMap(({mode:s},i)=>s==="always"?[r[i]]:[])}}catch(r){if(r instanceof TypeError||r instanceof SyntaxError)return null;throw r}}t(h,"activeRecord");function E(e){return Array.isArray(e)?`[${e.map(E).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().filter(r=>e[r]!==void 0).map(r=>`${JSON.stringify(r)}:${E(e[r])}`).join(",")}}`:JSON.stringify(e)??"null"}t(E,"canonicalJson");function D(e){const r={rev:e.rev,resolved_scopes:e.resolved_scopes,spend_cap:e.spend_cap,payer:e.payer,dependencies:e.dependencies??{},...e.inference_endpoint?{inference_endpoint:e.inference_endpoint}:{}};return g("sha256").update(E(r)).digest("base64url").slice(0,22)}t(D,"grantVersion");function W(e){return!!o(u(),"SELECT 1 FROM grants WHERE id = ?").get(e)}t(W,"hasGrant");function G(e){return o(u(),"SELECT rev, status FROM grants WHERE id = ?").get(e)??null}t(G,"grantSyncState");function J(e,r){return o(u(),"SELECT rev, status FROM grants WHERE grantee = ? AND sub = ?").get(e,r)??null}t(J,"grantSyncStateFor");function b(e){const r=o(u(),"SELECT * FROM grants WHERE id = ?").get(e);if(!r)return null;try{return f(r)}catch(s){if(s instanceof TypeError||s instanceof SyntaxError)return null;throw s}}t(b,"grantRecord");function I(e){return(e?b(e)?.payer:null)??"user"}t(I,"payerOfGrant");function U(e){return l(o(u(),"SELECT * FROM grants WHERE id = ?").get(e))}t(U,"activeGrant");function $(e,r){return l(o(u(),"SELECT * FROM grants WHERE grantee = ? AND sub = ?").get(e,r))}t($,"grantFor");function w(e){if(d({grantee:e}))return null;const r=o(u(),"SELECT * FROM grants WHERE grantee = ? AND status = 'active'").all(e);if(r.length>1)throw new Error(`multiple active grants for ${e}`);return l(r[0])}t(w,"activeGrantForApp");function V(e){const r=o(u(),"SELECT run_notice_url AS url, sub, grantee FROM grants WHERE id = ? AND status = 'active'").get(e);return r&&r.url&&!d(r)?{url:r.url,sub:r.sub,grantee:r.grantee}:null}t(V,"runNoticeTarget");function P(){const e=o(u(),"SELECT * FROM grants WHERE grantee = 'app:terminal' AND status = 'active'").all();if(e.length>1)throw new Error("multiple active terminal grants");return l(e[0])}t(P,"terminalGrant");function X(){return o(u(),"SELECT value FROM runtime_state WHERE key = 'grants_source'").get()?.value??null}t(X,"grantsSource");function q(e){return o(u(),"SELECT value FROM runtime_state WHERE key = 'grants_source'").get()?.value===e}t(q,"hasSyncedGrants");function z(e){return o(e,"SELECT value FROM runtime_state WHERE key = 'grants_source'").get()?.value!=="local"?0:(o(e,"DELETE FROM runtime_state WHERE key = 'grants_source'").run(),Number(o(e,"DELETE FROM grants").run().changes))}t(z,"dropLocalGrantMirror");function B(e,r,s){const i=new Set;for(const n of e){if(i.has(n.id)||!n.id||!n.runtime||!n.sub||!n.grantee||!Number.isInteger(n.rev)||!["active","revoked","removed"].includes(n.status))throw new TypeError("invalid grant sync response");i.add(n.id),p(n.scopes),p(n.resolved_scopes)}T(n=>{n.exec("DELETE FROM grants");const c=o(n,`INSERT INTO grants
1
+ var y=Object.defineProperty;var t=(e,r)=>y(e,"name",{value:r,configurable:!0});import{createHash as _}from"node:crypto";import{parseScope as g}from"@north-light/identity";import{openDb as o,withCanvasWrite as S}from"../canvas/db.js";import{isUnsandboxedMachine as T}from"../runtime/unsandboxed.js";const v=["not_started","pending","ready","failed","unavailable"],O=["ultra","strong","medium","light"];function p(e){if(!Array.isArray(e))throw new TypeError("grant scopes must be a list");return e.map(r=>{if(!r||typeof r!="object"||typeof r.scope!="string"||!["always","ask"].includes(r.mode))throw new TypeError("invalid grant scope entry");return{scope:r.scope,mode:r.mode}})}t(p,"entries");function m(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const{state:r,message:a,next:i,step:n}=e;return typeof r!="string"||!v.includes(r)||a!==void 0&&typeof a!="string"||n!==void 0&&typeof n!="string"||typeof i!="string"||!i?null:{state:r,...a===void 0?{}:{message:a},next:i,...n===void 0?{}:{step:n}}}t(m,"dependencyOf");function E(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const r={};for(const[a,i]of Object.entries(e)){const n=m(i);n&&(r[a]=n)}return r}t(E,"dependenciesOf");function w(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const{base_url:r,rungs:a}=e;if(typeof r!="string"||!r||!a||typeof a!="object"||Array.isArray(a))return null;const i={};for(const n of O){const c=a[n];typeof c=="string"&&c&&(i[n]=c)}return Object.keys(i).length?{base_url:r.replace(/\/+$/,""),rungs:i}:null}t(w,"inferenceEndpointOf");function l(e){return{id:e.id,runtime:e.runtime,sub:e.sub,grantee:e.grantee,rev:e.rev,scopes:p(JSON.parse(e.scopes_json)),resolved_scopes:p(JSON.parse(e.resolved_scopes_json)),spend_cap:e.spend_cap,expires_at:e.expires_at,status:e.status,revoked_at:e.revoked_at,approved_at:e.approved_at,payer:e.payer,dependencies:E(JSON.parse(e.dependencies_json)),run_notice_url:e.run_notice_url??null,inference_endpoint:e.inference_endpoint_json?w(JSON.parse(e.inference_endpoint_json)):null,synced_at:e.synced_at}}t(l,"record");function u(e){if(!e||e.status!=="active")return null;try{return N(l(e))}catch(r){if(r instanceof TypeError||r instanceof SyntaxError)return null;throw r}}t(u,"active");function f(e){return e.grantee!=="app:terminal"&&T()}t(f,"mirrorOnly");async function M(){return(await x()).filter(e=>!f(e))}t(M,"localGrants");async function x(){return(await(await o()).prepare("SELECT * FROM grants").all()).flatMap(e=>{try{return[l(e)]}catch(r){if(r instanceof TypeError||r instanceof SyntaxError)return[];throw r}})}t(x,"allGrants");function R(e){return e.expires_at!==null&&!(Date.parse(e.expires_at)>Date.now())}t(R,"grantExpired");function N(e){if(e.status!=="active"||R(e))return null;try{const r=e.resolved_scopes.map(({scope:a})=>g(a));return{...e,resolved:e.resolved_scopes.flatMap(({mode:a},i)=>a==="always"?[r[i]]:[])}}catch(r){if(r instanceof TypeError||r instanceof SyntaxError)return null;throw r}}t(N,"activeRecord");function d(e){return Array.isArray(e)?`[${e.map(d).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().filter(r=>e[r]!==void 0).map(r=>`${JSON.stringify(r)}:${d(e[r])}`).join(",")}}`:JSON.stringify(e)??"null"}t(d,"canonicalJson");function j(e){const r={rev:e.rev,resolved_scopes:e.resolved_scopes,spend_cap:e.spend_cap,payer:e.payer,dependencies:e.dependencies??{},...e.inference_endpoint?{inference_endpoint:e.inference_endpoint}:{}};return _("sha256").update(d(r)).digest("base64url").slice(0,22)}t(j,"grantVersion");async function k(e){return!!await(await o()).prepare("SELECT 1 FROM grants WHERE id = ?").get(e)}t(k,"hasGrant");async function H(e){return await(await o()).prepare("SELECT rev, status FROM grants WHERE id = ?").get(e)??null}t(H,"grantSyncState");async function D(e,r){return await(await o()).prepare("SELECT rev, status FROM grants WHERE grantee = ? AND sub = ?").get(e,r)??null}t(D,"grantSyncStateFor");async function A(e){const r=await(await o()).prepare("SELECT * FROM grants WHERE id = ?").get(e);if(!r)return null;try{return l(r)}catch(a){if(a instanceof TypeError||a instanceof SyntaxError)return null;throw a}}t(A,"grantRecord");async function W(e){return(e?(await A(e))?.payer:null)??"user"}t(W,"payerOfGrant");async function G(e){return u(await(await o()).prepare("SELECT * FROM grants WHERE id = ?").get(e))}t(G,"activeGrant");async function J(e,r){return u(await(await o()).prepare("SELECT * FROM grants WHERE grantee = ? AND sub = ?").get(e,r))}t(J,"grantFor");async function I(e){if(f({grantee:e}))return null;const r=await(await o()).prepare("SELECT * FROM grants WHERE grantee = ? AND status = 'active'").all(e);if(r.length>1)throw new Error(`multiple active grants for ${e}`);return u(r[0])}t(I,"activeGrantForApp");async function U(e){const r=await(await o()).prepare("SELECT run_notice_url AS url, sub, grantee FROM grants WHERE id = ? AND status = 'active'").get(e);return r&&r.url&&!f(r)?{url:r.url,sub:r.sub,grantee:r.grantee}:null}t(U,"runNoticeTarget");async function $(){const e=await(await o()).prepare("SELECT * FROM grants WHERE grantee = 'app:terminal' AND status = 'active'").all();if(e.length>1)throw new Error("multiple active terminal grants");return u(e[0])}t($,"terminalGrant");async function V(){return(await(await o()).prepare("SELECT value FROM runtime_state WHERE key = 'grants_source'").get())?.value??null}t(V,"grantsSource");async function P(e){return(await(await o()).prepare("SELECT value FROM runtime_state WHERE key = 'grants_source'").get())?.value===e}t(P,"hasSyncedGrants");async function X(e){return(await e.prepare("SELECT value FROM runtime_state WHERE key = 'grants_source'").get())?.value!=="local"?0:(await e.prepare("DELETE FROM runtime_state WHERE key = 'grants_source'").run(),Number((await e.prepare("DELETE FROM grants").run()).changes))}t(X,"dropLocalGrantMirror");async function q(e,r,a){const i=new Set;for(const n of e){if(i.has(n.id)||!n.id||!n.runtime||!n.sub||!n.grantee||!Number.isInteger(n.rev)||!["active","revoked","removed"].includes(n.status))throw new TypeError("invalid grant sync response");i.add(n.id),p(n.scopes),p(n.resolved_scopes)}await S(async n=>{await n.exec("DELETE FROM grants");const c=n.prepare(`INSERT INTO grants
2
2
  (id, runtime, sub, grantee, rev, scopes_json, resolved_scopes_json, spend_cap, expires_at,
3
3
  status, revoked_at, approved_at, payer, dependencies_json, run_notice_url, inference_endpoint_json, synced_at)
4
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(const a of e)c.run(a.id,a.runtime,a.sub,a.grantee,a.rev,JSON.stringify(a.scopes),JSON.stringify(a.resolved_scopes),a.spend_cap,a.expires_at,a.status,a.revoked_at,a.approved_at,a.payer,JSON.stringify(_(a.dependencies)),a.run_notice_url??null,a.inference_endpoint?JSON.stringify(a.inference_endpoint):null,a.synced_at);o(n,"INSERT INTO runtime_state (key, value) VALUES ('grants_source', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(s),o(n,"INSERT INTO runtime_state (key, value) VALUES ('grants_generation', '1') ON CONFLICT(key) DO UPDATE SET value = CAST(CAST(value AS INTEGER) + 1 AS TEXT)").run()})}t(B,"replaceGrants");function K(){const e=o(u(),"SELECT value FROM runtime_state WHERE key = 'grants_generation'").get();return e?Number(e.value):0}t(K,"grantsGeneration");export{U as activeGrant,w as activeGrantForApp,h as activeRecord,N as allGrants,_ as dependenciesOf,z as dropLocalGrantMirror,A as grantExpired,$ as grantFor,b as grantRecord,G as grantSyncState,J as grantSyncStateFor,D as grantVersion,K as grantsGeneration,X as grantsSource,W as hasGrant,q as hasSyncedGrants,R as inferenceEndpointOf,H as localGrants,d as mirrorOnly,I as payerOfGrant,B as replaceGrants,V as runNoticeTarget,P as terminalGrant};
4
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(const s of e)await c.run(s.id,s.runtime,s.sub,s.grantee,s.rev,JSON.stringify(s.scopes),JSON.stringify(s.resolved_scopes),s.spend_cap,s.expires_at,s.status,s.revoked_at,s.approved_at,s.payer,JSON.stringify(E(s.dependencies)),s.run_notice_url??null,s.inference_endpoint?JSON.stringify(s.inference_endpoint):null,s.synced_at);await n.prepare("INSERT INTO runtime_state (key, value) VALUES ('grants_source', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(a),await n.prepare("INSERT INTO runtime_state (key, value) VALUES ('grants_generation', '1') ON CONFLICT(key) DO UPDATE SET value = CAST(CAST(value AS INTEGER) + 1 AS TEXT)").run()})}t(q,"replaceGrants");async function z(){const e=await(await o()).prepare("SELECT value FROM runtime_state WHERE key = 'grants_generation'").get();return e?Number(e.value):0}t(z,"grantsGeneration");export{G as activeGrant,I as activeGrantForApp,N as activeRecord,x as allGrants,E as dependenciesOf,X as dropLocalGrantMirror,R as grantExpired,J as grantFor,A as grantRecord,H as grantSyncState,D as grantSyncStateFor,j as grantVersion,z as grantsGeneration,V as grantsSource,k as hasGrant,P as hasSyncedGrants,w as inferenceEndpointOf,M as localGrants,f as mirrorOnly,W as payerOfGrant,q as replaceGrants,U as runNoticeTarget,$ as terminalGrant};
@@ -7,7 +7,7 @@ export type Detach = (work: Promise<void>) => void;
7
7
  export declare function exceeds(sandbox: Pick<SandboxRecord, 'uid' | 'nodeId' | 'mounts'>, owners?: ReadonlyMap<number, {
8
8
  app: string;
9
9
  status: string;
10
- }>): string | null;
10
+ }>): Promise<string | null>;
11
11
  /** R26 from current state (runtime spec §15 "Ending revoked file access"):
12
12
  * compare every live launcher sandbox's launched mounts with what the current
13
13
  * mirror grants, and stop each one that holds more. Runs after every sync and
@@ -1 +1 @@
1
- var w=Object.defineProperty;var c=(n,r)=>w(n,"name",{value:r,configurable:!0});import{prepared as v}from"../sqlite-statements.js";import{relative as b,sep as g}from"node:path";import{activeBackgroundBashJobs as x,readJobPgid as y}from"../bash-jobs.js";import{appSpace as S}from"../layout.js";import{getNode as l,recordSettledTurn as k}from"../canvas/index.js";import{transition as E}from"../runtime/lifecycle.js";import{openDb as _}from"../canvas/db.js";import{contextDir as R}from"../canvas/node-agent-paths.js";import{emitEvent as p}from"../events/emit.js";import{closeGrantStreams as C}from"../runs/events.js";import{grantedMounts as G,isGrantedSource as I,mountAllowed as P}from"../spaces/mounts.js";import{permissionsForRun as m}from"../spaces/permissions.js";import{stopNodeSandboxes as O}from"../spaces/stop.js";import{discardChangedGrantTokens as T}from"../providers/token-cache.js";import{activeGrantForApp as F,allGrants as M,mirrorOnly as A}from"./mirror.js";import{runRemovalCascades as D}from"./remove.js";import{notifyGrantChanges as N}from"./watch.js";import{launcherPresent as W,listSandboxes as j,stopSandboxPid as B}from"./sandboxes.js";import{checkCronFire as J}from"../../daemon/cron/authority.js";import{cronExecutionFor as L}from"../../daemon/cron/live-runs.js";import{cronExecutionsReady as U}from"../../daemon/cron/run-socket.js";function h(){return new Map(v(_(),"SELECT uid, app, status FROM app_users").all().map(n=>[n.uid,{app:n.app,status:n.status}]))}c(h,"appUserOwners");function $(n,r=h()){const o=r.get(n.uid),i=n.nodeId.startsWith("cron-"),e=i?L(n.nodeId.slice(5)):void 0;if(i&&(e===void 0||!o))return"permission_revoked";if(e!==void 0&&o.status==="active"){const s=J({grantee:e.grantee,sub:e.sub,grant_id:e.grantId,scopes:e.scopes});if(!s.allowed)return e.refusal??={reason:s.reason,message:s.message},"permission_revoked"}if(!o||o.app==="app:terminal")return null;if(o.status!=="active")return"app_removed";const t=l(n.nodeId);try{let s;if(e!==void 0)s=m(e.grantee,e.sub,e.grantId,e.scopes);else if(t&&t.grantee===o.app)s=m(o.app,t.sub??"user:local",t.grant_id??null,t.scopes??null);else{const d=F(o.app);if(!d)return"permission_revoked";s=m(o.app,d.sub,d.id,null)}const u=G(s),f=S(o.app).root;return n.mounts.every(d=>{const a=b(f,d.source);return a===""||a!==".."&&!a.startsWith(`..${g}`)&&!a.startsWith(g)||!I(o.app,d.source)||P(d,u)})?null:"permission_revoked"}catch{return"permission_revoked"}}c($,"exceeds");async function H(n){const r=l(n);if(!r)return;(r.status==="active"||r.status==="idle")&&E(n,"release");const o=new Date().toISOString();k(n,o),r.run_id&&r.run_id!==n&&v(_(),"UPDATE nodes SET last_settled_at = COALESCE(last_settled_at, ?) WHERE node_id = ?").run(o,r.run_id)}c(H,"afterRevocationStop");function q(n){const r=new Set,o=l(n);o?.pi_pid!=null&&r.add(o.pi_pid);try{const i=R(n,o?.grantee);for(const e of x(i,!0)){const t=y(i,e.jobId);t!==void 0&&r.add(t)}}catch{}return r}c(q,"nodePids");async function z(){if(!W())return{completion:Promise.resolve()};await U();const n=await j(),r=h(),o=n.flatMap(t=>{const s=$(t,r);return s?[{sandbox:t,reason:s}]:[]}),i=[],e=new Map;for(const t of o){p({level:"info",event:"daemon.grants.sandbox_stop",fields:{sandbox_node:t.sandbox.nodeId,pid:t.sandbox.pid,grantee:r.get(t.sandbox.uid).app,reason:t.reason}});const s=e.get(t.sandbox.nodeId)??[];s.push(t),e.set(t.sandbox.nodeId,s)}for(const[t,s]of e){const u=l(t),f=u?q(t):new Set,d=u!==null&&s.some(({sandbox:a})=>f.has(a.pid));i.push((async()=>{if(d){const a=await O(t,"permission_revoked",{holdRecovery:!0,after:c(()=>H(t),"after")});if(!a.confirmed)throw a.error??new Error(`stop of ${t} was not confirmed`)}for(const{sandbox:a}of s)(!d||!f.has(a.pid))&&await B(a.pid)})().catch(a=>{p({level:"error",event:"daemon.grants.sandbox_stop_failed",...u?{node_id:t}:{fields:{sandbox_node:t}},error:a})}))}return{completion:Promise.all(i).then(()=>{})}}c(z,"sweepSandboxes");function K(n,r){try{const{pairs:o,providers:i,tokens:e}=T(n,r);(o||i)&&p({level:"info",event:"daemon.grants.outbound_tokens_discarded",fields:{grants:o,providers:i,tokens:e}})}catch(o){p({level:"error",event:"daemon.grants.outbound_tokens_discard_failed",error:o})}}c(K,"discardOutboundTokens");async function he(n,r=o=>{}){const o=M();try{N(n,o)}catch(e){p({level:"error",event:"daemon.grants.notify_failed",error:e})}K(n,o);for(const e of n){if(e.status!=="active"||o.find(u=>u.id===e.id)?.status==="active")continue;const s=C(e.id);s&&p({level:"info",event:"daemon.grants.streams_closed",fields:{grant:e.id,grantee:e.grantee,streams:s}})}try{const{completion:e}=await z();r(e)}catch(e){p({level:"error",event:"daemon.grants.sweep_failed",error:e})}const i=new Set(o.filter(e=>!A(e)&&e.status==="removed"&&n.find(t=>t.id===e.id)?.status!=="removed").map(e=>e.grantee));r(D(i).catch(()=>{})),r(import("../providers/bundles.js").then(({syncProviderBundles:e})=>e()).catch(e=>{p({level:"error",event:"daemon.providers.bundle_sync_failed",error:e})}))}c(he,"onGrantSync");export{$ as exceeds,he as onGrantSync,z as sweepSandboxes};
1
+ var _=Object.defineProperty;var c=(n,r)=>_(n,"name",{value:r,configurable:!0});import{relative as y,sep as w}from"node:path";import{activeBackgroundBashJobs as h,readJobPgid as b}from"../bash-jobs.js";import{appSpace as x}from"../layout.js";import{getNode as l,recordSettledTurn as S}from"../canvas/index.js";import{transition as k}from"../runtime/lifecycle.js";import{openDb as v}from"../canvas/db.js";import{contextDir as E}from"../canvas/node-agent-paths.js";import{emitEvent as p}from"../events/emit.js";import{closeGrantStreams as R}from"../runs/events.js";import{grantedMounts as C,isGrantedSource as G,mountAllowed as I}from"../spaces/mounts.js";import{permissionsForRun as m}from"../spaces/permissions.js";import{stopNodeSandboxes as P}from"../spaces/stop.js";import{discardChangedGrantTokens as O}from"../providers/token-cache.js";import{activeGrantForApp as T,allGrants as A,mirrorOnly as F}from"./mirror.js";import{runRemovalCascades as M}from"./remove.js";import{notifyGrantChanges as D}from"./watch.js";import{launcherPresent as N,listSandboxes as W,stopSandboxPid as j}from"./sandboxes.js";import{checkCronFire as B}from"../../daemon/cron/authority.js";import{cronExecutionFor as J}from"../../daemon/cron/live-runs.js";import{cronExecutionsReady as L}from"../../daemon/cron/run-socket.js";import{flatMapAsync as U}from"../async-array.js";async function g(){return new Map((await(await v()).prepare("SELECT uid, app, status FROM app_users").all()).map(n=>[n.uid,{app:n.app,status:n.status}]))}c(g,"appUserOwners");async function $(n,r){r??=await g();const t=r.get(n.uid),i=n.nodeId.startsWith("cron-"),e=i?J(n.nodeId.slice(5)):void 0;if(i&&(e===void 0||!t))return"permission_revoked";if(e!==void 0&&t.status==="active"){const a=await B({grantee:e.grantee,sub:e.sub,grant_id:e.grantId,scopes:e.scopes});if(!a.allowed)return e.refusal??={reason:a.reason,message:a.message},"permission_revoked"}if(!t||t.app==="app:terminal")return null;if(t.status!=="active")return"app_removed";const o=await l(n.nodeId);try{let a;if(e!==void 0)a=await m(e.grantee,e.sub,e.grantId,e.scopes);else if(o&&o.grantee===t.app)a=await m(t.app,o.sub??"user:local",o.grant_id??null,o.scopes??null);else{const d=await T(t.app);if(!d)return"permission_revoked";a=await m(t.app,d.sub,d.id,null)}const u=C(a),f=x(t.app).root;return n.mounts.every(d=>{const s=y(f,d.source);return s===""||s!==".."&&!s.startsWith(`..${w}`)&&!s.startsWith(w)||!G(t.app,d.source)||I(d,u)})?null:"permission_revoked"}catch{return"permission_revoked"}}c($,"exceeds");async function H(n){const r=await l(n);if(!r)return;(r.status==="active"||r.status==="idle")&&await k(n,"release");const t=new Date().toISOString();await S(n,t),r.run_id&&r.run_id!==n&&await(await v()).prepare("UPDATE nodes SET last_settled_at = COALESCE(last_settled_at, ?) WHERE node_id = ?").run(t,r.run_id)}c(H,"afterRevocationStop");async function q(n){const r=new Set,t=await l(n);t?.pi_pid!=null&&r.add(t.pi_pid);try{const i=await E(n,t?.grantee);for(const e of h(i,!0)){const o=b(i,e.jobId);o!==void 0&&r.add(o)}}catch{}return r}c(q,"nodePids");async function z(){if(!N())return{completion:Promise.resolve()};await L();const n=await W(),r=await g(),t=await U(n,async o=>{const a=await $(o,r);return a?[{sandbox:o,reason:a}]:[]}),i=[],e=new Map;for(const o of t){p({level:"info",event:"daemon.grants.sandbox_stop",fields:{sandbox_node:o.sandbox.nodeId,pid:o.sandbox.pid,grantee:r.get(o.sandbox.uid).app,reason:o.reason}});const a=e.get(o.sandbox.nodeId)??[];a.push(o),e.set(o.sandbox.nodeId,a)}for(const[o,a]of e){const u=await l(o),f=u?await q(o):new Set,d=u!==null&&a.some(({sandbox:s})=>f.has(s.pid));i.push((async()=>{if(d){const s=await P(o,"permission_revoked",{holdRecovery:!0,after:c(()=>H(o),"after")});if(!s.confirmed)throw s.error??new Error(`stop of ${o} was not confirmed`)}for(const{sandbox:s}of a)(!d||!f.has(s.pid))&&await j(s.pid)})().catch(s=>{p({level:"error",event:"daemon.grants.sandbox_stop_failed",...u?{node_id:o}:{fields:{sandbox_node:o}},error:s})}))}return{completion:Promise.all(i).then(()=>{})}}c(z,"sweepSandboxes");function K(n,r){try{const{pairs:t,providers:i,tokens:e}=O(n,r);(t||i)&&p({level:"info",event:"daemon.grants.outbound_tokens_discarded",fields:{grants:t,providers:i,tokens:e}})}catch(t){p({level:"error",event:"daemon.grants.outbound_tokens_discard_failed",error:t})}}c(K,"discardOutboundTokens");async function _e(n,r=t=>{}){const t=await A();try{D(n,t)}catch(e){p({level:"error",event:"daemon.grants.notify_failed",error:e})}K(n,t);for(const e of n){if(e.status!=="active"||t.find(u=>u.id===e.id)?.status==="active")continue;const a=R(e.id);a&&p({level:"info",event:"daemon.grants.streams_closed",fields:{grant:e.id,grantee:e.grantee,streams:a}})}try{const{completion:e}=await z();r(e)}catch(e){p({level:"error",event:"daemon.grants.sweep_failed",error:e})}const i=new Set(t.filter(e=>!F(e)&&e.status==="removed"&&n.find(o=>o.id===e.id)?.status!=="removed").map(e=>e.grantee));r(M(i).catch(()=>{})),r(import("../providers/bundles.js").then(({syncProviderBundles:e})=>e()).catch(e=>{p({level:"error",event:"daemon.providers.bundle_sync_failed",error:e})}))}c(_e,"onGrantSync");export{$ as exceeds,_e as onGrantSync,z as sweepSandboxes};
@@ -1 +1 @@
1
- var S=Object.defineProperty;var m=(r,i)=>S(r,"name",{value:i,configurable:!0});import{prepared as d}from"../sqlite-statements.js";import{rmSync as h}from"node:fs";import{join as w}from"node:path";import{deleteNodes as O}from"../canvas/canvas.js";import{openDb as c,withCanvasWrite as E}from"../canvas/db.js";import{cancelCron as T}from"../canvas/crons.js";import{emitEvent as l}from"../events/emit.js";import{appSpace as C,appsRoot as u,secretsDir as D}from"../layout.js";import{notifyRunDeleted as L}from"../runs/events.js";import{cancelOpenQuestions as W}from"../runs/questions.js";import{removeTreeBeneath as F}from"../spaces/open-beneath.js";import{markGranteeUploadsDeletePending as H,releaseRunUploads as N,turnSharesOffFor as M}from"../storage/tables.js";import{stopNodeSandboxes as b}from"../spaces/stop.js";import{activeAppUser as p,markAppUserRemoved as I}from"../spaces/users.js";import{launcherRequest as y}from"../../launcher/client.js";import{LaunchRefused as A}from"../../launcher/spec.js";import{localGrants as P}from"./mirror.js";import{launcherPresent as g,listSandboxes as U,stopSandboxPid as $}from"./sandboxes.js";let v=Promise.resolve();function ae(r=new Set){const i=v.then(async()=>{const t=P(),o=new Set(t.filter(n=>n.status==="removed").map(n=>n.grantee));for(const n of o)if(!t.some(a=>a.grantee===n&&a.status==="active")&&!(p(n)===null&&!r.has(n)))try{await x(n)}catch(a){l({level:"error",event:"daemon.grants.removal_failed",error:a,fields:{grantee:n}})}});return v=i.catch(()=>{}),i}m(ae,"runRemovalCascades");async function x(r){if(r==="app:terminal")throw new Error("app:terminal cannot be removed");const i=C(r),t=p(r);l({level:"info",event:"daemon.grants.removal_started",fields:{grantee:r,uid:t?.uid??null}}),await W({grantee:r},"the app was removed");const o=E(e=>(d(e,"UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id IN (SELECT node_id FROM node_rows WHERE grantee = ?)").run(new Date().toISOString(),r),d(e,"SELECT node_id FROM node_rows WHERE grantee = ? ORDER BY created DESC").all(r).map(s=>s.node_id)));for(const{cron_id:e}of d(c(),"SELECT cron_id FROM crons WHERE grantee = ?").all(r))T(e);const a=(await Promise.all(o.map(e=>b(e,"app_removed",{deleting:!0})))).filter(e=>!e.confirmed);if(a.length)throw new Error(`sandbox teardown could not be confirmed for ${a.length} node(s) of ${r}`);if(t&&g())for(const e of await U())e.uid===t.uid&&await $(e.pid);const R=o.filter(e=>d(c(),"SELECT run_id FROM nodes WHERE node_id = ?").get(e)?.run_id===e);E(e=>{if(M(r,e),N(o,e),H(r,e),!o.length)return;const s=o.map(()=>"?").join(","),_=e.prepare(`SELECT message_id FROM messages WHERE sender_node_id IN (${s}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${s})`).all(...o,...o);e.prepare(`DELETE FROM deliveries WHERE destination_id IN (${s})`).run(...o);for(const{message_id:f}of _)d(e,"DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(f,f)}),O(o);for(const e of R)L(e);if(h(w(D(),"env",i.root.slice(u().length+1)),{recursive:!0,force:!0}),F(u(),i.root),t&&g())try{await y({operation:"user.delete",uid:t.uid})}catch(e){if(!(e instanceof A&&e.refusal==="invalid_uid"))throw e}t&&I(t.uid),l({level:"info",event:"daemon.grants.removal_completed",fields:{grantee:r,uid:t?.uid??null,nodes:o.length}})}m(x,"removeApp");export{x as removeApp,ae as runRemovalCascades};
1
+ var R=Object.defineProperty;var d=(r,n)=>R(r,"name",{value:n,configurable:!0});import{rmSync as _}from"node:fs";import{join as h}from"node:path";import{deleteNodes as S}from"../canvas/canvas.js";import{withCanvasWrite as c,openDb as f}from"../canvas/db.js";import{cancelCron as O}from"../canvas/crons.js";import{emitEvent as m}from"../events/emit.js";import{appSpace as T,appsRoot as E,secretsDir as C}from"../layout.js";import{notifyRunDeleted as D}from"../runs/events.js";import{cancelOpenQuestions as L}from"../runs/questions.js";import{removeTreeBeneath as W}from"../spaces/open-beneath.js";import{markGranteeUploadsDeletePending as y,releaseRunUploads as F,turnSharesOffFor as H}from"../storage/tables.js";import{stopNodeSandboxes as N}from"../spaces/stop.js";import{activeAppUser as p,markAppUserRemoved as M}from"../spaces/users.js";import{launcherRequest as U}from"../../launcher/client.js";import{LaunchRefused as b}from"../../launcher/spec.js";import{localGrants as A}from"./mirror.js";import{launcherPresent as u,listSandboxes as I,stopSandboxPid as P}from"./sandboxes.js";import{filterAsync as $}from"../async-array.js";let w=Promise.resolve();function ie(r=new Set){const n=w.then(async()=>{const o=await A(),t=new Set(o.filter(a=>a.status==="removed").map(a=>a.grantee));for(const a of t)if(!o.some(i=>i.grantee===a&&i.status==="active")&&!(await p(a)===null&&!r.has(a)))try{await x(a)}catch(i){m({level:"error",event:"daemon.grants.removal_failed",error:i,fields:{grantee:a}})}});return w=n.catch(()=>{}),n}d(ie,"runRemovalCascades");async function x(r){if(r==="app:terminal")throw new Error("app:terminal cannot be removed");const n=T(r),o=await p(r);m({level:"info",event:"daemon.grants.removal_started",fields:{grantee:r,uid:o?.uid??null}}),await L({grantee:r},"the app was removed");const t=await c(async e=>(await e.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id IN (SELECT node_id FROM node_rows WHERE grantee = ?)").run(new Date().toISOString(),r),(await e.prepare("SELECT node_id FROM node_rows WHERE grantee = ? ORDER BY created DESC").all(r)).map(s=>s.node_id)));for(const{cron_id:e}of await(await f()).prepare("SELECT cron_id FROM crons WHERE grantee = ?").all(r))await O(e);const i=(await Promise.all(t.map(e=>N(e,"app_removed",{deleting:!0})))).filter(e=>!e.confirmed);if(i.length)throw new Error(`sandbox teardown could not be confirmed for ${i.length} node(s) of ${r}`);if(o&&u())for(const e of await I())e.uid===o.uid&&await P(e.pid);const g=await $(t,async e=>(await(await f()).prepare("SELECT run_id FROM nodes WHERE node_id = ?").get(e))?.run_id===e);await c(async e=>{if(await H(r,e),await F(t,e),await y(r,e),!t.length)return;const s=t.map(()=>"?").join(","),v=await e.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${s}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${s})`).all(...t,...t);await e.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${s})`).run(...t);for(const{message_id:l}of v)await e.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(l,l)}),await S(t);for(const e of g)D(e);if(_(h(C(),"env",n.root.slice(E().length+1)),{recursive:!0,force:!0}),W(E(),n.root),o&&u())try{await U({operation:"user.delete",uid:o.uid})}catch(e){if(!(e instanceof b&&e.refusal==="invalid_uid"))throw e}o&&await M(o.uid),m({level:"info",event:"daemon.grants.removal_completed",fields:{grantee:r,uid:o?.uid??null,nodes:t.length}})}d(x,"removeApp");export{x as removeApp,ie as runRemovalCascades};
@@ -1 +1 @@
1
- var w=Object.defineProperty;var r=(t,n)=>w(t,"name",{value:n,configurable:!0});import{createPrivateKey as v,randomUUID as E,sign as S}from"node:crypto";import{readFileSync as b}from"node:fs";import{join as j}from"node:path";import{crtrHome as x}from"../canvas/paths.js";import{isUnsandboxedMachine as g}from"../runtime/unsandboxed.js";import{emitEvent as f}from"../events/emit.js";import{allGrants as $,dependenciesOf as T,inferenceEndpointOf as A,replaceGrants as N}from"./mirror.js";import{onGrantSync as O}from"./on-sync.js";const H=300;function G(t,n){const e=Math.floor(Date.now()/1e3),s=Buffer.from(JSON.stringify({alg:"ES256",typ:"JWT",kid:t.kid})).toString("base64url"),c=Buffer.from(JSON.stringify({iss:t.client_id,sub:t.client_id,aud:n,iat:e,exp:e+300,jti:E()})).toString("base64url"),o=`${s}.${c}`,i=S("sha256",Buffer.from(o),{key:v({key:t.jwk,format:"jwk"}),dsaEncoding:"ieee-p1363"});return`${o}.${i.toString("base64url")}`}r(G,"assertion");function y(){const t=JSON.parse(b(j(x(),"secrets","runtime-client.json"),"utf8"));if(!t.jwk||t.alg!=="ES256"||!t.kid||!t.client_id||!t.runtime||t.jwk.kid!==t.kid||t.jwk.kty!=="EC"||t.jwk.crv!=="P-256"||!t.jwk.d)throw new TypeError("invalid runtime client key");return t}r(y,"runtimeClient");function K(t=y()){return t.runtime.startsWith("runtime:")?t.runtime.slice(8):t.runtime}r(K,"runtimeId");function R(t){return`This machine was removed from your Northlight account. To use it again, create a join token at ${t.replace(/\/$/,"")}/account/machines, and run \`crtr sys join\` from a plain terminal.`}r(R,"machineRevokedMessage");class h extends Error{static{r(this,"MachineRevokedError")}constructor(n){super(R(n)),this.name="MachineRevokedError"}}async function B(t,n){const e=y(),s=`${t.replace(/\/$/,"")}/token`,c=new URLSearchParams({grant_type:"client_credentials",client_id:e.client_id,client_assertion_type:"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",client_assertion:G(e,s),...n===void 0?{}:{audience:n}}),o=await fetch(s,{method:"POST",body:c,signal:AbortSignal.timeout(1e4)});if(!o.ok)throw o.status===401&&g()&&await D(o)?new h(t):new Error(`directory token request failed: ${o.status}`);const i=await o.json();if(typeof i.access_token!="string")throw new TypeError("directory token response has no access_token");return{access_token:i.access_token,expires_at:J(i.access_token,i.expires_in)}}r(B,"mintDirectoryToken");async function D(t){try{return(await t.json()).error==="invalid_client"}catch{return!1}}r(D,"isInvalidClient");function J(t,n){if(typeof n=="number"&&Number.isFinite(n)&&n>0)return Date.now()+n*1e3;try{const e=JSON.parse(Buffer.from(t.split(".")[1]??"","base64url").toString("utf8"));if(typeof e.exp=="number")return e.exp*1e3}catch{}return Date.now()+3e5}r(J,"tokenExpiry");function M(t,n){if(!t||typeof t!="object")throw new TypeError("invalid grant sync response");const e=t,s=n.runtime.startsWith("runtime:")?n.runtime:`runtime:${n.runtime}`;if(!(e.runtime===s||g()&&typeof e.runtime=="string"&&e.runtime.startsWith("runtime:")&&e.grantee!=="app:terminal")||typeof e.id!="string"||typeof e.sub!="string"||typeof e.grantee!="string"||!Number.isInteger(e.rev)||!Array.isArray(e.scopes)||!Array.isArray(e.resolved_scopes)||!["active","revoked","removed"].includes(e.status??"")||typeof e.synced_at!="string")throw new TypeError("invalid grant sync response");const i=t.revisions?.find(a=>a.rev===e.rev)?.approved_at;if(typeof i!="string")throw new TypeError("grant revision has no approval time");const d=e.payer==="app"?"app":"user";return{...e,spend_cap:e.spend_cap??null,expires_at:e.expires_at??null,revoked_at:e.revoked_at??null,approved_at:i,payer:d,dependencies:T(e.dependencies),inference_endpoint:d==="app"?A(e.inference_endpoint):null,run_notice_url:typeof e.run_notice_url=="string"&&e.run_notice_url!==""?e.run_notice_url:null}}r(M,"responseGrant");let _;function V(t){return _?_(t):Promise.resolve()}r(V,"requestGrantSync");function Y(t,n=e=>{}){let e;const s=t.replace(/\/$/,""),c=r(async()=>{const a=y(),u=await B(s),l=await fetch(`${s}/v1/runtime/grants`,{headers:{Authorization:`Bearer ${u.access_token}`},signal:AbortSignal.timeout(1e4)});if(!l.ok)throw new Error(`directory grant sync failed: ${l.status}`);const p=await l.json();if(!Array.isArray(p.grants)||typeof p.synced_at!="string")throw new TypeError("invalid grant sync response");const k=$();N(p.grants.map(m=>M(m,a)),p.synced_at,s),f({level:"info",event:"daemon.grants.synced",fields:{grants:p.grants.length,synced_at:p.synced_at}});try{await O(k,n)}catch(m){f({level:"error",event:"daemon.grants.on_sync_failed",error:m})}},"run");let o;const i=r(()=>{const a=c().catch(u=>{throw u instanceof h?f({level:"error",event:"daemon.grants.machine_revoked",error:u}):f({level:"error",event:"daemon.grants.sync_failed",error:u}),u}).finally(()=>{e===a&&(e=void 0)});return e=a,a},"start"),d=r((a={})=>e?a.fresh?(o??=e.catch(()=>{}).then(()=>(o=void 0,e??i())),o):e:i(),"sync");return _=d,d}r(Y,"createGrantSync");export{H as GRANT_SYNC_INTERVAL_S,h as MachineRevokedError,G as assertion,Y as createGrantSync,R as machineRevokedMessage,B as mintDirectoryToken,V as requestGrantSync,y as runtimeClient,K as runtimeId};
1
+ var k=Object.defineProperty;var r=(t,n)=>k(t,"name",{value:n,configurable:!0});import{createPrivateKey as v,randomUUID as E,sign as S}from"node:crypto";import{readFileSync as b}from"node:fs";import{join as j}from"node:path";import{crtrHome as x}from"../canvas/paths.js";import{isUnsandboxedMachine as g}from"../runtime/unsandboxed.js";import{emitEvent as f}from"../events/emit.js";import{allGrants as $,dependenciesOf as T,inferenceEndpointOf as A,replaceGrants as N}from"./mirror.js";import{onGrantSync as O}from"./on-sync.js";const H=300;function G(t,n){const e=Math.floor(Date.now()/1e3),s=Buffer.from(JSON.stringify({alg:"ES256",typ:"JWT",kid:t.kid})).toString("base64url"),c=Buffer.from(JSON.stringify({iss:t.client_id,sub:t.client_id,aud:n,iat:e,exp:e+300,jti:E()})).toString("base64url"),o=`${s}.${c}`,i=S("sha256",Buffer.from(o),{key:v({key:t.jwk,format:"jwk"}),dsaEncoding:"ieee-p1363"});return`${o}.${i.toString("base64url")}`}r(G,"assertion");function y(){const t=JSON.parse(b(j(x(),"secrets","runtime-client.json"),"utf8"));if(!t.jwk||t.alg!=="ES256"||!t.kid||!t.client_id||!t.runtime||t.jwk.kid!==t.kid||t.jwk.kty!=="EC"||t.jwk.crv!=="P-256"||!t.jwk.d)throw new TypeError("invalid runtime client key");return t}r(y,"runtimeClient");function K(t=y()){return t.runtime.startsWith("runtime:")?t.runtime.slice(8):t.runtime}r(K,"runtimeId");function R(t){return`This machine was removed from your Northlight account. To use it again, create a join token at ${t.replace(/\/$/,"")}/account/machines, and run \`crtr sys join\` from a plain terminal.`}r(R,"machineRevokedMessage");class h extends Error{static{r(this,"MachineRevokedError")}constructor(n){super(R(n)),this.name="MachineRevokedError"}}async function B(t,n){const e=y(),s=`${t.replace(/\/$/,"")}/token`,c=new URLSearchParams({grant_type:"client_credentials",client_id:e.client_id,client_assertion_type:"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",client_assertion:G(e,s),...n===void 0?{}:{audience:n}}),o=await fetch(s,{method:"POST",body:c,signal:AbortSignal.timeout(1e4)});if(!o.ok)throw o.status===401&&g()&&await D(o)?new h(t):new Error(`directory token request failed: ${o.status}`);const i=await o.json();if(typeof i.access_token!="string")throw new TypeError("directory token response has no access_token");return{access_token:i.access_token,expires_at:J(i.access_token,i.expires_in)}}r(B,"mintDirectoryToken");async function D(t){try{return(await t.json()).error==="invalid_client"}catch{return!1}}r(D,"isInvalidClient");function J(t,n){if(typeof n=="number"&&Number.isFinite(n)&&n>0)return Date.now()+n*1e3;try{const e=JSON.parse(Buffer.from(t.split(".")[1]??"","base64url").toString("utf8"));if(typeof e.exp=="number")return e.exp*1e3}catch{}return Date.now()+3e5}r(J,"tokenExpiry");function M(t,n){if(!t||typeof t!="object")throw new TypeError("invalid grant sync response");const e=t,s=n.runtime.startsWith("runtime:")?n.runtime:`runtime:${n.runtime}`;if(!(e.runtime===s||g()&&typeof e.runtime=="string"&&e.runtime.startsWith("runtime:")&&e.grantee!=="app:terminal")||typeof e.id!="string"||typeof e.sub!="string"||typeof e.grantee!="string"||!Number.isInteger(e.rev)||!Array.isArray(e.scopes)||!Array.isArray(e.resolved_scopes)||!["active","revoked","removed"].includes(e.status??"")||typeof e.synced_at!="string")throw new TypeError("invalid grant sync response");const i=t.revisions?.find(a=>a.rev===e.rev)?.approved_at;if(typeof i!="string")throw new TypeError("grant revision has no approval time");const d=e.payer==="app"?"app":"user";return{...e,spend_cap:e.spend_cap??null,expires_at:e.expires_at??null,revoked_at:e.revoked_at??null,approved_at:i,payer:d,dependencies:T(e.dependencies),inference_endpoint:d==="app"?A(e.inference_endpoint):null,run_notice_url:typeof e.run_notice_url=="string"&&e.run_notice_url!==""?e.run_notice_url:null}}r(M,"responseGrant");let _;function V(t){return _?_(t):Promise.resolve()}r(V,"requestGrantSync");function Y(t,n=e=>{}){let e;const s=t.replace(/\/$/,""),c=r(async()=>{const a=y(),u=await B(s),l=await fetch(`${s}/v1/runtime/grants`,{headers:{Authorization:`Bearer ${u.access_token}`},signal:AbortSignal.timeout(1e4)});if(!l.ok)throw new Error(`directory grant sync failed: ${l.status}`);const p=await l.json();if(!Array.isArray(p.grants)||typeof p.synced_at!="string")throw new TypeError("invalid grant sync response");const w=await $();await N(p.grants.map(m=>M(m,a)),p.synced_at,s),f({level:"info",event:"daemon.grants.synced",fields:{grants:p.grants.length,synced_at:p.synced_at}});try{await O(w,n)}catch(m){f({level:"error",event:"daemon.grants.on_sync_failed",error:m})}},"run");let o;const i=r(()=>{const a=c().catch(u=>{throw u instanceof h?f({level:"error",event:"daemon.grants.machine_revoked",error:u}):f({level:"error",event:"daemon.grants.sync_failed",error:u}),u}).finally(()=>{e===a&&(e=void 0)});return e=a,a},"start"),d=r((a={})=>e?a.fresh?(o??=e.catch(()=>{}).then(()=>(o=void 0,e??i())),o):e:i(),"sync");return _=d,d}r(Y,"createGrantSync");export{H as GRANT_SYNC_INTERVAL_S,h as MachineRevokedError,G as assertion,Y as createGrantSync,R as machineRevokedMessage,B as mintDirectoryToken,V as requestGrantSync,y as runtimeClient,K as runtimeId};
@@ -1,54 +1,54 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import type { ObjectRow, Reader } from './types.js';
2
+ import type { CanvasDb } from '../canvas/db.js';
3
3
  /** The object's owners, nearest first, ending at its space; empty when the object is a space.
4
4
  * CROSS JOIN pins the chain as the outer loop: left to the planner, it scans every
5
5
  * object and probes the chain, which made each read check cost milliseconds. */
6
- export declare function ownerChain(db: DatabaseSync, object: ObjectRow): ObjectRow[];
7
- export declare function spaceOf(db: DatabaseSync, object: ObjectRow): ObjectRow;
6
+ export declare function ownerChain(db: CanvasDb, object: ObjectRow): Promise<ObjectRow[]>;
7
+ export declare function spaceOf(db: CanvasDb, object: ObjectRow): Promise<ObjectRow>;
8
8
  /** A shipped document: one a package reconciler owns, read from its package file
9
9
  * (`documents.source_path` is set). Only the reconciler writes it. */
10
- export declare function isShipped(db: DatabaseSync, object: ObjectRow): boolean;
10
+ export declare function isShipped(db: CanvasDb, object: ObjectRow): Promise<boolean>;
11
11
  /** The apps whose tools a run may use, `crtr` last. On a local runtime (v0) every
12
12
  * installed, enabled plugin's tools are usable by every run, and an installed
13
13
  * plugin is exactly an app holding live shipped documents. Hosted grants narrow
14
14
  * this per reader later; `mayUseTools` is the one question both ask. */
15
- export declare function toolApps(db: DatabaseSync, reader: Reader): ObjectRow[];
15
+ export declare function toolApps(db: CanvasDb, reader: Reader): Promise<ObjectRow[]>;
16
16
  /** May `reader` use any of `app`'s tool groups? v0: every run may use every installed plugin's tools. */
17
- export declare function mayUseTools(_db: DatabaseSync, _reader: Reader, app: ObjectRow): boolean;
17
+ export declare function mayUseTools(_db: CanvasDb, _reader: Reader, app: ObjectRow): boolean;
18
18
  /** Whether `scopes` hold a provider-group scope `<provider>:<group>` of `app`: what a run needs to call that app's provider commands
19
19
  * (`requireGroup`). The provider id is the app's client id. */
20
- export declare function holdsProviderGroup(db: DatabaseSync, scopes: readonly string[], app: ObjectRow): boolean;
20
+ export declare function holdsProviderGroup(db: CanvasDb, scopes: readonly string[], app: ObjectRow): Promise<boolean>;
21
21
  /** Whether this reader may register, publish or watch as an object owned by `owner`. */
22
- export declare function mayActAs(db: DatabaseSync, reader: Reader, owner: ObjectRow): boolean;
22
+ export declare function mayActAs(db: CanvasDb, reader: Reader, owner: ObjectRow): Promise<boolean>;
23
23
  /** Run confinement for a node acting on a custom object of its app (Silas, 2026-09-30):
24
24
  * a node reaches an object registered in its own run, or when neither run is isolated.
25
25
  * An object the person or the app's server registered is reached by nodes outside
26
26
  * isolation only. Any other reader is unchanged. */
27
- export declare function customReachable(db: DatabaseSync, reader: Reader, object: ObjectRow): boolean;
27
+ export declare function customReachable(db: CanvasDb, reader: Reader, object: ObjectRow): Promise<boolean>;
28
28
  /** The `crtr:objects:*` targets an object belongs to, from its owner chain (rulings R5):
29
29
  * person space → `user`; under an app's profile → `profile:<id>`; a node of an app or a custom
30
30
  * object → `app:<x>`; any node (local, or a stub of one of the account's nodes) → `node`.
31
31
  * App documents and the profile itself stay under the memory scopes; a repo has no target.
32
32
  * The app's own `app:<x>` is left out: its own objects need no scope. */
33
- export declare function objectsTargets(db: DatabaseSync, object: ObjectRow, appGrantee: string): string[];
33
+ export declare function objectsTargets(db: CanvasDb, object: ObjectRow, appGrantee: string): Promise<string[]>;
34
34
  /** Whether a non-person reader's scopes hold `crtr:objects:<verb>:<t>` for a target t of `object`.
35
35
  * False for a person and for a revoked grant (`scopes === null`). `covers` is exact equality here. */
36
- export declare function holdsObjectsScope(db: DatabaseSync, reader: Reader, verb: 'read' | 'watch' | 'link' | 'write', object: ObjectRow): boolean;
36
+ export declare function holdsObjectsScope(db: CanvasDb, reader: Reader, verb: 'read' | 'watch' | 'link' | 'write', object: ObjectRow): Promise<boolean>;
37
37
  /** Whether the watch `watcher` → `object` that `app` made through `link` still authorizes delivering `object`'s events to `watcher` past the
38
38
  * watcher's read gate: `app` owns `object` (directly, or through its profile: `mayActAs`) and, when its `scopes` are known, they hold
39
39
  * `crtr:objects:link:<t>` for the watcher. Null `scopes` (a stub of a remote object: the home already checked the link) skip the scope. It grants
40
40
  * delivery of this one object's events only; nothing about reading it. */
41
- export declare function linkAuthorizes(db: DatabaseSync, app: ObjectRow, scopes: readonly string[] | null, object: ObjectRow, watcher: ObjectRow): boolean;
41
+ export declare function linkAuthorizes(db: CanvasDb, app: ObjectRow, scopes: readonly string[] | null, object: ObjectRow, watcher: ObjectRow): Promise<boolean>;
42
42
  /** Callers turn `false` into `not_found`. A person reader reads everything. An app's
43
43
  * shipped documents are read by any run that may use that app's tools. */
44
- export declare function canRead(db: DatabaseSync, reader: Reader, object: ObjectRow): boolean;
44
+ export declare function canRead(db: CanvasDb, reader: Reader, object: ObjectRow): Promise<boolean>;
45
45
  /** `canRead` for many readers of one object: the owner chain is walked once. */
46
- export declare function readCheck(db: DatabaseSync, object: ObjectRow): (reader: Reader) => boolean;
46
+ export declare function readCheck(db: CanvasDb, object: ObjectRow): Promise<(reader: Reader) => Promise<boolean>>;
47
47
  /** Always asked of the space, also for a person: a repo never owns a non-public
48
48
  * document, whoever asks. A shipped document is changed by nobody, its own app
49
49
  * included — only the package reconciler writes it, and it asks no reader. */
50
- export declare function canChange(db: DatabaseSync, reader: Reader, object: ObjectRow): boolean;
50
+ export declare function canChange(db: CanvasDb, reader: Reader, object: ObjectRow): Promise<boolean>;
51
51
  /** The own-app memory scope a narrowed run lacks for `access` on a document, or null (see `missingOwnMemoryScope`). */
52
- export declare function missingMemoryScope(db: DatabaseSync, reader: Reader, object: ObjectRow, access: 'read' | 'rw'): string | null;
52
+ export declare function missingMemoryScope(db: CanvasDb, reader: Reader, object: ObjectRow, access: 'read' | 'rw'): Promise<string | null>;
53
53
  /** The same for a document about to be created under `owner`. */
54
- export declare function missingMemoryScopeUnder(db: DatabaseSync, reader: Reader, owner: ObjectRow, access: 'read' | 'rw'): string | null;
54
+ export declare function missingMemoryScopeUnder(db: CanvasDb, reader: Reader, owner: ObjectRow, access: 'read' | 'rw'): Promise<string | null>;
@@ -1,8 +1,8 @@
1
- var R=Object.defineProperty;var s=(n,t)=>R(n,"name",{value:t,configurable:!0});import{prepared as f}from"../sqlite-statements.js";import{covers as O}from"@north-light/identity";import{objectPlace as x,runPlace as N,runsSeeEachOther as g}from"../runs/confinement.js";import{missingOwnMemoryScope as E}from"./spaces/own-memory.js";import{SPACES as L,identityOf as u}from"./spaces/index.js";import{insideRepo as C}from"./spaces/repo.js";function T(n,t){return f(n,`WITH RECURSIVE chain(rowid, depth) AS (
1
+ var R=Object.defineProperty;var s=(n,t)=>R(n,"name",{value:t,configurable:!0});import{covers as S}from"@north-light/identity";import{objectPlace as O,runPlace as x,runsSeeEachOther as N}from"../runs/confinement.js";import{missingOwnMemoryScope as h}from"./spaces/own-memory.js";import{SPACES as g,identityOf as l}from"./spaces/index.js";import{insideRepo as L}from"./spaces/repo.js";async function C(n,t){return await n.prepare(`WITH RECURSIVE chain(rowid, depth) AS (
2
2
  SELECT owner, 1 FROM objects WHERE rowid = ? AND owner IS NOT NULL
3
3
  UNION ALL
4
4
  SELECT o.owner, c.depth + 1 FROM objects o JOIN chain c ON o.rowid = c.rowid WHERE o.owner IS NOT NULL
5
- ) SELECT o.* FROM chain c CROSS JOIN objects o WHERE o.rowid = c.rowid ORDER BY c.depth`).all(t.rowid)}s(T,"ownerChain");function J(n,t){return c(n,t).space}s(J,"spaceOf");function c(n,t){const e=T(n,t),p=e.length?e[e.length-1]:t,o=L[p.type];if(!o)throw new Error(`${t.type} ${t.id} has no space: its owner chain ends at ${p.type} ${p.id}`);const r=e.length?[...e.slice(0,-1).reverse(),t]:[];return{space:p,path:r,impl:o}}s(c,"locate");function m(n,t){return t.type!=="document"?!1:f(n,"SELECT source_path FROM documents WHERE object = ?").get(t.rowid)?.source_path!=null}s(m,"isShipped");function B(n,t){return f(n,`SELECT a.* FROM objects a WHERE a.type = 'app' AND a.deleted_at IS NULL AND EXISTS (
5
+ ) SELECT o.* FROM chain c CROSS JOIN objects o WHERE o.rowid = c.rowid ORDER BY c.depth`).all(t.rowid)}s(C,"ownerChain");async function P(n,t){return(await r(n,t)).space}s(P,"spaceOf");async function r(n,t){const a=await C(n,t),i=a.length?a[a.length-1]:t,e=g[i.type];if(!e)throw new Error(`${t.type} ${t.id} has no space: its owner chain ends at ${i.type} ${i.id}`);const o=a.length?[...a.slice(0,-1).reverse(),t]:[];return{space:i,path:o,impl:e}}s(r,"locate");async function y(n,t){return t.type!=="document"?!1:(await n.prepare("SELECT source_path FROM documents WHERE object = ?").get(t.rowid))?.source_path!=null}s(y,"isShipped");async function k(n,t){return(await n.prepare(`SELECT a.* FROM objects a WHERE a.type = 'app' AND a.deleted_at IS NULL AND EXISTS (
6
6
  SELECT 1 FROM objects o JOIN documents d ON d.object = o.rowid
7
7
  WHERE o.owner = a.rowid AND o.type = 'document' AND o.deleted_at IS NULL AND d.source_path IS NOT NULL)
8
- ORDER BY a.name = 'crtr', a.name`).all().filter(p=>h(n,t,p))}s(B,"toolApps");function h(n,t,e){return e.type==="app"}s(h,"mayUseTools");const A=s(n=>n.class!=="app"||n.place!==void 0,"isRun");function I(n,t,e){const p=`${u(n,e).external_id.replace(/^app:/,"")}:`;return t.some(o=>o.startsWith(p)&&!o.slice(p.length).includes(":"))}s(I,"holdsProviderGroup");function _(n,t,e){return t.class==="person"?!0:t.class==="object"?t.owner.rowid===e.rowid:t.class==="app"?t.app.rowid===e.rowid||e.type==="profile"&&e.owner===t.app.rowid:t.app.rowid===e.rowid||e.type==="profile"&&t.profile?.rowid===e.rowid||e.type==="repo"&&C(n,t,e,"rw")}s(_,"mayActAs");function M(n,t,e){if(t.class!=="node"&&!(t.class==="app"&&t.place!==void 0))return!0;const p=t.class==="app"?t.place:N(t.node.id,n);if(p===null)return!0;const o=x(e.rowid,n);return o===null?!p.isolated:g(p,o)}s(M,"customReachable");const w=s(n=>n.type.includes("."),"isCustom");function Y(n,t,e){return d(n,c(n,t),t,e)}s(Y,"objectsTargets");function d(n,{space:t,path:e},p,o){const r=[];if(t.type==="person")r.push("user");else if(t.type==="app"&&e.length>0){const i=e[0];if(i.type==="profile")e.length>1&&r.push(`profile:${u(n,i).external_id}`);else if(i.type==="node"||w(i)){const l=u(n,t).external_id;l!==o&&r.push(l)}}return p.type==="node"&&r.push("node"),r}s(d,"targetsOf");function a(n,t,e,p,o){if(t.class==="person"||t.scopes===null)return!1;const r=t.scopes;if(r.length===0||p.space.type==="app"&&t.app.rowid===p.space.rowid)return!1;const i=u(n,t.app).external_id;return d(n,p,o,i).some(l=>{const y=`crtr:objects:${e}:${l}`;return r.some(S=>O(S,y))})}s(a,"holdsInLocated");function U(n,t,e,p){return t.class==="person"||t.scopes===null?!1:a(n,t,e,c(n,p),p)}s(U,"holdsObjectsScope");function z(n,t,e,p,o){const r=p.owner===null?null:n.prepare("SELECT * FROM objects WHERE rowid = ?").get(p.owner)??null;if(r===null)return!1;const i={class:"app",app:t,scopes:e??[]};return _(n,i,r)?e===null||U(n,i,"link",o):!1}s(z,"linkAuthorizes");function G(n,t,e){return W(n,e)(t)}s(G,"canRead");function W(n,t){let e=null,p=null;return o=>{if(o.class==="person")return!0;if(e??=c(n,t),e.space.type==="app"&&e.path.length>0){if(p??=m(n,t),p&&h(n,o,e.space))return!0;if(w(t)){if(o.app.rowid===e.space.rowid&&!M(n,o,t))return!1;if(o.app.rowid!==e.space.rowid&&o.scopes!==null&&h(n,o,e.space)&&(t.privacy==="public"||A(o)&&I(n,o.scopes,e.space)))return!0}}return a(n,o,"read",e,t)||o.class==="object"&&w(o.object)&&a(n,o,"watch",e,t)?!0:e.impl.canRead(n,o,e.space,e.path,t)}}s(W,"readCheck");function V(n,t,e){if(m(n,e))return!1;const p=c(n,e);if(a(n,t,"write",p,e))return!0;const{space:o,path:r,impl:i}=p;return i.canChange(n,t,o,r,e)}s(V,"canChange");function X(n,t,e,p){if(t.class==="person")return null;const{space:o,path:r}=c(n,e);return o.type==="app"&&t.app.rowid===o.rowid?E(n,t,o,r,e,p):null}s(X,"missingMemoryScope");function q(n,t,e,p){if(t.class==="person")return null;const o=c(n,e),{space:r}=o;return r.type!=="app"||t.app.rowid!==r.rowid?null:E(n,t,r,o.path.length===0?[e]:[...o.path],null,p)}s(q,"missingMemoryScopeUnder");export{V as canChange,G as canRead,M as customReachable,U as holdsObjectsScope,I as holdsProviderGroup,m as isShipped,z as linkAuthorizes,_ as mayActAs,h as mayUseTools,X as missingMemoryScope,q as missingMemoryScopeUnder,Y as objectsTargets,T as ownerChain,W as readCheck,J as spaceOf,B as toolApps};
8
+ ORDER BY a.name = 'crtr', a.name`).all()).filter(i=>f(n,t,i))}s(k,"toolApps");function f(n,t,a){return a.type==="app"}s(f,"mayUseTools");const T=s(n=>n.class!=="app"||n.place!==void 0,"isRun");async function A(n,t,a){const i=`${(await l(n,a)).external_id.replace(/^app:/,"")}:`;return t.some(e=>e.startsWith(i)&&!e.slice(i.length).includes(":"))}s(A,"holdsProviderGroup");async function I(n,t,a){return t.class==="person"?!0:t.class==="object"?t.owner.rowid===a.rowid:t.class==="app"?t.app.rowid===a.rowid||a.type==="profile"&&a.owner===t.app.rowid:t.app.rowid===a.rowid||a.type==="profile"&&t.profile?.rowid===a.rowid||a.type==="repo"&&await L(n,t,a,"rw")}s(I,"mayActAs");async function _(n,t,a){if(t.class!=="node"&&!(t.class==="app"&&t.place!==void 0))return!0;const i=t.class==="app"?t.place:await x(t.node.id,n);if(i===null)return!0;const e=await O(a.rowid,n);return e===null?!i.isolated:N(i,e)}s(_,"customReachable");const w=s(n=>n.type.includes("."),"isCustom");async function J(n,t,a){return await E(n,await r(n,t),t,a)}s(J,"objectsTargets");async function E(n,{space:t,path:a},i,e){const o=[];if(t.type==="person")o.push("user");else if(t.type==="app"&&a.length>0){const p=a[0];if(p.type==="profile")a.length>1&&o.push(`profile:${(await l(n,p)).external_id}`);else if(p.type==="node"||w(p)){const c=(await l(n,t)).external_id;c!==e&&o.push(c)}}return i.type==="node"&&o.push("node"),o}s(E,"targetsOf");async function u(n,t,a,i,e){if(t.class==="person"||t.scopes===null)return!1;const o=t.scopes;if(o.length===0||i.space.type==="app"&&t.app.rowid===i.space.rowid)return!1;const p=(await l(n,t.app)).external_id;return(await E(n,i,e,p)).some(c=>{const m=`crtr:objects:${a}:${c}`;return o.some(d=>S(d,m))})}s(u,"holdsInLocated");async function M(n,t,a,i){return t.class==="person"||t.scopes===null?!1:await u(n,t,a,await r(n,i),i)}s(M,"holdsObjectsScope");async function B(n,t,a,i,e){const o=i.owner===null?null:await n.prepareUncached("SELECT * FROM objects WHERE rowid = ?").get(i.owner)??null;if(o===null)return!1;const p={class:"app",app:t,scopes:a??[]};return await I(n,p,o)?a===null||await M(n,p,"link",e):!1}s(B,"linkAuthorizes");async function Y(n,t,a){return(await U(n,a))(t)}s(Y,"canRead");async function U(n,t){let a=null,i=null;return async e=>{if(e.class==="person")return!0;if(a??=await r(n,t),a.space.type==="app"&&a.path.length>0){if(i??=await y(n,t),i&&f(n,e,a.space))return!0;if(w(t)){if(e.app.rowid===a.space.rowid&&!await _(n,e,t))return!1;if(e.app.rowid!==a.space.rowid&&e.scopes!==null&&f(n,e,a.space)&&(t.privacy==="public"||T(e)&&await A(n,e.scopes,a.space)))return!0}}return await u(n,e,"read",a,t)||e.class==="object"&&w(e.object)&&await u(n,e,"watch",a,t)?!0:await a.impl.canRead(n,e,a.space,a.path,t)}}s(U,"readCheck");async function z(n,t,a){if(await y(n,a))return!1;const i=await r(n,a);if(await u(n,t,"write",i,a))return!0;const{space:e,path:o,impl:p}=i;return await p.canChange(n,t,e,o,a)}s(z,"canChange");async function G(n,t,a,i){if(t.class==="person")return null;const{space:e,path:o}=await r(n,a);return e.type==="app"&&t.app.rowid===e.rowid?await h(n,t,e,o,a,i):null}s(G,"missingMemoryScope");async function V(n,t,a,i){if(t.class==="person")return null;const e=await r(n,a),{space:o}=e;return o.type!=="app"||t.app.rowid!==o.rowid?null:await h(n,t,o,e.path.length===0?[a]:[...e.path],null,i)}s(V,"missingMemoryScopeUnder");export{z as canChange,Y as canRead,_ as customReachable,M as holdsObjectsScope,A as holdsProviderGroup,y as isShipped,B as linkAuthorizes,I as mayActAs,f as mayUseTools,G as missingMemoryScope,V as missingMemoryScopeUnder,J as objectsTargets,C as ownerChain,U as readCheck,P as spaceOf,k as toolApps};
@@ -1,7 +1,7 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import type { Level, ObjectRow, Privacy, Reader } from './types.js';
3
2
  import { customReachable, mayActAs } from './access.js';
4
3
  import { onQueueSignal } from './receivers.js';
4
+ import type { CanvasDb } from '../canvas/db.js';
5
5
  export { customReachable, mayActAs, onQueueSignal };
6
6
  export type CustomReceiver = 'queue' | {
7
7
  url: string;
@@ -35,7 +35,7 @@ export interface QueueLine {
35
35
  created_at: string;
36
36
  }
37
37
  /** Register a kind and a named instance in the caller's write transaction. */
38
- export declare function registerCustomObject(db: DatabaseSync, reader: Reader, input: {
38
+ export declare function registerCustomObject(db: CanvasDb, reader: Reader, input: {
39
39
  kind: string;
40
40
  name: string;
41
41
  owner: ObjectRow;
@@ -45,12 +45,12 @@ export declare function registerCustomObject(db: DatabaseSync, reader: Reader, i
45
45
  receiver?: CustomReceiver | null;
46
46
  rotateToken?: boolean;
47
47
  privacy?: Privacy;
48
- }): {
48
+ }): Promise<{
49
49
  object: ObjectRow;
50
50
  token?: string;
51
51
  created: boolean;
52
52
  changed: string[];
53
- };
53
+ }>;
54
54
  export type KindSource = 'register' | 'manifest' | 'peer';
55
55
  export type KindChange = 'events' | 'description' | 'read';
56
56
  /**
@@ -61,7 +61,7 @@ export type KindChange = 'events' | 'description' | 'read';
61
61
  * `manifest` or `register` row is `kind_owned`. `read_json` is written only by `manifest`. A catalog is replaced,
62
62
  * never merged. Runs in the caller's write transaction.
63
63
  */
64
- export declare function upsertKind(db: DatabaseSync, input: {
64
+ export declare function upsertKind(db: CanvasDb, input: {
65
65
  name: string;
66
66
  owner: ObjectRow;
67
67
  description: string;
@@ -70,26 +70,26 @@ export declare function upsertKind(db: DatabaseSync, input: {
70
70
  command: string[];
71
71
  } | null;
72
72
  source: KindSource;
73
- }): {
73
+ }): Promise<{
74
74
  outcome: 'inserted' | 'updated' | 'unchanged' | 'skipped';
75
75
  changed: KindChange[];
76
- };
77
- export declare function publishCustom(db: DatabaseSync, object: ObjectRow, actor: ObjectRow | null, input: {
76
+ }>;
77
+ export declare function publishCustom(db: CanvasDb, object: ObjectRow, actor: ObjectRow | null, input: {
78
78
  event: string;
79
79
  summary: string;
80
80
  state?: unknown;
81
81
  cause?: string;
82
- }): {
82
+ }): Promise<{
83
83
  message_id: string | null;
84
84
  delivered: number;
85
85
  depth: number;
86
- };
87
- export declare function unregisterCustomObject(db: DatabaseSync, object: ObjectRow, actor: ObjectRow | null): void;
88
- export declare function pendingFor(db: DatabaseSync, object: ObjectRow, afterSeq?: number): QueueLine[];
86
+ }>;
87
+ export declare function unregisterCustomObject(db: CanvasDb, object: ObjectRow, actor: ObjectRow | null): Promise<void>;
88
+ export declare function pendingFor(db: CanvasDb, object: ObjectRow, afterSeq?: number): Promise<QueueLine[]>;
89
89
  /** A claimed push delivery has the identical document as a pending queue delivery. */
90
- export declare function pushLineFor(db: DatabaseSync, deliveryId: string): QueueLine | null;
91
- export declare function acknowledge(db: DatabaseSync, object: ObjectRow, deliveryIds: string[]): {
90
+ export declare function pushLineFor(db: CanvasDb, deliveryId: string): Promise<QueueLine | null>;
91
+ export declare function acknowledge(db: CanvasDb, object: ObjectRow, deliveryIds: string[]): Promise<{
92
92
  acknowledged: number;
93
93
  unknown?: string[];
94
- };
95
- export declare function verifyPublishToken(db: DatabaseSync, object: ObjectRow, token: string): boolean;
94
+ }>;
95
+ export declare function verifyPublishToken(db: CanvasDb, object: ObjectRow, token: string): Promise<boolean>;