@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
package/README.md ADDED
@@ -0,0 +1,496 @@
1
+ # @anchrd/intel
2
+
3
+ Intel is a customer-deployed, model-agnostic operating layer for company intelligence and processes. It
4
+ gives people and MCP-capable AI clients the same governed access to three surfaces:
5
+
6
+ - **Intelligence** — company content as nodes, with sharing, immutable versions, retrieval, citations and a graph
7
+ - **Flows** — versioned, durable processes that reference nodes and Tools
8
+ - **Tools** — MCP capabilities discovered through a Cloudflare MCP Portal
9
+
10
+ The UI, the HTTP API and the Intel MCP surface call the same application services, so authorization,
11
+ validation and side effects never differ by surface. You deploy it into your own Cloudflare account
12
+ against your own Gate; nothing runs on Anchrd infrastructure.
13
+
14
+ This package contains the portable server, the Cloudflare adapter, the D1 migrations and the
15
+ customer CLI.
16
+
17
+ ## Requirements
18
+
19
+ - A [Gate](https://www.npmjs.com/package/@anchrd/gate-sdk) instance — Gate owns identity and
20
+ capabilities, and is the only required Anchrd dependency
21
+ - A Cloudflare account with Workers, D1, R2, Queues and Workflows (Vectorize, Workers AI and an AI
22
+ Gateway are optional and only add semantic search and attachment conversion)
23
+ - Node 22 or newer
24
+
25
+ ## Setting Intel up
26
+
27
+ Nine steps. Step 3 talks only to Gate and can happen at any point; the rest run in this order,
28
+ because each one needs what the one before it produced. **Step 8 is the one people skip**, and
29
+ skipping it produces an installation that looks broken and is not.
30
+
31
+ ```bash
32
+ npm install @anchrd/intel
33
+ ```
34
+
35
+ ### 1. Create the Cloudflare resources
36
+
37
+ Workflows are created by the deploy in step 7; everything else has to exist first.
38
+
39
+ ```bash
40
+ wrangler d1 create intel # note the printed database_id
41
+ wrangler r2 bucket create intel-content
42
+ wrangler queues create intel-indexing
43
+ wrangler queues create intel-indexing-dlq # without it an exhausted message is dropped silently
44
+ wrangler vectorize create intel-nodes --dimensions=1024 --metric=cosine # optional, see Bindings
45
+ ```
46
+
47
+ The Vectorize shape is not a free choice: 1024 dimensions and cosine are what Intel's default
48
+ multilingual Workers AI embedding model (`@cf/baai/bge-m3`) produces. Nothing in the deploy compares
49
+ the two, so an index created with other values fails later, at the first write.
50
+
51
+ ### 2. Write the Worker
52
+
53
+ The customer edge re-exports the ready-made Cloudflare shell and nothing else. The named Workflow
54
+ class has to travel with it or Wrangler cannot find the entrypoint:
55
+
56
+ ```ts
57
+ // biome-ignore lint/performance/noBarrelFile: Wrangler needs the named Workflow entrypoint.
58
+ export { default, IntelFlowWorkflow } from "@anchrd/intel/cloudflare";
59
+ ```
60
+
61
+ Its Wrangler configuration declares the bindings from the table below, and points
62
+ `migrations_dir` at `.intel/migrations` — the directory step 4 fills. `assets.directory` points at
63
+ `.intel/ui`, which step 5 fills.
64
+
65
+ ### 3. Declare Intel's interfaces in Gate
66
+
67
+ ```bash
68
+ GATE_URL=… GATE_SERVICE_KEY=… npx intel bootstrap
69
+ ```
70
+
71
+ ⚠️ **`bootstrap` reads its configuration from the environment of the shell it runs in**, not from
72
+ the Worker's secrets — the two are different places that happen to use the same names. Without both
73
+ values it stops with `Error: GATE_URL and GATE_SERVICE_KEY must be set.` before it does anything.
74
+
75
+ It declares five interfaces — `intel`, `nodes`, `flows`, `tools`, `mcp` — with the functions listed
76
+ under *Permission, layer one* below. It is idempotent and safe to repeat after an upgrade.
77
+
78
+ ⚠️ **`bootstrap` hands out no grant, and it takes none away as long as the declared list does not
79
+ change.** It creates the permissions an administrator can hand out; it hands out none of them. This
80
+ is step 8, and it is why a fresh installation shows an empty screen to everybody including the
81
+ person who installed it.
82
+
83
+ ⚠️ **But a function that falls out of a still-declared interface takes its grants with it.**
84
+ Declaring is an upsert that REPLACES an interface's function list, and Gate deletes every grant on a
85
+ function the new list no longer names. So an upgrade that retires a function also retires every role
86
+ assignment on it — against a running installation that is a change to who may do what, not a
87
+ read. `bootstrap` reads the catalog before it writes and names each one as it goes:
88
+
89
+ ```text
90
+ Removed flows:approve from Gate; every grant on it was deleted with it.
91
+ Declared 5 Intel interfaces in Gate.
92
+ ```
93
+
94
+ A run that dropped nothing says so instead: `No declared function was dropped, so Gate deleted no
95
+ grant.` And if the catalog cannot be read, `bootstrap` writes nothing at all rather than delete
96
+ grants it would then be unable to name.
97
+
98
+ ⚠️ It never revokes a whole **interface**. One an older version declared stays declared in Gate:
99
+ `bootstrap` writes only the handles it names, so an interface outside that list keeps its functions
100
+ and its grants. That is harmless, and removing one is an act in Gate, by hand.
101
+
102
+ ### 4. Copy the migrations out of `node_modules`
103
+
104
+ ```bash
105
+ npx intel prepare
106
+ ```
107
+
108
+ This writes the versioned SQL to `.intel/migrations`. It only copies — applying them is the next
109
+ step, and nothing does it for you:
110
+
111
+ ```bash
112
+ wrangler d1 migrations apply intel --local # a local Worker
113
+ wrangler d1 migrations apply intel --remote # the deployed one
114
+ ```
115
+
116
+ Migration filenames and their order are immutable after release. Re-run `intel prepare` after every
117
+ upgrade of this package, before applying.
118
+
119
+ ### 5. Build the UI
120
+
121
+ ```bash
122
+ npx intel build
123
+ ```
124
+
125
+ `intel build` reads an optional strict `intel.json`, applies the customer branding, and writes the
126
+ static output to `.intel/ui`. See *Branding* below. No customer build output ever lives in
127
+ `node_modules`.
128
+
129
+ ### 6. Configure the Worker
130
+
131
+ Set the variables and secrets from the two tables below. `GATE_SERVICE_KEY` and
132
+ `INTEL_SESSION_SECRET` are Wrangler secrets (`wrangler secret put …`); the rest are plain vars.
133
+
134
+ For a local Worker, copy `node_modules/@anchrd/intel/examples/dev.vars.example` to `.dev.vars`.
135
+
136
+ ### 7. Check it, then deploy
137
+
138
+ ```bash
139
+ npx intel doctor
140
+ wrangler deploy
141
+ ```
142
+
143
+ `doctor` checks the same environment `bootstrap` uses, plus the installed packages and migrations
144
+ and the Gate interfaces. It reports every problem at once rather than the first:
145
+
146
+ ```text
147
+ Note: MCP_PORTAL_URL is unset, so the Tools area stays empty.
148
+ FAIL GATE_URL is missing
149
+ FAIL INTEL_URL is missing
150
+ FAIL GATE_SERVICE_KEY is missing
151
+ FAIL TOOL_SOURCE_ORIGINS is missing
152
+ FAIL INTEL_SESSION_SECRET must contain at least 32 bytes
153
+ ```
154
+
155
+ It also compares the Gate interfaces **in both directions**. A function or a whole interface Gate
156
+ carries that this version of Intel no longer declares is reported as a `NOTE`, never as a `FAIL`:
157
+ nothing is broken by it, and a check one knows red stops being read. Each note names the surplus,
158
+ why it went, and what to do about it:
159
+
160
+ ```text
161
+ NOTE Gate carries flows:approve, which Intel does not declare — the approval node is gone (#73).
162
+ NOTE Gate carries the interface knowledge (read, write), which Intel does not declare — the whole interface became `nodes` (#152, after #125).
163
+ NOTE The next `intel bootstrap` removes a surplus function and every grant on it (#474). Take the grant away in Gate first if anybody should keep it.
164
+ NOTE `bootstrap` never touches an interface Intel does not declare, so a surplus one stays until somebody removes it in Gate by hand — which takes its grants with it.
165
+ OK Intel packages, configuration, and Gate interfaces are ready.
166
+ ```
167
+
168
+ ⚠️ **`doctor` cannot see the Worker's secrets.** It answers about the shell it runs in, so it says
169
+ nothing about whether the deployed Worker is configured. `GET /health` on the deployed Worker
170
+ answers `{"status":"ok"}`; a Worker missing one of the five required variables answers
171
+ `500 configuration_missing` and names them.
172
+
173
+ ⚠️ **`doctor` does not check that step 4 happened.** It looks for the migrations *installed* in
174
+ `node_modules`, not for the copies in `.intel/migrations`, so it answers `OK` on a project that never
175
+ ran `intel prepare`. `wrangler deploy` does not mind an empty `migrations_dir` either, and the first
176
+ sign is a database with no tables in it. The `.intel/migrations` directory has to be checked by eye.
177
+
178
+ ### 8. Hand out permissions — both layers
179
+
180
+ This is the step that decides whether anybody sees anything, and it is entirely manual.
181
+
182
+ 1. In **Gate**, grant people the Intel capabilities from *Permission, layer one*. Without
183
+ `nodes.read` the sidebar answers `403` and says a permission is missing.
184
+ 2. In **Intel**, share a node with them. Without a grant the tree is empty — correctly, because
185
+ nothing has been shared yet.
186
+
187
+ Both are needed. Neither on its own produces a usable screen, and the symptom of missing either one
188
+ is the same shape: a view with nothing in it. See *Permission has two layers* below.
189
+
190
+ ### 9. Connect the portal, if there is one
191
+
192
+ Tools are optional. If the installation has a Cloudflare MCP Portal, set `MCP_PORTAL_URL` and add
193
+ its origin to `TOOL_SOURCE_ORIGINS`, then read *Tools come from the portal* below — two settings
194
+ outside this repository decide whether the silent sign-in can work at all.
195
+
196
+ ## Bindings
197
+
198
+ The reference Wrangler deployment binds all of these. "Required" means a request fails without it,
199
+ not that Wrangler refuses to deploy.
200
+
201
+ | Binding | Resource | Required | What its absence costs |
202
+ |---|---|---|---|
203
+ | `DB` | D1 | **yes** | Nothing works: D1 owns metadata, relationships, grants, flow and run state, audit |
204
+ | `CONTENT` | R2 | **yes** | Node content and attachments cannot be read or written |
205
+ | `INDEXING` | Queue | **yes** | Every save fails; this is the queue that builds the indexes |
206
+ | `FLOWS` | Workflow `IntelFlowWorkflow` | **yes** | Flows cannot be run |
207
+ | `ASSETS` | static assets from `.intel/ui` | for the UI | The API and MCP surface still answer; the browser application is not served at all |
208
+ | `AI` | Workers AI | no | **Two losses, and only one is obvious.** No semantic search, and no attachment conversion — an uploaded PDF or Word file is stored intact but never becomes searchable text |
209
+ | `SEARCH` | Vectorize index, 1024 dims, cosine | no | Search silently falls back to lexical only. Nothing says so, and half a search looks exactly like a whole one |
210
+
211
+ ⚠️ **Semantic search needs `AI`, `SEARCH` *and* the variable `AI_GATEWAY_ID`.** Any one of the three
212
+ missing leaves search lexical. If you add them to an existing installation, run `intel reindex`
213
+ afterwards — the embeddings for content already stored are built by that pass and by nothing else.
214
+
215
+ ⚠️ **The gateway is a condition, not an option.** Intel makes no Workers AI call without it: no
216
+ gateway name, no semantic index and no attachment conversion. The alternative — calling Workers AI
217
+ directly whenever the variable is absent — is the failure this rule exists against, because a spend
218
+ limit set on the gateway counts only what passes through it. An installation embedding past it works
219
+ perfectly, costs money, and tells nobody.
220
+
221
+ There is no `AGENT` service binding, and `AI_GATEWAY_ACCOUNT_ID` and the `AI_GATEWAY_READ_TOKEN`
222
+ secret are gone. All three belonged to the agent runtime, which is no longer part of Intel; an
223
+ installation that still carries them can drop them, including
224
+ `wrangler secret delete AI_GATEWAY_READ_TOKEN`. ⚠️ `AI_GATEWAY_ID` is **not** among them: it carries
225
+ a different job now, described in the row below.
226
+
227
+ ## Variables and secrets
228
+
229
+ Every value below is read in **two different places** depending on the command, and mixing them up
230
+ is the most common setup failure:
231
+
232
+ - the **Worker's** environment — what the deployed Intel reads on every request;
233
+ - the **shell's** environment — what `intel bootstrap`, `intel doctor` and `intel reindex` read.
234
+
235
+ `GATE_URL`, `GATE_SERVICE_KEY`, `INTEL_URL`, `INTEL_SESSION_SECRET` and `TOOL_SOURCE_ORIGINS` are
236
+ needed in both. Setting them only as Wrangler secrets leaves the CLI blind, and setting them only in
237
+ a shell leaves the Worker answering `500 configuration_missing`.
238
+
239
+ ⚠️ `MCP_PORTAL_URL` is the eighth value in the same trap, and the one that fails quietly.
240
+ `intel doctor` reads it from the shell as well, so a portal configured only as a Wrangler var makes
241
+ `doctor` report `MCP_PORTAL_URL is unset` about an installation that is configured correctly — and
242
+ skip the origin check it would otherwise have run.
243
+
244
+ | Name | Where | Required | What it does, and what a wrong value does |
245
+ |---|---|---|---|
246
+ | `GATE_URL` | Worker + shell | **yes** | The Gate this installation authenticates against. Wrong: every request is refused and no login completes |
247
+ | `GATE_SERVICE_KEY` | Worker secret + shell | **yes** | Intel's own service credential at Gate. Wrong: every authorization call fails, so everything answers as unauthenticated. It is a secret and never appears in a response, log or tool result |
248
+ | `INTEL_URL` | Worker + shell | **yes** | Intel's own public base URL. It is also **the OAuth resource identifier**: Intel asks Gate for a token for `<INTEL_URL>/mcp`. ⚠️ A trailing-slash or scheme difference is a *different* resource. ⚠️ **Changing it later is a one-way street**: the resource is bound once on the Gate side and cannot be re-pointed — the way back is deleting the Gate service and setting it up again. Decide the hostname before the first login, not after |
249
+ | `INTEL_SESSION_SECRET` | Worker secret + shell | **yes** | Derives the key for the encrypted `HttpOnly` session cookie and for sealing each person's portal token in D1. Must be at least 32 bytes. ⚠️ **Changing it invalidates every session and makes every stored portal token unreadable** — everybody signs in again, and everybody reconnects to the portal |
250
+ | `TOOL_SOURCE_ORIGINS` | Worker + shell | **yes** | Comma-separated **exact origins** Intel is allowed to fetch tools from. ⚠️ An entry carrying a path or credentials is refused — and refused *per request*, so a bad value deploys cleanly and then answers `500` on everything |
251
+ | `MCP_PORTAL_URL` | Worker + shell (for `doctor`) | no | The portal's Streamable HTTP MCP endpoint. Unset means the Tools area stays empty and Intel says so rather than reporting an error. ⚠️ Its origin must also appear in `TOOL_SOURCE_ORIGINS`; `intel doctor` fails when it does not — but only if it can see the value, so set it in the shell too before believing the check ran |
252
+ | `ALLOW_INSECURE_OAUTH` | Worker | no | `true` permits an `http://` OAuth issuer. **Local development only.** Production issuers must be HTTPS |
253
+ | `FLOW_RUN_STALL_TIMEOUT` | Worker | no | How long a run may stand on one step before it is ended as stalled, e.g. `30 minutes`. Too short is worse than the problem: it ends runs that were merely slow |
254
+ | `AI_GATEWAY_ID` | Worker | for `AI` | The **name** of the AI Gateway every Workers AI call is routed through, as it stands in the address of its dashboard page. ⚠️ Unset means Intel calls Workers AI **not at all** — no semantic index, no attachment conversion — rather than calling it directly. A wrong name fails the embedding and conversion calls loudly, which is the intended direction: a spend limit set on the gateway counts only what reaches it |
255
+ | `INTEL_OPERATOR_TOKEN` | shell | for `reindex` | A short-lived bearer carrying the Gate capability `intel.admin`, used only by `intel reindex`. Not a Worker value and not a stored one |
256
+
257
+ Gate OAuth uses PKCE and dynamic public-client registration; browser access tokens stay inside an
258
+ encrypted `HttpOnly` cookie and are never exposed to the UI bundle or D1.
259
+
260
+ ## Branding: `intel.json`
261
+
262
+ Put `intel.json` next to the customer project's `package.json`:
263
+
264
+ ```json
265
+ {
266
+ "ui": {
267
+ "theme": "./branding/theme.css",
268
+ "logo": "./branding/logo.svg",
269
+ "favicon": "./branding/favicon.svg",
270
+ "defaultLanguage": "en",
271
+ "languages": {}
272
+ }
273
+ }
274
+ ```
275
+
276
+ The theme is plain CSS containing shadcn semantic tokens such as `--primary`, `--background`,
277
+ `--sidebar`, and `--radius`. It is loaded after Intel's defaults, so customer tokens win without a
278
+ component fork. Unknown config fields, missing assets, non-SVG branding, and incomplete language
279
+ catalogs fail the build rather than producing a half-branded application. A ready-to-copy starting
280
+ point is included under `node_modules/@anchrd/intel/examples`.
281
+
282
+ The file is optional: `intel build` without it produces the default Intel branding.
283
+
284
+ ## Permission has two layers
285
+
286
+ Access to anything in Intel is the **and** of two independent answers, and neither layer knows about
287
+ the other. This is the single most common source of "it is broken" reports, because a person missing
288
+ either layer sees roughly the same thing: a screen with nothing on it.
289
+
290
+ ### Layer one: the Gate capability
291
+
292
+ What somebody may do *at all*, granted in Gate. `intel bootstrap` declares these; an administrator
293
+ grants them.
294
+
295
+ | Interface | Functions |
296
+ |---|---|
297
+ | `intel` | `admin` |
298
+ | `nodes` | `read`, `create`, `write`, `share` |
299
+ | `flows` | `read`, `create`, `write`, `publish`, `run`, `share` |
300
+ | `tools` | `read`, `test`, `execute` |
301
+ | `mcp` | `connect` |
302
+
303
+ A missing capability answers **`403`**, and the screen says a permission is missing.
304
+
305
+ ⚠️ **`mcp.connect` is the one that gates a whole endpoint rather than an action.** Intel's own MCP
306
+ endpoint (`POST /mcp`, the one an MCP client or a portal connects to) checks it **on every request**
307
+ and answers `403` without it — before any tool runs and before anything is read. Two things follow
308
+ for an operator:
309
+
310
+ - **Somebody who should use Intel through an MCP client needs `mcp.connect` in Intel**, beside their
311
+ `nodes.*` capabilities. Without it the client authenticates successfully and every call is refused.
312
+ - **Revoking it takes effect on the next call**, with no new sign-in and nothing to press. If a
313
+ Cloudflare Access policy in front of the endpoint also compares the `mcp` claim, that layer is the
314
+ slower of the two — the claim is written once per sign-in and a running session carries it for up
315
+ to 24 hours, while this check reads the live grant rows every time.
316
+
317
+ The web UI is unaffected: it speaks the HTTP surface, which is gated by `nodes.*`, `flows.*` and
318
+ `tools.*` as before.
319
+
320
+ ### Layer two: the grant on the node
321
+
322
+ What somebody may reach *in this tree*, granted in Intel on a node. Four verbs — `read`, `write`,
323
+ `execute`, `share` — each granted on its own; none implies another. Seeing a process is deliberately
324
+ separable from being allowed to start it.
325
+
326
+ A grant on a **folder is inherited by everything beneath it**, including nodes created after the
327
+ grant was made. That is the usual way to share a whole area.
328
+
329
+ A missing grant answers **`404`**, never `403`: Intel gives the same answer for "there is no such
330
+ node" and "not for you", so that a refusal never confirms that something exists.
331
+
332
+ ### Reading the empty screen
333
+
334
+ | What you see | Which layer |
335
+ |---|---|
336
+ | A sentence naming a missing permission | Gate — layer one |
337
+ | An empty tree, no error | Intel — nothing has been shared with this person yet |
338
+ | A node that vanished between two visits | Its grant was revoked; revocation takes effect immediately, on every path, without a new login |
339
+
340
+ A shared node appears in the recipient's navigation on its own, at the top level, without exposing
341
+ the titles of the folders above it. Nobody has to be sent a link.
342
+
343
+ ### Three things about grants that surprise people
344
+
345
+ - **A flow is not a node, and is reached by two things at once.** The folder it is filed in passes
346
+ its grants down, and since #530 a grant may sit on the flow itself; they add up. Move a flow and
347
+ you have changed the first half of that. A grant on one flow does not reach the flows it calls —
348
+ the answer names them, and `flow_validate` tells the person about to run what is still missing.
349
+ - **`organization` + `execute` on a folder makes that folder a library**: flows from anywhere in the
350
+ tree may then call into it. The share dialog warns before the click, because the way back is
351
+ narrow — revoking is refused with `409 folder_execute_in_use` for as long as one of those callers
352
+ still calls.
353
+ - **A grant can be complete and a flow still stop.** A run is re-authorized against the person
354
+ running it, so a flow in a shared folder that reads a document outside it stops for somebody who
355
+ cannot read that document. The answer names what was out of reach.
356
+
357
+ ## Export and import
358
+
359
+ `GET /api/v1/nodes/export` writes the whole installation as this caller may read it; the same route
360
+ under a node id exports that subtree. Import is the mirror:
361
+
362
+ ```bash
363
+ curl -X POST https://intel.example.com/api/v1/nodes/import \
364
+ -H "authorization: Bearer $TOKEN" \
365
+ -H "content-type: application/zip" \
366
+ -H "idempotency-key: $(uuidgen)" \
367
+ --data-binary @bundle.zip
368
+ ```
369
+
370
+ ⚠️ **The idempotency key travels as a header.** The body is the zip itself, so there is nowhere else
371
+ to put it. A request without the header is refused.
372
+
373
+ Only nodes the caller may read enter the bundle; exporting a folder that is out of reach answers
374
+ `404`. A fresh import answers `201`; a repeat of the same idempotency key answers `200` with the
375
+ summary of the earlier import, because this request created nothing.
376
+
377
+ ⚠️ **A bundle carries only the current state of each node. Version history does not survive
378
+ export → import.** A document with two versions comes back with one, and the earlier one is then
379
+ retrievable nowhere. Everything else survives in full — nodes per kind, table content including a
380
+ previous `redefine`, and attachments byte for byte. The loss is accepted and deliberate, but anyone
381
+ moving an installation this way has to know about it **before** they start: after the import there
382
+ is nothing to recover from.
383
+
384
+ ## Tools come from the portal
385
+
386
+ Intel stores no tool permissions. The catalog is a **live `tools/list`** made with the requesting
387
+ person's own token, never a mirrored table. Two consequences follow, and both are correct behaviour
388
+ rather than bugs:
389
+
390
+ - **Two people legitimately see different tools**, and the same person can see a different set
391
+ tomorrow. What is offered is whatever the portal answers for them at that moment.
392
+ - **A tool can disappear between defining a flow and running it.** Published flows pin immutable
393
+ MCP schema fingerprints, so a changed or vanished tool is reported by name instead of being
394
+ silently substituted.
395
+
396
+ The portal endpoint exposes RFC 9728 metadata. The Tools UI follows that metadata, dynamically
397
+ registers with Gate or Cloudflare Access, and completes a separate PKCE flow — silently, with
398
+ `prompt=none`, as soon as a Gate session exists. Nobody is asked to connect anything.
399
+
400
+ ⚠️ **Two settings outside this repository decide whether that silent sign-in can work.** In
401
+ Cloudflare Zero Trust → Access controls → AI controls → your portal → Edit → Advanced settings,
402
+ `Managed OAuth` must be enabled, and an Access policy must carry the people who use Intel. Without
403
+ both, every silent sign-in is refused and the Tools area shows "No access to the company portal" —
404
+ correct behaviour for somebody outside every policy, and a misleading one for a deployment that
405
+ simply never enabled the setting.
406
+
407
+ ⚠️ **Somebody who carries the Gate capability `mcp.connect` at no service at all is not sent into
408
+ that sign-in.** Gate answers that question service-wide, Intel asks it before the first redirect,
409
+ and the person stays here reading a sentence that says whom to ask — rather than landing on the
410
+ portal's own error page, outside Intel, with no way back but the browser's back button
411
+ (anchrd/intel#434). Grant `mcp.connect` alongside the Intel capabilities to everyone who should
412
+ reach Tools.
413
+
414
+ Two things that guard deliberately does not do. It **names no server**: the answer is one bit, so
415
+ somebody who may reach a different product's MCP server walks on and sees what the portal offers
416
+ them. And it **promises nothing** — this is the part worth knowing before you grant: the portal
417
+ decides on the `mcp` claim frozen into the ID token, and a running Cloudflare Access session carries
418
+ the old claim for up to 24 hours. ⚠️ **Inside that window the old dead end is still open.** Somebody
419
+ who was granted `mcp.connect` a minute ago is not refused here, walks on, and Access then decides on
420
+ the claim state that produced the error page in the first place. The guard closes the trip that is
421
+ certainly pointless; it does not close this one. The way out is the same as before — sign out of
422
+ Access and in again, so a new ID token carries the new claim. (Not measured against a running
423
+ installation; the claim lifetime is the documented one.) Against a Gate too old to answer the
424
+ question at all, nobody is refused here.
425
+
426
+ The Tools screen distinguishes four situations rather than calling all of them "no access": a
427
+ refusal that really came back, an expired connection, a sign-in that broke, and a sign-in that was
428
+ started and never answered. Only the first has no button, because only there is there nothing a
429
+ second attempt would change.
430
+
431
+ The only tool secret Intel stores is the resulting per-user access token for its own portal
432
+ endpoint — one per person, never one shared operator token — sealed with a key derived from
433
+ `INTEL_SESSION_SECRET` and kept in the `portal_tokens` table of your D1; provider credentials stay
434
+ with the portal and never reach Intel.
435
+
436
+ Intel unseals that token just in time and renews it shortly before it expires. **"Expired" above is
437
+ what a failed renewal looks like**: a token that cannot be renewed is dropped rather than kept and
438
+ retried with, the browser signs in again silently, and an MCP client repeats its own authorization.
439
+ Two different causes end up there — a portal that issued no refresh token at all, which is a
440
+ configuration problem, and a refresh that was rejected, which is not — and Intel logs which of the
441
+ two it was, because the person only ever sees "sign in again". The Intel audience token is never forwarded to another OAuth
442
+ resource. Durable Flow state contains no browser, Gate, or provider credentials.
443
+
444
+ ## The `intel` CLI
445
+
446
+ ```text
447
+ intel prepare Copy versioned D1 migrations to .intel/migrations
448
+ intel bootstrap Idempotently declare Intel interfaces in Gate
449
+ intel build Apply intel.json and atomically build the customer UI
450
+ intel doctor Check packages, environment, migrations, UI, and Gate interfaces
451
+ intel reindex Request a full authorized search-index rebuild
452
+ ```
453
+
454
+ All five run in the customer project directory — the one holding `package.json`, `intel.json` and
455
+ `node_modules` — and read their configuration from that shell's environment.
456
+
457
+ `intel reindex` needs `INTEL_URL` and a short-lived `INTEL_OPERATOR_TOKEN`. It asks the running
458
+ installation to rebuild the derived indexes from D1 and R2 and returns as soon as the request is
459
+ accepted; the work happens on the indexing queue. Reach for it after adding `AI`, `SEARCH` and
460
+ `AI_GATEWAY_ID` to an installation that ran without them, and after restoring an emptied Vectorize
461
+ index.
462
+
463
+ ## Writing against the API directly
464
+
465
+ Everything the browser does is available over HTTP and over the Intel MCP surface, against the same
466
+ application services. The schemas are inside this package under `src/contract` — the runtime-
467
+ validated wire formats the server, the browser application and every MCP tool share. Read
468
+ [`src/contract/README.md`](./src/contract/README.md) first: it carries the six things that reliably
469
+ cost a first-time caller an afternoon.
470
+
471
+ ## What is in this package
472
+
473
+ One package carries all of Intel, and that is deliberate: an installation pins **one** version
474
+ number instead of three that could drift apart.
475
+
476
+ | Path | What it is |
477
+ |---|---|
478
+ | `dist/` | the server: portable application services, the HTTP and MCP adapters, the Cloudflare shell behind `@anchrd/intel/cloudflare` |
479
+ | `bin/intel.mjs` | the `intel` CLI — `prepare`, `bootstrap`, `build`, `doctor`, `reindex` |
480
+ | `migrations/` | the D1 migrations, copied out by `intel prepare` |
481
+ | `src/contract/` | the wire schemas, as source, because the browser application compiles them too |
482
+ | `ui/` | the browser application, shipped as **source** so `intel build` applies your own theme, logo and languages — see [`ui/README.md`](./ui/README.md) |
483
+
484
+ ⚠️ **Installing this package pulls the browser build toolchain with it** — Vite, React, Tailwind and
485
+ the document renderers are runtime dependencies here, even if you never run `intel build`. That is
486
+ the knowingly accepted cost of one version number: a headless Intel has no consumer today, and
487
+ splitting one out later is more expensive than not building it now.
488
+
489
+ ⚠️ **`@anchrd/intel-api`, `@anchrd/intel-ui` and `@anchrd/intel-contract` are the predecessors of this
490
+ package.** Once this package is on npm they get an `npm deprecate` pointing here. They are **not**
491
+ deleted, and the versions that are published stay published.
492
+
493
+ ## License
494
+
495
+ Proprietary. Published publicly for installation convenience; this is not an open-source license and
496
+ grants no right to use, copy, modify or redistribute the software. Contact Anchrd for licensing.
package/bin/intel.mjs ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from "node:child_process";
3
+ import { cp, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
4
+ import { dirname, resolve } from "node:path";
5
+ import { createGateClient } from "@anchrd/gate-sdk";
6
+ import { createCli } from "../dist/cli/cli.js";
7
+
8
+ // Since #827 the surface and the migrations travel inside @anchrd/intel itself, so an installation
9
+ // finds both below one package directory. The second entry of each pair is this repository's own
10
+ // tree, which is what `bun run build` and `bun run dev` walk.
11
+ const uiCandidates = [
12
+ { dir: "node_modules/@anchrd/intel/ui", outDir: ".intel/ui" },
13
+ { dir: "packages/intel/ui", outDir: "packages/intel/ui/dist" },
14
+ ];
15
+ const migrationCandidates = ["node_modules/@anchrd/intel/migrations", "packages/intel/migrations"];
16
+
17
+ // npm sets npm_execpath to its own JavaScript entry point. Running that through the current Node
18
+ // binary avoids the .cmd shim entirely, which matters on Windows: Node has refused to spawn a .cmd
19
+ // without a shell since CVE-2024-27980, and cmd.exe expands %NAME% even inside quotes, so a checkout
20
+ // path containing a percent sign would be rewritten.
21
+ function npmScriptPath(command) {
22
+ if (command !== "npm") return null;
23
+ const execPath = process.env.npm_execpath;
24
+ return execPath?.endsWith(".js") ? execPath : null;
25
+ }
26
+
27
+ // Only reached on the Windows shell fallback, where cmd.exe would otherwise split on whitespace.
28
+ function quoteForCmd(argument) {
29
+ if (!/[\s"^&|<>()]/.test(argument)) return argument;
30
+ return `"${argument.replaceAll('"', '""')}"`;
31
+ }
32
+
33
+ function spawnArguments(command, args) {
34
+ const script = npmScriptPath(command);
35
+ if (script) return [process.execPath, [script, ...args]];
36
+ if (process.platform !== "win32") return [command, args];
37
+ return [`${command}.cmd`, args.map(quoteForCmd)];
38
+ }
39
+
40
+ async function isFile(path) {
41
+ try {
42
+ return (await stat(path)).isFile();
43
+ } catch (error) {
44
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR") return false;
45
+ throw error;
46
+ }
47
+ }
48
+
49
+ async function isDirectory(path) {
50
+ try {
51
+ return (await stat(path)).isDirectory();
52
+ } catch (error) {
53
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR") return false;
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ async function replaceDir(from, to) {
59
+ await mkdir(dirname(to), { recursive: true });
60
+ const backup = `${to}.old`;
61
+ await rm(backup, { recursive: true, force: true });
62
+ let hasBackup = false;
63
+ try {
64
+ await rename(to, backup);
65
+ hasBackup = true;
66
+ } catch (error) {
67
+ if (error?.code !== "ENOENT") throw error;
68
+ }
69
+ try {
70
+ await rename(from, to);
71
+ } catch (error) {
72
+ if (hasBackup) await rename(backup, to);
73
+ throw error;
74
+ }
75
+ if (hasBackup) await rm(backup, { recursive: true, force: true });
76
+ }
77
+
78
+ const cli = createCli({
79
+ env: process.env,
80
+ fetch: globalThis.fetch,
81
+ createGateInterfaces: (url, serviceKey) => createGateClient({ url, serviceKey }).interfaces,
82
+ readTextFile: async (path) => {
83
+ try {
84
+ return await readFile(path, "utf8");
85
+ } catch (error) {
86
+ if (error?.code === "ENOENT") return null;
87
+ throw error;
88
+ }
89
+ },
90
+ writeTextFile: async (path, content) => {
91
+ await mkdir(dirname(path), { recursive: true });
92
+ await writeFile(path, content, "utf8");
93
+ },
94
+ resolveUi: async () => {
95
+ for (const candidate of uiCandidates) {
96
+ if (await isFile(`${candidate.dir}/package.json`)) {
97
+ return { dir: candidate.dir, outDir: resolve(process.cwd(), candidate.outDir) };
98
+ }
99
+ }
100
+ return null;
101
+ },
102
+ resolveMigrations: async () => {
103
+ for (const dir of migrationCandidates) {
104
+ if (await isDirectory(dir)) {
105
+ return { dir, outDir: resolve(process.cwd(), ".intel/migrations") };
106
+ }
107
+ }
108
+ return null;
109
+ },
110
+ copyDir: async (from, to) => {
111
+ await rm(to, { recursive: true, force: true });
112
+ await mkdir(dirname(to), { recursive: true });
113
+ await cp(from, to, { recursive: true });
114
+ },
115
+ exec: (command, args, { cwd }) =>
116
+ new Promise((resolveCode, reject) => {
117
+ const child = spawn(...spawnArguments(command, args), {
118
+ cwd,
119
+ stdio: "inherit",
120
+ shell: process.platform === "win32" && !npmScriptPath(command),
121
+ });
122
+ child.on("error", reject);
123
+ child.on("close", (code) => resolveCode(code ?? 1));
124
+ }),
125
+ replaceDir,
126
+ log: (message) => console.log(message),
127
+ });
128
+
129
+ try {
130
+ process.exitCode = await cli.run(process.argv.slice(2));
131
+ } catch (error) {
132
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
133
+ process.exitCode = 1;
134
+ }
@@ -0,0 +1,42 @@
1
+ import type { CloudflareEnv } from "./cloudflare.types.js";
2
+ interface WorkflowEvent<Params> {
3
+ payload: Readonly<Params>;
4
+ }
5
+ interface WorkflowStep {
6
+ do<T>(name: string, callback: () => Promise<T>): Promise<T>;
7
+ waitForEvent(name: string, options: {
8
+ type: string;
9
+ timeout?: string | number;
10
+ }): Promise<unknown>;
11
+ }
12
+ interface FlowWorkflowParams {
13
+ runId: string;
14
+ }
15
+ interface IntelFlowWorkflowInstance {
16
+ run(event: Readonly<WorkflowEvent<FlowWorkflowParams>>, step: WorkflowStep): Promise<unknown>;
17
+ }
18
+ /**
19
+ * What the durable wait actually does, with storage handed in.
20
+ *
21
+ * ⚠️ Separated from the class because `WorkflowEntrypoint` is a runtime class that cannot be
22
+ * constructed outside workerd's workflow context — so as long as this logic lived inside it, none
23
+ * of it could be tested, including the rule that keeps a caller alive while its child runs. That
24
+ * rule is the one that decides whether this feature destroys work or not, and it had to be
25
+ * provable. The shell below is now only bindings and SQL, which is what `CLAUDE.md` asks of it.
26
+ */
27
+ export declare function driveFlowRun(step: WorkflowStep, deps: {
28
+ readStatus(): Promise<{
29
+ status: string;
30
+ error: string | null;
31
+ }>;
32
+ hasRunningChild(): Promise<boolean>;
33
+ markFailed(error: string): Promise<void>;
34
+ stallTimeout: string;
35
+ }): Promise<{
36
+ status: string;
37
+ error: string | null;
38
+ }>;
39
+ export declare const IntelFlowWorkflow: {
40
+ new (context: unknown, env: CloudflareEnv): IntelFlowWorkflowInstance;
41
+ };
42
+ export {};