@anchrd/intel 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (364) hide show
  1. package/README.md +496 -0
  2. package/bin/intel.mjs +134 -0
  3. package/dist/adapters/cloudflare/cloudflare-flow-workflow.d.ts +42 -0
  4. package/dist/adapters/cloudflare/cloudflare-flow-workflow.js +89 -0
  5. package/dist/adapters/cloudflare/cloudflare.d.ts +29 -0
  6. package/dist/adapters/cloudflare/cloudflare.js +416 -0
  7. package/dist/adapters/cloudflare/cloudflare.types.d.ts +31 -0
  8. package/dist/adapters/cloudflare/cloudflare.types.js +1 -0
  9. package/dist/adapters/content/content.d.ts +3 -0
  10. package/dist/adapters/content/content.js +128 -0
  11. package/dist/adapters/content/content.types.d.ts +38 -0
  12. package/dist/adapters/content/content.types.js +1 -0
  13. package/dist/adapters/db/db-audit.d.ts +62 -0
  14. package/dist/adapters/db/db-audit.js +150 -0
  15. package/dist/adapters/db/db-boards.d.ts +6 -0
  16. package/dist/adapters/db/db-boards.js +324 -0
  17. package/dist/adapters/db/db-feed.d.ts +30 -0
  18. package/dist/adapters/db/db-feed.js +276 -0
  19. package/dist/adapters/db/db-flows.d.ts +42 -0
  20. package/dist/adapters/db/db-flows.js +1311 -0
  21. package/dist/adapters/db/db-grants.d.ts +133 -0
  22. package/dist/adapters/db/db-grants.js +269 -0
  23. package/dist/adapters/db/db-indexing.d.ts +3 -0
  24. package/dist/adapters/db/db-indexing.js +200 -0
  25. package/dist/adapters/db/db-oauth.d.ts +3 -0
  26. package/dist/adapters/db/db-oauth.js +26 -0
  27. package/dist/adapters/db/db-prompts.d.ts +46 -0
  28. package/dist/adapters/db/db-prompts.js +144 -0
  29. package/dist/adapters/db/db.d.ts +6 -0
  30. package/dist/adapters/db/db.js +1687 -0
  31. package/dist/adapters/db/db.types.d.ts +16 -0
  32. package/dist/adapters/db/db.types.js +1 -0
  33. package/dist/adapters/document-converter/document-converter.d.ts +2 -0
  34. package/dist/adapters/document-converter/document-converter.js +26 -0
  35. package/dist/adapters/document-converter/document-converter.types.d.ts +17 -0
  36. package/dist/adapters/document-converter/document-converter.types.js +1 -0
  37. package/dist/adapters/flow-runtime/flow-runtime.d.ts +3 -0
  38. package/dist/adapters/flow-runtime/flow-runtime.js +22 -0
  39. package/dist/adapters/flow-runtime/flow-runtime.types.d.ts +19 -0
  40. package/dist/adapters/flow-runtime/flow-runtime.types.js +1 -0
  41. package/dist/adapters/index-queue/index-queue.d.ts +10 -0
  42. package/dist/adapters/index-queue/index-queue.js +12 -0
  43. package/dist/adapters/index-queue/index-queue.types.d.ts +11 -0
  44. package/dist/adapters/index-queue/index-queue.types.js +1 -0
  45. package/dist/adapters/json-schema/json-schema.d.ts +2 -0
  46. package/dist/adapters/json-schema/json-schema.js +77 -0
  47. package/dist/adapters/openid/openid.d.ts +5 -0
  48. package/dist/adapters/openid/openid.js +301 -0
  49. package/dist/adapters/portal-tokens/portal-tokens.d.ts +8 -0
  50. package/dist/adapters/portal-tokens/portal-tokens.js +79 -0
  51. package/dist/adapters/remote-tools/remote-tools.d.ts +5 -0
  52. package/dist/adapters/remote-tools/remote-tools.js +129 -0
  53. package/dist/adapters/semantic-index/semantic-index.d.ts +2 -0
  54. package/dist/adapters/semantic-index/semantic-index.js +139 -0
  55. package/dist/adapters/semantic-index/semantic-index.types.d.ts +56 -0
  56. package/dist/adapters/semantic-index/semantic-index.types.js +1 -0
  57. package/dist/adapters/session-cookie/session-cookie.d.ts +5 -0
  58. package/dist/adapters/session-cookie/session-cookie.js +87 -0
  59. package/dist/adapters/tool-source-policy/tool-source-policy.d.ts +1 -0
  60. package/dist/adapters/tool-source-policy/tool-source-policy.js +22 -0
  61. package/dist/audit/audit.d.ts +2 -0
  62. package/dist/audit/audit.js +87 -0
  63. package/dist/audit/audit.types.d.ts +23 -0
  64. package/dist/audit/audit.types.js +1 -0
  65. package/dist/auth/auth.d.ts +2 -0
  66. package/dist/auth/auth.js +284 -0
  67. package/dist/auth/auth.types.d.ts +108 -0
  68. package/dist/auth/auth.types.js +1 -0
  69. package/dist/boards/boards.d.ts +44 -0
  70. package/dist/boards/boards.js +447 -0
  71. package/dist/boards/boards.types.d.ts +117 -0
  72. package/dist/boards/boards.types.js +1 -0
  73. package/dist/build/build.d.ts +2 -0
  74. package/dist/build/build.js +192 -0
  75. package/dist/build/build.types.d.ts +17 -0
  76. package/dist/build/build.types.js +1 -0
  77. package/dist/bundle/bundle.d.ts +4 -0
  78. package/dist/bundle/bundle.js +1194 -0
  79. package/dist/bundle/bundle.types.d.ts +33 -0
  80. package/dist/bundle/bundle.types.js +1 -0
  81. package/dist/cli/cli.d.ts +4 -0
  82. package/dist/cli/cli.js +262 -0
  83. package/dist/cli/cli.types.d.ts +14 -0
  84. package/dist/cli/cli.types.js +1 -0
  85. package/dist/contract/audit.d.ts +50 -0
  86. package/dist/contract/audit.js +72 -0
  87. package/dist/contract/board.d.ts +150 -0
  88. package/dist/contract/board.js +262 -0
  89. package/dist/contract/bundle.d.ts +147 -0
  90. package/dist/contract/bundle.js +139 -0
  91. package/dist/contract/contract.d.ts +112 -0
  92. package/dist/contract/contract.js +143 -0
  93. package/dist/contract/feed.d.ts +126 -0
  94. package/dist/contract/feed.js +149 -0
  95. package/dist/contract/flow-run.d.ts +346 -0
  96. package/dist/contract/flow-run.js +194 -0
  97. package/dist/contract/flow.d.ts +1057 -0
  98. package/dist/contract/flow.js +552 -0
  99. package/dist/contract/node.d.ts +551 -0
  100. package/dist/contract/node.js +456 -0
  101. package/dist/contract/share.d.ts +216 -0
  102. package/dist/contract/share.js +134 -0
  103. package/dist/contract/table.d.ts +171 -0
  104. package/dist/contract/table.js +117 -0
  105. package/dist/contract/tool.d.ts +122 -0
  106. package/dist/contract/tool.js +172 -0
  107. package/dist/feed/feed.d.ts +2 -0
  108. package/dist/feed/feed.js +77 -0
  109. package/dist/feed/feed.types.d.ts +23 -0
  110. package/dist/feed/feed.types.js +1 -0
  111. package/dist/flows/flows.d.ts +41 -0
  112. package/dist/flows/flows.js +2216 -0
  113. package/dist/flows/flows.types.d.ts +339 -0
  114. package/dist/flows/flows.types.js +1 -0
  115. package/dist/http/http.d.ts +9 -0
  116. package/dist/http/http.js +874 -0
  117. package/dist/http/http.types.d.ts +22 -0
  118. package/dist/http/http.types.js +1 -0
  119. package/dist/indexing/indexing.d.ts +6 -0
  120. package/dist/indexing/indexing.js +239 -0
  121. package/dist/indexing/indexing.types.d.ts +11 -0
  122. package/dist/indexing/indexing.types.js +1 -0
  123. package/dist/intel/intel.d.ts +3 -0
  124. package/dist/intel/intel.js +194 -0
  125. package/dist/intel/intel.types.d.ts +24 -0
  126. package/dist/intel/intel.types.js +1 -0
  127. package/dist/mcp/mcp.d.ts +2 -0
  128. package/dist/mcp/mcp.js +1292 -0
  129. package/dist/mcp/mcp.types.d.ts +25 -0
  130. package/dist/mcp/mcp.types.js +1 -0
  131. package/dist/nodes/document-links/document-links.d.ts +20 -0
  132. package/dist/nodes/document-links/document-links.js +57 -0
  133. package/dist/nodes/nodes.d.ts +2 -0
  134. package/dist/nodes/nodes.js +1667 -0
  135. package/dist/nodes/nodes.types.d.ts +511 -0
  136. package/dist/nodes/nodes.types.js +1 -0
  137. package/dist/prepare/prepare.d.ts +4 -0
  138. package/dist/prepare/prepare.js +16 -0
  139. package/dist/prepare/prepare.types.d.ts +9 -0
  140. package/dist/prepare/prepare.types.js +1 -0
  141. package/dist/prompts/prompts.d.ts +2 -0
  142. package/dist/prompts/prompts.js +65 -0
  143. package/dist/prompts/prompts.types.d.ts +71 -0
  144. package/dist/prompts/prompts.types.js +1 -0
  145. package/dist/shared/callers/callers.d.ts +28 -0
  146. package/dist/shared/callers/callers.js +30 -0
  147. package/dist/shared/csv/csv.d.ts +13 -0
  148. package/dist/shared/csv/csv.js +85 -0
  149. package/dist/shared/document-text/document-text.d.ts +21 -0
  150. package/dist/shared/document-text/document-text.js +31 -0
  151. package/dist/shared/gate-authorization/gate-authorization.d.ts +5 -0
  152. package/dist/shared/gate-authorization/gate-authorization.js +26 -0
  153. package/dist/shared/grant-expiry/grant-expiry.d.ts +19 -0
  154. package/dist/shared/grant-expiry/grant-expiry.js +26 -0
  155. package/dist/shared/intel-error/intel-error.d.ts +22 -0
  156. package/dist/shared/intel-error/intel-error.js +27 -0
  157. package/dist/shared/plain-title/plain-title.d.ts +16 -0
  158. package/dist/shared/plain-title/plain-title.js +45 -0
  159. package/dist/shared/problem-details/problem-details.d.ts +30 -0
  160. package/dist/shared/problem-details/problem-details.js +18 -0
  161. package/dist/shared/report-unexpected-error/report-unexpected-error.d.ts +1 -0
  162. package/dist/shared/report-unexpected-error/report-unexpected-error.js +37 -0
  163. package/dist/shared/safe-return-path/safe-return-path.d.ts +2 -0
  164. package/dist/shared/safe-return-path/safe-return-path.js +11 -0
  165. package/dist/shared/sha256/sha256.d.ts +2 -0
  166. package/dist/shared/sha256/sha256.js +14 -0
  167. package/dist/tools/tool-servers/tool-servers.d.ts +46 -0
  168. package/dist/tools/tool-servers/tool-servers.js +177 -0
  169. package/dist/tools/tools.d.ts +2 -0
  170. package/dist/tools/tools.js +207 -0
  171. package/dist/tools/tools.types.d.ts +56 -0
  172. package/dist/tools/tools.types.js +1 -0
  173. package/examples/branding/favicon.svg +5 -0
  174. package/examples/branding/logo.svg +5 -0
  175. package/examples/branding/theme.css +16 -0
  176. package/examples/dev.vars.example +7 -0
  177. package/examples/intel.json +9 -0
  178. package/migrations/0000_intel_foundation.sql +203 -0
  179. package/migrations/0001_portal_native_tools.sql +21 -0
  180. package/migrations/0002_flows_in_the_knowledge_tree.sql +34 -0
  181. package/migrations/0003_folder_permissions.sql +211 -0
  182. package/migrations/0004_subflow_runs.sql +14 -0
  183. package/migrations/0005_flow_node_cleanup.sql +28 -0
  184. package/migrations/0005_tables_in_the_knowledge_tree.sql +68 -0
  185. package/migrations/0006_links_are_written_in_the_text.sql +20 -0
  186. package/migrations/0007_no_node_waits.sql +69 -0
  187. package/migrations/0008_three_layers.sql +130 -0
  188. package/migrations/0009_no_context_policy.sql +48 -0
  189. package/migrations/0010_no_run_waits_a_year.sql +27 -0
  190. package/migrations/0011_one_name_for_the_tree.sql +53 -0
  191. package/migrations/0012_table_snapshots.sql +29 -0
  192. package/migrations/0017_a_vector_per_card.sql +38 -0
  193. package/migrations/0018_no_context_policy_at_last.sql +97 -0
  194. package/migrations/0019_one_name_for_the_grants.sql +52 -0
  195. package/migrations/0020_cascade_purge_replay.sql +11 -0
  196. package/migrations/0021_a_flow_carries_its_own_grant.sql +44 -0
  197. package/migrations/0022_a_cursor_over_the_journal.sql +14 -0
  198. package/migrations/0023_a_board_and_its_tasks.sql +116 -0
  199. package/migrations/0024_the_archive_is_a_column.sql +33 -0
  200. package/migrations/0025_archiving_takes_the_subtree.sql +29 -0
  201. package/migrations/0026_one_feed_over_two_kinds.sql +23 -0
  202. package/migrations/0027_the_runs_of_every_flow.sql +27 -0
  203. package/migrations/0028_a_prompt_name_over_two_kinds.sql +70 -0
  204. package/package.json +118 -0
  205. package/src/contract/CLAUDE.md +152 -0
  206. package/src/contract/README.md +102 -0
  207. package/src/contract/audit.ts +85 -0
  208. package/src/contract/board.ts +306 -0
  209. package/src/contract/bundle.ts +157 -0
  210. package/src/contract/contract.ts +161 -0
  211. package/src/contract/feed.ts +165 -0
  212. package/src/contract/flow-run.ts +241 -0
  213. package/src/contract/flow.ts +675 -0
  214. package/src/contract/node.ts +583 -0
  215. package/src/contract/share.ts +196 -0
  216. package/src/contract/table.ts +178 -0
  217. package/src/contract/tool.ts +202 -0
  218. package/ui/README.md +110 -0
  219. package/ui/components.json +21 -0
  220. package/ui/index.html +13 -0
  221. package/ui/package.json +11 -0
  222. package/ui/scripts/lint-tokens.mjs +187 -0
  223. package/ui/src/access-summary/access-summary.tsx +385 -0
  224. package/ui/src/app/action-slot/action-slot.tsx +27 -0
  225. package/ui/src/app/app-sidebar/app-sidebar.tsx +71 -0
  226. package/ui/src/app/app-tree/app-tree.tsx +1175 -0
  227. package/ui/src/app/app.tsx +87 -0
  228. package/ui/src/app/header-search/header-search.tsx +294 -0
  229. package/ui/src/app/reindex-dialog/reindex-dialog.tsx +79 -0
  230. package/ui/src/app/settings-dialog/settings-dialog.tsx +135 -0
  231. package/ui/src/app/sidebar-preferences/sidebar-preferences.ts +68 -0
  232. package/ui/src/app/sidebar-preferences/sidebar-preferences.types.ts +15 -0
  233. package/ui/src/app/sidebar-resize-handle/sidebar-resize-handle.tsx +86 -0
  234. package/ui/src/app/tree-expansion/tree-expansion.ts +107 -0
  235. package/ui/src/app/tree-expansion/tree-expansion.types.ts +31 -0
  236. package/ui/src/app/tree-move/tree-move.tsx +427 -0
  237. package/ui/src/app/tree-reveal/tree-reveal.ts +64 -0
  238. package/ui/src/app/tree-reveal/tree-reveal.types.ts +16 -0
  239. package/ui/src/app/user-footer/user-footer.tsx +188 -0
  240. package/ui/src/app/view-menu/view-menu.tsx +115 -0
  241. package/ui/src/app-root/app-root.tsx +109 -0
  242. package/ui/src/app-root/app-root.types.ts +27 -0
  243. package/ui/src/archive/archive.tsx +417 -0
  244. package/ui/src/attachment-detail/attachment-detail.ts +52 -0
  245. package/ui/src/attachment-viewer/attachment-viewer.tsx +166 -0
  246. package/ui/src/blocknote-view/blocknote-view.tsx +30 -0
  247. package/ui/src/board/board-assignee/board-assignee-picker.tsx +132 -0
  248. package/ui/src/board/board-assignee/board-assignee.ts +48 -0
  249. package/ui/src/board/board-assignee/board-assignee.tsx +75 -0
  250. package/ui/src/board/board-chip/board-chip.tsx +46 -0
  251. package/ui/src/board/board-crumbs/board-crumbs.ts +56 -0
  252. package/ui/src/board/board-crumbs/board-crumbs.tsx +111 -0
  253. package/ui/src/board/board-data/board-data.ts +195 -0
  254. package/ui/src/board/board-data/board-data.types.ts +38 -0
  255. package/ui/src/board/board-dates/board-dates.ts +40 -0
  256. package/ui/src/board/board-dates/board-dates.tsx +105 -0
  257. package/ui/src/board/board-kanban/board-kanban.ts +162 -0
  258. package/ui/src/board/board-kanban/board-kanban.tsx +680 -0
  259. package/ui/src/board/board-open-task/board-open-task.ts +32 -0
  260. package/ui/src/board/board-panel/board-panel.tsx +259 -0
  261. package/ui/src/board/board-settings/board-settings.tsx +226 -0
  262. package/ui/src/board/board-status/board-status.tsx +60 -0
  263. package/ui/src/board/board-stripes/board-stripes.ts +128 -0
  264. package/ui/src/board/board-table/board-table.ts +53 -0
  265. package/ui/src/board/board-table/board-table.tsx +610 -0
  266. package/ui/src/board/board-task/board-task.ts +108 -0
  267. package/ui/src/board/board-task/board-task.tsx +335 -0
  268. package/ui/src/board/board-title-row/board-title-row.tsx +66 -0
  269. package/ui/src/branding/branding.tsx +17 -0
  270. package/ui/src/branding/custom-logo.ts +1 -0
  271. package/ui/src/branding/favicon.default.svg +5 -0
  272. package/ui/src/branding/favicon.svg +5 -0
  273. package/ui/src/components/ui/avatar.tsx +39 -0
  274. package/ui/src/components/ui/button.tsx +64 -0
  275. package/ui/src/components/ui/collapsible.tsx +20 -0
  276. package/ui/src/components/ui/command.tsx +160 -0
  277. package/ui/src/components/ui/dialog.tsx +143 -0
  278. package/ui/src/components/ui/dropdown-menu.tsx +187 -0
  279. package/ui/src/components/ui/input.tsx +21 -0
  280. package/ui/src/components/ui/popover.tsx +41 -0
  281. package/ui/src/components/ui/select.tsx +163 -0
  282. package/ui/src/components/ui/separator.tsx +26 -0
  283. package/ui/src/components/ui/sheet.tsx +136 -0
  284. package/ui/src/components/ui/sidebar.tsx +693 -0
  285. package/ui/src/components/ui/skeleton.tsx +13 -0
  286. package/ui/src/components/ui/switch.tsx +25 -0
  287. package/ui/src/components/ui/table.tsx +82 -0
  288. package/ui/src/components/ui/tabs.tsx +52 -0
  289. package/ui/src/components/ui/tooltip.tsx +51 -0
  290. package/ui/src/data/intel-data-provider/intel-data-provider.ts +685 -0
  291. package/ui/src/data/intel-data-provider/intel-data-provider.types.ts +266 -0
  292. package/ui/src/data/query-client.ts +18 -0
  293. package/ui/src/data/request-refusal/refusal-notice.tsx +36 -0
  294. package/ui/src/data/request-refusal/request-refusal.ts +51 -0
  295. package/ui/src/data/sign-in/sign-in.ts +97 -0
  296. package/ui/src/data/sign-in/sign-in.types.ts +15 -0
  297. package/ui/src/document-link/document-link.tsx +114 -0
  298. package/ui/src/document-markdown/document-markdown.ts +195 -0
  299. package/ui/src/editor-schema/editor-schema.ts +23 -0
  300. package/ui/src/entry-picker/entry-picker.tsx +238 -0
  301. package/ui/src/feed/feed.tsx +344 -0
  302. package/ui/src/file-preview/file-preview-view.tsx +496 -0
  303. package/ui/src/file-preview/file-preview.tsx +28 -0
  304. package/ui/src/file-preview/pdf-file-preview.tsx +5 -0
  305. package/ui/src/file-preview/presentation-file-preview.tsx +21 -0
  306. package/ui/src/file-preview/spreadsheet-file-preview.tsx +5 -0
  307. package/ui/src/file-preview/word-file-preview.tsx +5 -0
  308. package/ui/src/flow-runs/flow-runs.tsx +238 -0
  309. package/ui/src/flows/flows.tsx +1646 -0
  310. package/ui/src/flows/node-icon/node-icon.ts +34 -0
  311. package/ui/src/flows/node-palette/node-palette.tsx +214 -0
  312. package/ui/src/flows/node-palette/node-palette.types.ts +15 -0
  313. package/ui/src/folder-contents/folder-contents.tsx +321 -0
  314. package/ui/src/folder-index/folder-index.ts +55 -0
  315. package/ui/src/frontmatter/frontmatter.tsx +193 -0
  316. package/ui/src/graph-pane/graph-pane.tsx +53 -0
  317. package/ui/src/hooks/use-mobile.ts +19 -0
  318. package/ui/src/i18n/custom.json +4 -0
  319. package/ui/src/i18n/de.json +609 -0
  320. package/ui/src/i18n/en.json +609 -0
  321. package/ui/src/i18n/es.json +609 -0
  322. package/ui/src/i18n/i18n-context.tsx +65 -0
  323. package/ui/src/i18n/i18n-languages/i18n-languages.ts +83 -0
  324. package/ui/src/i18n/i18n.ts +32 -0
  325. package/ui/src/i18n/i18n.types.ts +49 -0
  326. package/ui/src/kind-icon.ts +97 -0
  327. package/ui/src/lib/utils.ts +6 -0
  328. package/ui/src/main.tsx +68 -0
  329. package/ui/src/modal/modal.tsx +53 -0
  330. package/ui/src/node-details/node-details.tsx +545 -0
  331. package/ui/src/node-editor/node-editor.tsx +304 -0
  332. package/ui/src/node-graph/graph-notice.tsx +21 -0
  333. package/ui/src/node-graph/node-graph.ts +214 -0
  334. package/ui/src/node-graph/node-graph.tsx +295 -0
  335. package/ui/src/node-import/node-import.tsx +418 -0
  336. package/ui/src/node-save-error.ts +46 -0
  337. package/ui/src/node-source/node-source.tsx +128 -0
  338. package/ui/src/node-table/node-table.tsx +107 -0
  339. package/ui/src/nodes/nodes.tsx +240 -0
  340. package/ui/src/rename-resource/rename-resource.ts +80 -0
  341. package/ui/src/resolved-names/resolved-names.tsx +67 -0
  342. package/ui/src/resource-error.ts +33 -0
  343. package/ui/src/resource-menu/resource-menu.tsx +1156 -0
  344. package/ui/src/router/router-context.ts +6 -0
  345. package/ui/src/router/router.tsx +67 -0
  346. package/ui/src/router/router.types.ts +8 -0
  347. package/ui/src/router/selection-search.ts +88 -0
  348. package/ui/src/save-button/save-button.tsx +94 -0
  349. package/ui/src/section-hint/section-hint.tsx +40 -0
  350. package/ui/src/sign-in-refused/sign-in-refused.tsx +35 -0
  351. package/ui/src/styles.css +189 -0
  352. package/ui/src/table-columns/table-columns.tsx +379 -0
  353. package/ui/src/theme/custom.css +1 -0
  354. package/ui/src/theme/theme-context.tsx +89 -0
  355. package/ui/src/theme/theme.ts +70 -0
  356. package/ui/src/time/relative-time.tsx +41 -0
  357. package/ui/src/time/time-context.tsx +78 -0
  358. package/ui/src/time/time.ts +165 -0
  359. package/ui/src/title-row/title-row.tsx +185 -0
  360. package/ui/src/tools/tools.tsx +546 -0
  361. package/ui/src/user-name/user-name.ts +61 -0
  362. package/ui/src/verbatim/verbatim.tsx +68 -0
  363. package/ui/tsconfig.json +17 -0
  364. package/ui/vite.config.ts +129 -0
@@ -0,0 +1,128 @@
1
+ import { IntelError } from "../../shared/intel-error/intel-error.js";
2
+ import { reportUnexpectedError } from "../../shared/report-unexpected-error/report-unexpected-error.js";
3
+ import { hexDigest } from "../../shared/sha256/sha256.js";
4
+ // ⚠️ Both are workerd globals rather than imports, and they are read through a guard because a
5
+ // missing one is a deployment fact, not a bug in the caller: without them this adapter can still
6
+ // serve every other method, and the one that needs them says so instead of throwing a `TypeError`
7
+ // out of a stream nobody is watching.
8
+ function streaming() {
9
+ const fixedLength = globalThis
10
+ .FixedLengthStream;
11
+ const digestStream = crypto
12
+ .DigestStream;
13
+ if (!fixedLength || !digestStream) {
14
+ throw new IntelError(500, "streaming_unavailable", "This runtime cannot store a file without holding it in memory");
15
+ }
16
+ return { fixedLength, digestStream };
17
+ }
18
+ // The two halves of one pass over the bytes, named so that the promise of each can be held and
19
+ // answered separately from the other.
20
+ function hashed(content, hashing) {
21
+ return content.pipeTo(hashing.writable);
22
+ }
23
+ function written(hashing, body) {
24
+ return hashing.readable.pipeTo(body.writable);
25
+ }
26
+ export function createContentStore(bucket) {
27
+ return {
28
+ async get(key) {
29
+ return (await (await bucket.get(key))?.text()) ?? null;
30
+ },
31
+ async getBytes(key) {
32
+ return (await (await bucket.get(key))?.arrayBuffer()) ?? null;
33
+ },
34
+ async getStream(key) {
35
+ return (await bucket.get(key))?.body ?? null;
36
+ },
37
+ async put(key, content, mediaType) {
38
+ await bucket.put(key, content, { httpMetadata: { contentType: mediaType } });
39
+ },
40
+ async putBytes(key, content, mediaType) {
41
+ await bucket.put(key, content, { httpMetadata: { contentType: mediaType } });
42
+ },
43
+ /**
44
+ * The file into R2 and the hash out of it, in one pass over the bytes (#821).
45
+ *
46
+ * ⚠️ The `put` is started BEFORE the pipe is awaited, and the order is the whole of it: R2 pulls
47
+ * from `readable` while this writes into `writable`. Awaiting the write first would fill a
48
+ * stream nobody reads, and a 50 MB body would sit in memory — which is the state this method
49
+ * exists to prevent.
50
+ *
51
+ * ⚠️ Every chunk goes to the digest before it is passed on, so the hash covers exactly the bytes
52
+ * that were stored. Hashing a copy taken anywhere else would be a statement about a different
53
+ * stream.
54
+ */
55
+ async putStream(key, content, mediaType, size) {
56
+ const { fixedLength, digestStream } = streaming();
57
+ const digest = new digestStream("SHA-256");
58
+ const writer = digest.getWriter();
59
+ let counted = 0;
60
+ const hashing = new TransformStream({
61
+ async transform(chunk, controller) {
62
+ counted += chunk.byteLength;
63
+ await writer.write(chunk);
64
+ controller.enqueue(chunk);
65
+ },
66
+ async flush() {
67
+ await writer.close();
68
+ },
69
+ });
70
+ const body = new fixedLength(size);
71
+ const stored = bucket.put(key, body.readable, { httpMetadata: { contentType: mediaType } });
72
+ // ⚠️ **Nothing here is ever awaited on its own, and that is the whole shape of this method.**
73
+ // Three promises are in flight and each of them can be the one that fails: the source, the
74
+ // write into the store's body, and the store itself. Awaiting one of them first means waiting
75
+ // forever for the other two whenever THAT one is not the one that broke — a store which
76
+ // refuses before it reads leaves the pipe with no reader, and a source which dies leaves the
77
+ // store with no bytes. Both were measured as a 30 s hang rather than a refusal.
78
+ const pipes = Promise.all([hashed(content, hashing), written(hashing, body)]);
79
+ const outcome = await Promise.race([
80
+ pipes.then(() => ({ side: "piped" }), (cause) => ({ side: "body", cause })),
81
+ stored.then(() => ({ side: "stored" }), (cause) => ({ side: "store", cause })),
82
+ ]);
83
+ // The digest stream is closed by the transform's `flush` and by nothing else, so a run that
84
+ // ends any other way has to end it here or its `digest` never settles. Every promise gets a
85
+ // catch of its own for the same reason: a failure already answered must not surface a second
86
+ // time as an unhandled rejection.
87
+ const giveUp = (cause) => {
88
+ void writer.abort(cause).catch(() => undefined);
89
+ void digest.digest.catch(() => undefined);
90
+ void stored.catch(() => undefined);
91
+ void pipes.catch(() => undefined);
92
+ };
93
+ if (outcome.side === "body") {
94
+ giveUp(outcome.cause);
95
+ throw new IntelError(400, "upload_incomplete", "The upload ended before the body did");
96
+ }
97
+ if (outcome.side === "store") {
98
+ giveUp(outcome.cause);
99
+ // The reason goes to the log, the answer names only whose side failed: a store can quote
100
+ // what a peer sent, and that is not something a response may carry.
101
+ reportUnexpectedError(outcome.cause);
102
+ throw new IntelError(502, "content_store_failed", "The file could not be stored");
103
+ }
104
+ // ⚠️ The length is compared before the store is asked how it went. A body that simply stops
105
+ // carries fewer bytes without failing a single write — the `FixedLengthStream` notices only
106
+ // when the store reads it — so without this the caller's short body and a failure inside the
107
+ // store would arrive as one rejection and be answered with one sentence. They are opposite
108
+ // failures: one is the caller's, the other is ours, and a reader sent hunting through their
109
+ // own connection for our outage is what that costs.
110
+ if (counted !== size) {
111
+ giveUp(new Error("short body"));
112
+ throw new IntelError(400, "upload_incomplete", `The body carried ${counted} bytes, and ${size} were announced`);
113
+ }
114
+ let object;
115
+ try {
116
+ object = await stored;
117
+ }
118
+ catch (cause) {
119
+ reportUnexpectedError(cause);
120
+ throw new IntelError(502, "content_store_failed", "The file could not be stored");
121
+ }
122
+ return { size: object.size, hash: hexDigest(await digest.digest) };
123
+ },
124
+ async delete(key) {
125
+ await bucket.delete(key);
126
+ },
127
+ };
128
+ }
@@ -0,0 +1,38 @@
1
+ export interface R2ObjectBody {
2
+ body: ReadableStream<Uint8Array>;
3
+ text(): Promise<string>;
4
+ arrayBuffer(): Promise<ArrayBuffer>;
5
+ }
6
+ export interface R2PutResult {
7
+ size: number;
8
+ }
9
+ export interface R2Bucket {
10
+ get(key: string): Promise<R2ObjectBody | null>;
11
+ put(key: string, value: string | ArrayBuffer | ReadableStream<Uint8Array>, options?: {
12
+ httpMetadata?: {
13
+ contentType?: string;
14
+ };
15
+ }): Promise<R2PutResult>;
16
+ delete(key: string): Promise<void>;
17
+ }
18
+ /**
19
+ * The two workerd streams this adapter needs, declared rather than imported (#821).
20
+ *
21
+ * ⚠️ `FixedLengthStream` is why a stream can reach R2 at all: a `put` needs to know how long the
22
+ * body is, and everything piped through a `TransformStream` has lost that. It carries the length
23
+ * with it and fails the write when the bytes disagree — the same guard, one layer lower.
24
+ *
25
+ * ⚠️ `crypto.DigestStream` is the hash of a file nobody holds. `crypto.subtle.digest` wants the
26
+ * whole buffer, which is the memory this path exists to avoid.
27
+ */
28
+ export interface FixedLengthStreamConstructor {
29
+ new (length: number): {
30
+ readable: ReadableStream<Uint8Array>;
31
+ writable: WritableStream<Uint8Array>;
32
+ };
33
+ }
34
+ export interface DigestStreamConstructor {
35
+ new (algorithm: string): WritableStream<Uint8Array> & {
36
+ digest: Promise<ArrayBuffer>;
37
+ };
38
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ import type { AuditRepository } from "../../audit/audit.types.js";
2
+ import type { D1Database } from "./db.types.js";
3
+ /**
4
+ * The journal, cut down to the rows this actor may see, continued from a stable position.
5
+ *
6
+ * ⚠️ **The visibility check is a JOIN against `allowed`, evaluated on every call.** `allowed` is
7
+ * the same tree walk `nodes` reads through (`db-grants.ts`), so an event about a node is visible
8
+ * exactly when the node is — no second rule that could drift from the first. It runs per row and
9
+ * per request; nothing here is cached, so a grant revoked a second ago is gone from the next
10
+ * answer.
11
+ *
12
+ * ⚠️ It filters the EXISTENCE of the row, not only its contents. That is deliberate and it is
13
+ * the stricter reading: that something is moving inside a customer's folder is itself
14
+ * information, so an actor who may not read the node learns nothing at all — not an id, not a
15
+ * count, not a timestamp.
16
+ *
17
+ * ⚠️ **An event about a purged node is therefore unreachable, for everybody.** `allowed` walks
18
+ * `nodes`, and after `node.purge` that row is gone, so the join finds nothing. This is not an
19
+ * oversight and it cannot be fixed without giving up the check: at a deleted row there is no
20
+ * longer anything against which a claim to have been allowed to read it could be tested. Hiding
21
+ * is the safe direction. A consumer learns about creation, change, moves and archiving — never
22
+ * about final deletion (#620).
23
+ *
24
+ * ⚠️ **`ORDER BY` and the cursor comparison must name BOTH columns, in the same order.** Two
25
+ * events in the same millisecond are the normal case in a batch, not the exception; on
26
+ * `occurred_at` alone the second one is skipped in silence — no error, no log, just an event
27
+ * that never arrived. The tuple comparison below is written out by hand because SQLite has no
28
+ * row-value comparison here: "later timestamp, OR same timestamp and larger id".
29
+ */
30
+ export declare const auditFeedQuery: string;
31
+ /**
32
+ * The same journal about FLOWS (#774).
33
+ *
34
+ * ⚠️ **A separate statement rather than a widened one, and that is the decision.** The three kinds
35
+ * do not differ in a value but in the QUESTION they ask: a node is visible when the node is in
36
+ * `allowed`, a flow when its folder is or it carries a grant of its own, a run one join further on.
37
+ * Written as one query with three branches, every caller would pay all three joins to read one
38
+ * kind — and `audit_list` names exactly one kind per call, so there is nothing to gain from it.
39
+ * The feed is the opposite case and rightly written the opposite way: it reads all three at once.
40
+ *
41
+ * ⚠️ **`INNER JOIN flows`, so an event about a purged flow is unreachable** — the same shape the
42
+ * node half has carried since #620, and for the same reason: at a deleted row there is nothing left
43
+ * against which a claim to have been allowed to read it could be tested. Hiding is the safe
44
+ * direction. The feed differs deliberately (it falls back on the purge's own metadata) because a
45
+ * card that says "deleted" is the whole point there; a journal consumer gets the deletion through
46
+ * the parent folder's events instead.
47
+ */
48
+ export declare const auditFlowFeedQuery: string;
49
+ /**
50
+ * And about RUNS, which is the walk one join further: run → flow → folder (#774).
51
+ *
52
+ * ⚠️ The alias is `run_flow` and it is handed to `flowInSubtreeOver` explicitly. Until #767 that
53
+ * guard had `flow` hard-wired, and against a flow reached through a second join every branch but
54
+ * the folder one compared NULL — a flow somebody OWNS but that hangs at the top level answered "not
55
+ * visible" to its own owner. It fails in the safe direction, which is exactly why it needs a test
56
+ * that seeds a run of a flow at the ROOT rather than in a folder.
57
+ */
58
+ export declare const auditRunFeedQuery: string;
59
+ export declare function createAuditRepository(deps: {
60
+ db: D1Database;
61
+ now(): Date;
62
+ }): AuditRepository;
@@ -0,0 +1,150 @@
1
+ import { flowInSubtree, flowInSubtreeBindings, flowInSubtreeOver, subtreeBindings, subtreeCte, } from "./db-grants.js";
2
+ function mapEvent(row, resourceType) {
3
+ let metadata = {};
4
+ // The column is `NOT NULL DEFAULT '{}'`, but it is written by 11 call sites over
5
+ // `JSON.stringify` on whatever each one had at hand. A row that cannot be parsed, or that parses
6
+ // to something other than an object, must not take the whole page down with it: the reader would
7
+ // then be stuck at that cursor forever with no way past. An unreadable payload becomes `{}` and
8
+ // the event itself still arrives — the fact that something happened is the part a change feed
9
+ // cannot afford to lose.
10
+ try {
11
+ const parsed = JSON.parse(row.metadata_json);
12
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
13
+ metadata = parsed;
14
+ }
15
+ }
16
+ catch {
17
+ metadata = {};
18
+ }
19
+ return {
20
+ id: row.id,
21
+ actorId: row.actor_id,
22
+ action: row.action,
23
+ // ⚠️ Taken from the QUESTION, not from the row. Each statement names exactly one
24
+ // `resource_type` in its `WHERE`, so the answer cannot carry another — and reading the column
25
+ // back would add a second truth about the same thing (#774).
26
+ resourceType,
27
+ resourceId: row.resource_id,
28
+ metadata,
29
+ occurredAt: row.occurred_at,
30
+ };
31
+ }
32
+ /**
33
+ * The journal, cut down to the rows this actor may see, continued from a stable position.
34
+ *
35
+ * ⚠️ **The visibility check is a JOIN against `allowed`, evaluated on every call.** `allowed` is
36
+ * the same tree walk `nodes` reads through (`db-grants.ts`), so an event about a node is visible
37
+ * exactly when the node is — no second rule that could drift from the first. It runs per row and
38
+ * per request; nothing here is cached, so a grant revoked a second ago is gone from the next
39
+ * answer.
40
+ *
41
+ * ⚠️ It filters the EXISTENCE of the row, not only its contents. That is deliberate and it is
42
+ * the stricter reading: that something is moving inside a customer's folder is itself
43
+ * information, so an actor who may not read the node learns nothing at all — not an id, not a
44
+ * count, not a timestamp.
45
+ *
46
+ * ⚠️ **An event about a purged node is therefore unreachable, for everybody.** `allowed` walks
47
+ * `nodes`, and after `node.purge` that row is gone, so the join finds nothing. This is not an
48
+ * oversight and it cannot be fixed without giving up the check: at a deleted row there is no
49
+ * longer anything against which a claim to have been allowed to read it could be tested. Hiding
50
+ * is the safe direction. A consumer learns about creation, change, moves and archiving — never
51
+ * about final deletion (#620).
52
+ *
53
+ * ⚠️ **`ORDER BY` and the cursor comparison must name BOTH columns, in the same order.** Two
54
+ * events in the same millisecond are the normal case in a batch, not the exception; on
55
+ * `occurred_at` alone the second one is skipped in silence — no error, no log, just an event
56
+ * that never arrived. The tuple comparison below is written out by hand because SQLite has no
57
+ * row-value comparison here: "later timestamp, OR same timestamp and larger id".
58
+ */
59
+ export const auditFeedQuery = `${subtreeCte}
60
+ SELECT e.id, e.actor_id, e.action, e.resource_id, e.metadata_json, e.occurred_at
61
+ FROM audit_events e
62
+ JOIN allowed ON allowed.id = e.resource_id
63
+ WHERE e.resource_type = 'node'
64
+ AND (
65
+ ? IS NULL
66
+ OR e.occurred_at > ?
67
+ OR (e.occurred_at = ? AND e.id > ?)
68
+ )
69
+ ORDER BY e.occurred_at ASC, e.id ASC
70
+ LIMIT ?`;
71
+ /**
72
+ * The same journal about FLOWS (#774).
73
+ *
74
+ * ⚠️ **A separate statement rather than a widened one, and that is the decision.** The three kinds
75
+ * do not differ in a value but in the QUESTION they ask: a node is visible when the node is in
76
+ * `allowed`, a flow when its folder is or it carries a grant of its own, a run one join further on.
77
+ * Written as one query with three branches, every caller would pay all three joins to read one
78
+ * kind — and `audit_list` names exactly one kind per call, so there is nothing to gain from it.
79
+ * The feed is the opposite case and rightly written the opposite way: it reads all three at once.
80
+ *
81
+ * ⚠️ **`INNER JOIN flows`, so an event about a purged flow is unreachable** — the same shape the
82
+ * node half has carried since #620, and for the same reason: at a deleted row there is nothing left
83
+ * against which a claim to have been allowed to read it could be tested. Hiding is the safe
84
+ * direction. The feed differs deliberately (it falls back on the purge's own metadata) because a
85
+ * card that says "deleted" is the whole point there; a journal consumer gets the deletion through
86
+ * the parent folder's events instead.
87
+ */
88
+ export const auditFlowFeedQuery = `${subtreeCte}
89
+ SELECT e.id, e.actor_id, e.action, e.resource_id, e.metadata_json, e.occurred_at
90
+ FROM audit_events e
91
+ JOIN flows flow ON flow.id = e.resource_id
92
+ WHERE e.resource_type = 'flow'
93
+ AND ${flowInSubtree}
94
+ AND (
95
+ ? IS NULL
96
+ OR e.occurred_at > ?
97
+ OR (e.occurred_at = ? AND e.id > ?)
98
+ )
99
+ ORDER BY e.occurred_at ASC, e.id ASC
100
+ LIMIT ?`;
101
+ /**
102
+ * And about RUNS, which is the walk one join further: run → flow → folder (#774).
103
+ *
104
+ * ⚠️ The alias is `run_flow` and it is handed to `flowInSubtreeOver` explicitly. Until #767 that
105
+ * guard had `flow` hard-wired, and against a flow reached through a second join every branch but
106
+ * the folder one compared NULL — a flow somebody OWNS but that hangs at the top level answered "not
107
+ * visible" to its own owner. It fails in the safe direction, which is exactly why it needs a test
108
+ * that seeds a run of a flow at the ROOT rather than in a folder.
109
+ */
110
+ export const auditRunFeedQuery = `${subtreeCte}
111
+ SELECT e.id, e.actor_id, e.action, e.resource_id, e.metadata_json, e.occurred_at
112
+ FROM audit_events e
113
+ JOIN flow_runs run ON run.id = e.resource_id
114
+ JOIN flows run_flow ON run_flow.id = run.flow_id
115
+ WHERE e.resource_type = 'flow-run'
116
+ AND ${flowInSubtreeOver("run_flow.parent_id", "run_flow")}
117
+ AND (
118
+ ? IS NULL
119
+ OR e.occurred_at > ?
120
+ OR (e.occurred_at = ? AND e.id > ?)
121
+ )
122
+ ORDER BY e.occurred_at ASC, e.id ASC
123
+ LIMIT ?`;
124
+ export function createAuditRepository(deps) {
125
+ return {
126
+ async listEvents(actor, query) {
127
+ const after = query.after ?? null;
128
+ const now = deps.now().toISOString();
129
+ // ⚠️ One reading of the clock for the whole call. Both guards measure grant expiry against
130
+ // it, and two `now()` readings could straddle the moment a grant runs out.
131
+ const guard = query.resourceType === "node"
132
+ ? { page: auditFeedQuery, bindings: subtreeBindings(actor, "read", now) }
133
+ : {
134
+ page: query.resourceType === "flow" ? auditFlowFeedQuery : auditRunFeedQuery,
135
+ // The flow walks need the CTE's bindings and the guard's, in that order — the guard
136
+ // is written into the statement after the CTE.
137
+ bindings: [
138
+ ...subtreeBindings(actor, "read", now),
139
+ ...flowInSubtreeBindings(actor, "read", now),
140
+ ],
141
+ };
142
+ const result = await deps.db
143
+ .prepare(guard.page)
144
+ .bind(...guard.bindings, after === null ? null : after.occurredAt, after === null ? null : after.occurredAt, after === null ? null : after.occurredAt, after === null ? null : after.id, query.limit)
145
+ .all();
146
+ const rows = result.results ?? [];
147
+ return { events: rows.map((row) => mapEvent(row, query.resourceType)) };
148
+ },
149
+ };
150
+ }
@@ -0,0 +1,6 @@
1
+ import type { BoardRepository } from "../../boards/boards.types.js";
2
+ import type { D1Database } from "./db.types.js";
3
+ export declare function createBoardRepository(deps: {
4
+ db: D1Database;
5
+ now(): Date;
6
+ }): BoardRepository;