okengine 0.18.5 → 0.19.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 (510) hide show
  1. package/AGENTS.md +18 -10
  2. package/README.md +2 -2
  3. package/package.json +51 -50
  4. package/site/content/docs/ai/llms-txt.mdx +1 -1
  5. package/site/content/docs/ai/meta.json +1 -1
  6. package/site/content/docs/ai/skills.mdx +4 -1
  7. package/site/content/docs/ai/try-it.mdx +58 -0
  8. package/site/content/docs/client/auth.mdx +208 -0
  9. package/site/content/docs/client/calling.mdx +451 -0
  10. package/site/content/docs/client/index.mdx +209 -0
  11. package/site/content/docs/client/live.mdx +234 -0
  12. package/site/content/docs/client/meta.json +5 -0
  13. package/site/content/docs/client/react.mdx +249 -0
  14. package/site/content/docs/elements/ai/agents.mdx +232 -0
  15. package/site/content/docs/elements/ai/index.mdx +341 -0
  16. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  17. package/site/content/docs/elements/ai/meta.json +5 -0
  18. package/site/content/docs/elements/ai/models.mdx +283 -0
  19. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  20. package/site/content/docs/elements/channel/email.mdx +266 -0
  21. package/site/content/docs/elements/channel/index.mdx +344 -0
  22. package/site/content/docs/elements/channel/meta.json +5 -0
  23. package/site/content/docs/elements/channel/push.mdx +218 -0
  24. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  25. package/site/content/docs/elements/channel/sms.mdx +264 -0
  26. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  27. package/site/content/docs/elements/clock/index.mdx +300 -0
  28. package/site/content/docs/elements/clock/meta.json +5 -0
  29. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  30. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  31. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  32. package/site/content/docs/elements/flow/http.mdx +1080 -0
  33. package/site/content/docs/elements/flow/index.mdx +618 -0
  34. package/site/content/docs/elements/flow/meta.json +5 -0
  35. package/site/content/docs/elements/flow/routing.mdx +559 -0
  36. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  37. package/site/content/docs/elements/gate/auth.mdx +371 -0
  38. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  39. package/site/content/docs/elements/gate/index.mdx +418 -0
  40. package/site/content/docs/elements/gate/meta.json +5 -0
  41. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  42. package/site/content/docs/elements/gate/rls.mdx +303 -0
  43. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  44. package/site/content/docs/elements/index.mdx +20 -10
  45. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  46. package/site/content/docs/elements/signal/index.mdx +352 -0
  47. package/site/content/docs/elements/signal/live.mdx +590 -0
  48. package/site/content/docs/elements/signal/meta.json +5 -0
  49. package/site/content/docs/elements/signal/once.mdx +596 -0
  50. package/site/content/docs/elements/store/files.mdx +659 -0
  51. package/site/content/docs/elements/store/index.mdx +310 -0
  52. package/site/content/docs/elements/store/kv.mdx +629 -0
  53. package/site/content/docs/elements/store/meta.json +5 -0
  54. package/site/content/docs/elements/store/search.mdx +946 -0
  55. package/site/content/docs/elements/store/sql.mdx +937 -0
  56. package/site/content/docs/elements/vault/config.mdx +256 -0
  57. package/site/content/docs/elements/vault/index.mdx +356 -0
  58. package/site/content/docs/elements/vault/meta.json +5 -0
  59. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  60. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  61. package/site/content/docs/index.mdx +63 -36
  62. package/site/content/docs/meta.json +8 -7
  63. package/site/content/docs/plugins/cors.mdx +2 -1
  64. package/site/content/docs/plugins/csrf.mdx +4 -1
  65. package/site/content/docs/plugins/headers.mdx +2 -1
  66. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  67. package/site/content/docs/plugins/magic-link.mdx +6 -0
  68. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  69. package/site/content/docs/plugins/oauth.mdx +1 -1
  70. package/site/content/docs/plugins/otp.mdx +12 -1
  71. package/site/content/docs/plugins/passkey.mdx +39 -15
  72. package/site/content/docs/plugins/two-factor.mdx +91 -34
  73. package/site/content/docs/plugins/username.mdx +1 -1
  74. package/site/content/docs/recipes/caddy.mdx +3 -3
  75. package/site/content/docs/recipes/index.mdx +18 -28
  76. package/site/content/docs/recipes/mailpit.mdx +1 -1
  77. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  78. package/site/content/docs/recipes/meta.json +1 -4
  79. package/site/content/docs/recipes/nginx.mdx +2 -2
  80. package/site/content/docs/recipes/openrouter.mdx +283 -0
  81. package/site/content/docs/recipes/pgdog.mdx +3 -3
  82. package/site/content/docs/recipes/postgres.mdx +1 -2
  83. package/site/content/docs/recipes/rustfs.mdx +2 -2
  84. package/site/content/docs/recipes/traefik.mdx +3 -3
  85. package/site/content/docs/reference/cli.mdx +231 -0
  86. package/site/content/docs/reference/configuration.mdx +30 -10
  87. package/site/content/docs/reference/environment-variables.mdx +93 -20
  88. package/site/content/docs/reference/errors.mdx +132 -29
  89. package/site/content/docs/reference/fx.mdx +137 -73
  90. package/site/content/docs/reference/index.mdx +13 -21
  91. package/site/content/docs/reference/meta.json +4 -5
  92. package/site/content/docs/reference/okid.mdx +42 -17
  93. package/site/content/docs/reference/plugins.mdx +4 -3
  94. package/site/content/docs/reference/security.mdx +197 -0
  95. package/site/content/docs/understand/meta.json +5 -0
  96. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  97. package/site/content/docs/understand/the-model.mdx +32 -0
  98. package/site/content/docs/understand/the-problem.mdx +74 -0
  99. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  100. package/src/auth/api-keys.ts +2 -1
  101. package/src/auth/bindings.ts +64 -16
  102. package/src/auth/gate-auth.test.ts +6 -1
  103. package/src/auth/identity.ts +152 -5
  104. package/src/auth/index.ts +29 -0
  105. package/src/auth/invites.ts +2 -1
  106. package/src/auth/method-context.ts +41 -0
  107. package/src/auth/oauth-as/crypto.ts +2 -1
  108. package/src/auth/oauth-as/stores.ts +2 -1
  109. package/src/auth/operator.ts +2 -1
  110. package/src/auth/sessions-jwt.test.ts +77 -0
  111. package/src/auth/sessions.ts +20 -4
  112. package/src/auth/tenants.ts +3 -2
  113. package/src/auth/two-factor-challenge.test.ts +61 -0
  114. package/src/auth/two-factor-challenge.ts +284 -0
  115. package/src/auth/verification.ts +5 -0
  116. package/src/bench/REPORT.md +49 -0
  117. package/src/bench/g03-signal-once.bench.ts +1 -1
  118. package/src/bench/g10-observability-contention.bench.ts +1 -1
  119. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  120. package/src/bench/load-app.ts +2 -10
  121. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  122. package/src/cli/ai-setup/apply.ts +294 -52
  123. package/src/cli/ai-setup/catalog.ts +238 -1342
  124. package/src/cli/ai-setup/index.ts +14 -99
  125. package/src/cli/ai-setup/prompts.ts +60 -443
  126. package/src/cli/ask-seed.test.ts +96 -0
  127. package/src/cli/ask-seed.ts +82 -0
  128. package/src/cli/ask-vault-gaps.test.ts +84 -0
  129. package/src/cli/ask-vault-gaps.ts +146 -0
  130. package/src/cli/build.ts +2 -2
  131. package/src/cli/client-add.test.ts +26 -1
  132. package/src/cli/client-add.ts +106 -27
  133. package/src/cli/db-seed.ts +2 -0
  134. package/src/cli/db.ts +150 -11
  135. package/src/cli/dev.ts +119 -211
  136. package/src/cli/docker-clean.ts +2 -2
  137. package/src/cli/docker-cli.test.ts +1 -1
  138. package/src/cli/doctor-diff.ts +4 -2
  139. package/src/cli/doctor-pii.test.ts +1 -1
  140. package/src/cli/doctor.ts +14 -1
  141. package/src/cli/hero-meta.test.ts +4 -2
  142. package/src/cli/load-config.images.test.ts +8 -10
  143. package/src/cli/load-config.ts +1 -1
  144. package/src/cli/registry.ts +22 -10
  145. package/src/cli/replay.ts +3 -1
  146. package/src/cli/start.ts +1 -1
  147. package/src/cli/tui/keys.ts +2 -3
  148. package/src/client/auth/cookies.ts +74 -0
  149. package/src/client/auth/create-auth-client.ts +636 -0
  150. package/src/client/auth/denials.ts +99 -0
  151. package/src/client/auth/session.ts +283 -0
  152. package/src/client/auth.test.ts +251 -0
  153. package/src/client/auth.ts +39 -114
  154. package/src/client/create-with-session.ts +245 -0
  155. package/src/client/create.ts +51 -5
  156. package/src/client/index.ts +11 -1
  157. package/src/client/live.ts +11 -79
  158. package/src/client/notes-contract.test.ts +5 -10
  159. package/src/client/sse.ts +137 -0
  160. package/src/client/stream.ts +147 -0
  161. package/src/client/transport.test.ts +32 -0
  162. package/src/client/transport.ts +123 -26
  163. package/src/client/types.ts +118 -14
  164. package/src/client-react/index.ts +185 -24
  165. package/src/client-react/use-live-query.ts +13 -3
  166. package/src/compiler/aot.test.ts +7 -4
  167. package/src/compiler/effects-embed.test.ts +56 -0
  168. package/src/compiler/effects-fetch.test.ts +43 -0
  169. package/src/compiler/effects-infer.ts +58 -2
  170. package/src/compiler/extract.test.ts +257 -43
  171. package/src/compiler/extract.ts +566 -48
  172. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  173. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  174. package/src/compiler/fixtures/skyport.expected.json +4 -4
  175. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  176. package/src/compiler/response.ts +2 -2
  177. package/src/compiler/search-writer-isolation.test.ts +40 -0
  178. package/src/config/index.ts +11 -0
  179. package/src/console/server/app.ts +17 -23
  180. package/src/console/server/bind.ts +4 -0
  181. package/src/console/server/console.test.ts +2 -2
  182. package/src/console/server/flows-invoke.test.ts +50 -34
  183. package/src/console/server/flows.ts +436 -255
  184. package/src/console/server/runs-ingest.test.ts +6 -3
  185. package/src/console/server/serve.ts +1 -1
  186. package/src/console/server/signals.test.ts +1 -5
  187. package/src/console/server/signals.ts +8 -6
  188. package/src/console/server/state.ts +6 -1
  189. package/src/console/server/store.ts +1 -1
  190. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  191. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  192. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  193. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  194. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  195. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  196. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  197. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  198. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  199. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  200. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  201. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  202. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  203. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  204. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  205. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  206. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  207. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  208. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  209. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  210. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  211. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  212. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  213. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  214. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  215. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  216. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  217. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  218. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  219. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  220. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  221. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  222. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  223. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  224. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  225. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  226. package/src/console/ui-next/dist/index.html +6 -13
  227. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  228. package/src/console/ui-next/src/client.ts +7 -2
  229. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  230. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  231. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  232. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  233. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  235. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  236. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  237. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  238. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  239. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  240. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  241. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  242. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  243. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  244. package/src/docker/ai-model-status.test.ts +1 -12
  245. package/src/docker/ai-model-status.ts +10 -38
  246. package/src/docker/compose-up.test.ts +100 -0
  247. package/src/docker/compose-up.ts +292 -0
  248. package/src/docker/compose.ts +4 -14
  249. package/src/docker/derive.ts +9 -34
  250. package/src/docker/docker.test.ts +16 -261
  251. package/src/docker/images-config.test.ts +13 -25
  252. package/src/docker/index.ts +1 -24
  253. package/src/docker/recipes/index.ts +0 -23
  254. package/src/docker/recipes/pgdog.ts +6 -4
  255. package/src/docker/stack-id.test.ts +2 -2
  256. package/src/docker/stack-id.ts +0 -1
  257. package/src/docker/types.ts +2 -2
  258. package/src/drivers/ai-anthropic.ts +10 -0
  259. package/src/drivers/ai-openai-compatible.ts +34 -7
  260. package/src/drivers/ai-providers.test.ts +0 -107
  261. package/src/drivers/ai-stream.test.ts +0 -34
  262. package/src/drivers/ai-types.ts +17 -8
  263. package/src/drivers/channel-fcm.ts +6 -1
  264. package/src/drivers/channel-msegat.ts +6 -1
  265. package/src/drivers/channel-resend.ts +5 -1
  266. package/src/drivers/channel-smtp.ts +5 -1
  267. package/src/drivers/channel-sndr.ts +10 -1
  268. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  269. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  270. package/src/drivers/channel-taqnyat.ts +6 -1
  271. package/src/drivers/channel-types.ts +10 -0
  272. package/src/drivers/channel-unifonic.ts +6 -1
  273. package/src/drivers/channel-wa-cloud.ts +6 -1
  274. package/src/drivers/channel-webpush.ts +6 -1
  275. package/src/drivers/external.ts +33 -0
  276. package/src/drivers/index.ts +0 -10
  277. package/src/drivers/meilisearch.ts +6 -0
  278. package/src/drivers/oauth-types.ts +4 -0
  279. package/src/drivers/postgres.test.ts +74 -3
  280. package/src/drivers/postgres.ts +175 -6
  281. package/src/drivers/signal-types.ts +5 -5
  282. package/src/drivers/types.ts +7 -0
  283. package/src/drivers/vault-types.ts +5 -0
  284. package/src/elements/ai/declare.ts +17 -4
  285. package/src/elements/ai/eval.ts +1 -1
  286. package/src/elements/ai/mcp-http.ts +1 -1
  287. package/src/elements/ai/pii.ts +1 -1
  288. package/src/elements/ai/providers.test.ts +289 -0
  289. package/src/elements/ai/providers.ts +169 -0
  290. package/src/elements/ai/runtime.ts +68 -5
  291. package/src/elements/ai/schema.ts +2 -2
  292. package/src/elements/ai.test.ts +7 -7
  293. package/src/elements/ai.ts +17 -1
  294. package/src/elements/channel/runtime.ts +105 -12
  295. package/src/elements/clock/cron-fields.test.ts +144 -0
  296. package/src/elements/clock/cron-fields.ts +185 -0
  297. package/src/elements/clock/declare.ts +247 -3
  298. package/src/elements/clock.ts +21 -1
  299. package/src/elements/index.ts +15 -0
  300. package/src/elements/signal/chaos-child.ts +1 -2
  301. package/src/elements/signal/declare.ts +65 -37
  302. package/src/elements/signal/delivery-modes.test.ts +11 -31
  303. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  304. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  305. package/src/elements/signal/key-ordering.test.ts +6 -26
  306. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  307. package/src/elements/signal/optional-emit.test.ts +6 -9
  308. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  309. package/src/elements/signal/orphan-messages.test.ts +4 -15
  310. package/src/elements/signal/reconcile.test.ts +2 -2
  311. package/src/elements/signal/runtime.ts +1 -1
  312. package/src/elements/signal/schema-emit.test.ts +4 -8
  313. package/src/elements/signal.test.ts +24 -49
  314. package/src/elements/signal.ts +9 -2
  315. package/src/elements/store/domain-ddl.test.ts +1 -1
  316. package/src/elements/store/live-http.test.ts +9 -4
  317. package/src/elements/store/prepare-row.test.ts +123 -0
  318. package/src/elements/store/resource.ts +43 -12
  319. package/src/elements/store/schema-decl.ts +117 -0
  320. package/src/elements/store/search-backfill.ts +205 -0
  321. package/src/elements/store/search-bind.ts +66 -0
  322. package/src/elements/store/search-bm25.ts +78 -0
  323. package/src/elements/store/search-ddl.ts +156 -0
  324. package/src/elements/store/search-embed-flow.ts +141 -0
  325. package/src/elements/store/search-errors.ts +34 -0
  326. package/src/elements/store/search-fusion.ts +112 -0
  327. package/src/elements/store/search-lsh.ts +179 -0
  328. package/src/elements/store/search-runtime.ts +300 -0
  329. package/src/elements/store/search.test.ts +144 -0
  330. package/src/elements/store/sql-session.test.ts +1 -0
  331. package/src/elements/store/sql-session.ts +83 -3
  332. package/src/elements/store/table.ts +23 -2
  333. package/src/elements/store/upsert-app.test.ts +1 -3
  334. package/src/elements/store.ts +50 -0
  335. package/src/full.ts +4 -2
  336. package/src/http.ts +4 -1
  337. package/src/i18n/catalogs/ar.ts +14 -6
  338. package/src/i18n/catalogs/en.ts +14 -6
  339. package/src/index.ts +6 -1
  340. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  341. package/src/kernel/adopt-routes.ts +9 -1
  342. package/src/kernel/app-auth.ts +5 -0
  343. package/src/kernel/app.ts +102 -9
  344. package/src/kernel/auto-cache.test.ts +6 -12
  345. package/src/kernel/auto-registry.test.ts +3 -3
  346. package/src/kernel/boot-bind/ai.test.ts +22 -19
  347. package/src/kernel/boot-bind/ai.ts +5 -43
  348. package/src/kernel/boot-bind/clock.ts +23 -5
  349. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  350. package/src/kernel/boot.test.ts +11 -6
  351. package/src/kernel/boot.ts +66 -16
  352. package/src/kernel/boundary-contract.ts +93 -0
  353. package/src/kernel/budget.test.ts +1 -1
  354. package/src/kernel/call.ts +89 -0
  355. package/src/kernel/capability.ts +6 -0
  356. package/src/kernel/client-descriptor.ts +123 -0
  357. package/src/kernel/clock-timezone.test.ts +80 -0
  358. package/src/kernel/correlation.test.ts +1 -1
  359. package/src/kernel/dry-run.ts +11 -8
  360. package/src/kernel/effects-stamping.test.ts +42 -9
  361. package/src/kernel/effects.test.ts +4 -2
  362. package/src/kernel/effects.ts +51 -9
  363. package/src/kernel/errors-channel.ts +17 -0
  364. package/src/kernel/errors-live-resume.ts +3 -2
  365. package/src/kernel/errors-tenant.ts +7 -4
  366. package/src/kernel/errors.registry-helpers.ts +96 -0
  367. package/src/kernel/errors.registry.test.ts +139 -25
  368. package/src/kernel/errors.ts +102 -23
  369. package/src/kernel/external-effects.test.ts +196 -0
  370. package/src/kernel/flow.test.ts +13 -4
  371. package/src/kernel/flow.ts +69 -71
  372. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  373. package/src/kernel/fx-dead-letters.test.ts +3 -3
  374. package/src/kernel/fx-fetch.ts +55 -0
  375. package/src/kernel/fx-live-stream.ts +2 -2
  376. package/src/kernel/fx-live.test.ts +8 -8
  377. package/src/kernel/fx.test.ts +17 -11
  378. package/src/kernel/fx.ts +180 -57
  379. package/src/kernel/horizontal-child.ts +1 -1
  380. package/src/kernel/http-query.test.ts +3 -6
  381. package/src/kernel/index.ts +13 -3
  382. package/src/kernel/instance-id.ts +1 -1
  383. package/src/kernel/instances.test.ts +40 -0
  384. package/src/kernel/instances.ts +47 -9
  385. package/src/kernel/live-http.test.ts +6 -7
  386. package/src/kernel/live-http.ts +6 -2
  387. package/src/kernel/live-resume.test.ts +1 -1
  388. package/src/kernel/mcp-tool.test.ts +3 -3
  389. package/src/kernel/on.ts +98 -4
  390. package/src/kernel/pipeline.test.ts +12 -15
  391. package/src/kernel/plugin-elements.test.ts +1 -1
  392. package/src/kernel/stamp-http.test.ts +3 -3
  393. package/src/kernel/triggers.ts +210 -95
  394. package/src/kernel-entry.ts +0 -1
  395. package/src/manifest/diff.ts +11 -1
  396. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  397. package/src/manifest/types.ts +46 -2
  398. package/src/mcp/docs-index.ts +3 -3
  399. package/src/mcp/docs-mcp.test.ts +2 -2
  400. package/src/mcp/docs-tools.ts +1 -1
  401. package/src/okid.test.ts +56 -0
  402. package/src/okid.ts +55 -11
  403. package/src/plugins/anonymous.ts +8 -4
  404. package/src/plugins/auth/shared.ts +27 -3
  405. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  406. package/src/plugins/auth-methods.security.test.ts +561 -23
  407. package/src/plugins/config-source.ts +1 -1
  408. package/src/plugins/csrf.test.ts +65 -0
  409. package/src/plugins/index.ts +2 -0
  410. package/src/plugins/magic-link.ts +36 -16
  411. package/src/plugins/oauth/shared.ts +3 -1
  412. package/src/plugins/oauth.ts +22 -14
  413. package/src/plugins/otp.ts +37 -21
  414. package/src/plugins/passkey-webauthn.ts +9 -6
  415. package/src/plugins/passkey.ts +98 -26
  416. package/src/plugins/pre-account-hijack.test.ts +223 -0
  417. package/src/plugins/two-factor.ts +466 -37
  418. package/src/plugins/username.ts +19 -7
  419. package/src/release/build-lib.ts +1 -0
  420. package/src/release/limits.ts +2 -2
  421. package/src/release/measure.ts +1 -1
  422. package/src/runs/collect.test.ts +0 -2
  423. package/src/runtime/json-code-block.test.ts +250 -20
  424. package/src/runtime/json-code-block.ts +1261 -41
  425. package/src/term.test.ts +1 -1
  426. package/src/test/create-test-app.test.ts +12 -12
  427. package/src/test/live-signals.test.ts +6 -6
  428. package/src/test/provisions.integration.test.ts +10 -14
  429. package/src/test/reset-element-registries.ts +1 -1
  430. package/src/test/tenant-isolation.test.ts +12 -6
  431. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  432. package/site/content/docs/deployment/docker.mdx +0 -227
  433. package/site/content/docs/deployment/index.mdx +0 -83
  434. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  435. package/site/content/docs/deployment/meta.json +0 -5
  436. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  437. package/site/content/docs/elements/ai.mdx +0 -385
  438. package/site/content/docs/elements/channel.mdx +0 -346
  439. package/site/content/docs/elements/clock.mdx +0 -244
  440. package/site/content/docs/elements/flow.mdx +0 -420
  441. package/site/content/docs/elements/gate.mdx +0 -436
  442. package/site/content/docs/elements/signal.mdx +0 -380
  443. package/site/content/docs/elements/store.mdx +0 -1099
  444. package/site/content/docs/elements/vault.mdx +0 -405
  445. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  446. package/site/content/docs/get-started/index.mdx +0 -43
  447. package/site/content/docs/get-started/installation.mdx +0 -220
  448. package/site/content/docs/get-started/introduction.mdx +0 -144
  449. package/site/content/docs/get-started/meta.json +0 -13
  450. package/site/content/docs/get-started/project-structure.mdx +0 -925
  451. package/site/content/docs/get-started/testing.mdx +0 -328
  452. package/site/content/docs/get-started/why.mdx +0 -114
  453. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  454. package/site/content/docs/recipes/ollama.mdx +0 -142
  455. package/site/content/docs/recipes/sglang.mdx +0 -105
  456. package/site/content/docs/recipes/vllm.mdx +0 -106
  457. package/site/content/docs/reference/cli.md +0 -232
  458. package/site/content/docs/reference/client.mdx +0 -469
  459. package/site/content/docs/reference/security.md +0 -74
  460. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  461. package/src/cli/ai-setup/recommend.test.ts +0 -225
  462. package/src/cli/ai-setup/recommend.ts +0 -225
  463. package/src/cli/dev-controls.test.ts +0 -122
  464. package/src/cli/dev-controls.ts +0 -164
  465. package/src/cli/tui/DevLive.tsx +0 -126
  466. package/src/console/ui-next/dist/assets/access-page-3-EFj-2G.js +0 -4
  467. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  468. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  469. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  470. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  471. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  472. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  473. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  474. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  475. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  476. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  477. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  478. package/src/console/ui-next/dist/assets/flows-page-cVFnA4HH.js +0 -1
  479. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  480. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  481. package/src/console/ui-next/dist/assets/index-CMIgUbD0.js +0 -66
  482. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  483. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  484. package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.js +0 -4
  485. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  486. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  487. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  488. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  489. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  490. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  491. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  492. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  493. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  494. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  495. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  496. package/src/console/ui-next/dist/assets/units-page-l8FeKfnP.js +0 -1
  497. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  498. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  499. package/src/console/ui-next/dist/assets/vault-page-CL-d_mLE.js +0 -2
  500. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  501. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  502. package/src/docker/ollama-pull.ts +0 -232
  503. package/src/docker/recipes/llama-cpp.ts +0 -298
  504. package/src/docker/recipes/ollama.ts +0 -44
  505. package/src/docker/recipes/sglang.ts +0 -55
  506. package/src/docker/recipes/vllm.ts +0 -44
  507. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  508. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  509. package/src/drivers/ai-ollama.ts +0 -389
  510. package/src/drivers/ollama.ts +0 -14
@@ -0,0 +1,559 @@
1
+ ---
2
+ title: "Routing"
3
+ description: "File-tree stamps for HTTP paths, Flow names, and client units from on(http.*, flow) under src/flows."
4
+ icon: "GitFork"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ HTTP routes are inferred from where a Flow file lives. Put `http.get()` in
9
+ `src/flows/notes/[id]/get.ts` and the compiler stamps `GET /notes/:id`, names the
10
+ Flow `notes.get`, and the client calls `api.notes.get({ id })`.
11
+
12
+ <Callout title="The one rule">
13
+ On a tree file, omit path and name: `on(http.get(), flow({ do }))`. The file
14
+ tree stamps both. Pass either only for control — barrels, a URL that must not
15
+ follow the folder, or a stable name for `fx.call`. Explicit always wins.
16
+ </Callout>
17
+
18
+ ## When to omit · when to pass
19
+
20
+ | | Omit (default) | Pass explicitly |
21
+ | ------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
22
+ | **HTTP path** | Tree file under `src/flows/<unit>/` — `http.get()`, `http.post()`, … | Barrel `index.ts`; a public URL that must not match the folder; `http.resource(path, ops)`; custom live SSE path |
23
+ | **Flow name** | Same tree file — `flow({ do })` stamps `unit.export` | Barrel (optional — export still stamps); stable name across moves; call-only Flow you `fx.call` by name |
24
+
25
+ **Consequence:** most app code looks like the create-oke template —
26
+ `http.get().public()` + `flow({ … })` — with no string path and no string name.
27
+
28
+ ## Smallest Example
29
+
30
+ <Steps>
31
+
32
+ <Step>
33
+ ### Place the file in the tree
34
+
35
+ `oke dev` / `oke build` regenerate `src/flows/generated.ts`. Import it before
36
+ `oke()` so pathless triggers receive their stamp:
37
+
38
+ ```typescript title="src/app.ts"
39
+ import "@/flows/generated";
40
+ import { oke } from "okengine";
41
+
42
+ export const app = oke({ name: "notes" });
43
+ ```
44
+
45
+ </Step>
46
+
47
+ <Step>
48
+ ### Use pathless `http.get()`
49
+
50
+ The tree stamps `GET /notes/:id`. `:id` merges into `in`. The export name is the
51
+ client method (`api.notes.get`):
52
+
53
+ ```typescript title="src/flows/notes/[id]/get.ts"
54
+ import { on, flow, http } from "okengine";
55
+ import { z } from "zod";
56
+
57
+ export const get = on(
58
+ http.get({
59
+ in: z.object({ id: z.string() }),
60
+ out: z.object({ id: z.string() }),
61
+ }),
62
+ flow({
63
+ do: async ({ id }) => ({ id }),
64
+ }),
65
+ );
66
+ ```
67
+
68
+ </Step>
69
+
70
+ <Step>
71
+ ### Call the endpoint
72
+
73
+ ```bash
74
+ curl -X GET http://localhost:6530/notes/n_1 -H "accept: application/json"
75
+ ```
76
+
77
+ Response:
78
+
79
+ ```json
80
+ {
81
+ "data": { "id": "n_1" },
82
+ "error": null
83
+ }
84
+ ```
85
+
86
+ </Step>
87
+
88
+ </Steps>
89
+
90
+ <Callout title="Method is not the filename">
91
+ `list.ts` does not become `GET` by itself. Reserved leaves only omit a URL segment. Bind
92
+ `http.get()`, `http.post()`, `http.patch()`, or `http.delete()` yourself — see [Reserved
93
+ Leaves](#reserved-leaves).
94
+ </Callout>
95
+
96
+ ## Progressive Patterns
97
+
98
+ From a pathless tree file to an explicit barrel, an action leaf, and a catch-all:
99
+
100
+ <Tabs items={["Tree", "Barrel", "Action", "Catch-all"]}>
101
+
102
+ <Tab value="Tree">
103
+
104
+ One file per route. Skip the path argument. The generated barrel calls
105
+ `stampHttpPath` / `stampFlowName` after import:
106
+
107
+ ```typescript title="src/flows/notes/list.ts"
108
+ import { on, flow, http } from "okengine";
109
+
110
+ export const list = on(
111
+ http.get(),
112
+ flow({
113
+ do: () => [],
114
+ }),
115
+ );
116
+ ```
117
+
118
+ Stamped to `GET /notes`, Flow `notes.list`, client `api.notes.list()`.
119
+
120
+ </Tab>
121
+
122
+ <Tab value="Barrel">
123
+
124
+ A unit that is **only** `index.ts` (plus skip-list files) is a barrel. The
125
+ generated file re-exports it **without** stamping — pass explicit paths:
126
+
127
+ ```typescript title="src/flows/notes/index.ts"
128
+ import { on, flow, http } from "okengine";
129
+ import { z } from "zod";
130
+
131
+ export const list = on(
132
+ http.get("/notes").public(),
133
+ flow("notes.list", {
134
+ do: () => [],
135
+ }),
136
+ );
137
+
138
+ export const create = on(
139
+ http.post("/notes", { in: z.object({ title: z.string().min(1) }) }),
140
+ flow("notes.create", {
141
+ do: async ({ title }, fx) => ({ id: fx.id(), title }),
142
+ }),
143
+ );
144
+ ```
145
+
146
+ Pathless `http.get()` inside a barrel stays unresolved and fails boot
147
+ (**OKE1040**).
148
+
149
+ </Tab>
150
+
151
+ <Tab value="Action">
152
+
153
+ A leaf that is not reserved **adds** a segment. `archive.ts` is
154
+ `POST /notes/:id/archive`, not `POST /notes/:id`:
155
+
156
+ ```typescript title="src/flows/notes/[id]/archive.ts"
157
+ import { on, flow, http } from "okengine";
158
+ import { z } from "zod";
159
+
160
+ export const archive = on(
161
+ http.post({ in: z.object({ id: z.string() }) }),
162
+ flow({
163
+ do: async ({ id }) => ({ id, archived: true }),
164
+ }),
165
+ );
166
+ ```
167
+
168
+ </Tab>
169
+
170
+ <Tab value="Catch-all">
171
+
172
+ `[...slug]` becomes `*` on the URL. The request param is always `"*"`, never
173
+ `slug`:
174
+
175
+ ```typescript title="src/flows/docs/[...slug]/get.ts"
176
+ import { on, flow, http } from "okengine";
177
+ import { z } from "zod";
178
+
179
+ export const get = on(
180
+ http.get({ in: z.object({ "*": z.string() }) }).public(),
181
+ flow({
182
+ do: async (input) => ({ path: input["*"] }),
183
+ }),
184
+ );
185
+ ```
186
+
187
+ ```bash
188
+ curl -X GET http://localhost:6530/docs/getting-started/install \
189
+ -H "accept: application/json"
190
+ ```
191
+
192
+ `do` receives `{ "*": "getting-started/install" }`. Call
193
+ `api.docs.get({ "*": "a/b/c" })` — not `{ slug }`.
194
+
195
+ </Tab>
196
+
197
+ </Tabs>
198
+
199
+ ## Convention Reference
200
+
201
+ | Convention | File | Stamped route | Client |
202
+ | ------------- | --------------------------------------- | ------------------------- | ------------------------------ |
203
+ | Dynamic param | `notes/[id]/get.ts` + `http.get()` | `GET /notes/:id` | `api.notes.get({ id })` |
204
+ | Reserved leaf | `notes/list.ts` + `http.get()` | `GET /notes` | `api.notes.list()` |
205
+ | Action leaf | `notes/[id]/archive.ts` + `http.post()` | `POST /notes/:id/archive` | `api.notes.archive({ id })` |
206
+ | Catch-all | `docs/[...slug]/get.ts` + `http.get()` | `GET /docs/*` | `api.docs.get({ "*": "a/b" })` |
207
+ | Route group | `notes/(ops)/archive.ts` | `/notes/archive` | `api.notes.archive` |
208
+ | Root unit | `main/health.ts` + `http.get()` | `GET /health` | `api.main.health()` |
209
+ | Folder root | `main/route.ts` + `http.get()` | `GET /` | `api.main.root()` |
210
+
211
+ ## Units
212
+
213
+ The first folder under `src/flows/` is the **client unit**. Nested folders and
214
+ the leaf file build the URL. The `export const` name is the method on that unit.
215
+
216
+ ```text
217
+ src/flows/
218
+ ├── notes/ # Unit: notes → api.notes.*
219
+ │ ├── list.ts # GET /notes (reserved leaf)
220
+ │ ├── create.ts # POST /notes (reserved leaf)
221
+ │ ├── shapes.ts # skipped (not a route)
222
+ │ └── [id]/
223
+ │ ├── get.ts # GET /notes/:id
224
+ │ └── archive.ts # POST /notes/:id/archive
225
+ ├── billing/
226
+ │ └── (checkout)/ # omitted from the URL
227
+ │ └── charge.ts # POST /billing/charge (if http.post())
228
+ └── main/ # Unit: main — prefix omitted from the URL
229
+ ├── health.ts # GET /health
230
+ └── route.ts # GET /
231
+ ```
232
+
233
+ A file sitting directly in `src/flows/` (no unit folder) is not a route.
234
+
235
+ Unit folder names must be valid JS identifiers (`notes`, `main`, `_` allowed
236
+ inside; `my-notes` is skipped). Folders starting with `_`, `[`, or `(` are not
237
+ units.
238
+
239
+ **Consequence:** `export const getNote` from `get.ts` is `api.notes.getNote`, not
240
+ `api.notes.get`. Match the export to the name you want on the client.
241
+
242
+ ## Path Conventions
243
+
244
+ **Default — pathless.** Omit the path so `generated.ts` stamps the URL from disk:
245
+
246
+ ```typescript
247
+ http.get(); // pending until stampHttpPath runs
248
+ ```
249
+
250
+ **Control — explicit path.** Pass the URL template when the folder should not
251
+ own the route (barrel, public API shape, resource mount). The tree never
252
+ overwrites an explicit path:
253
+
254
+ ```typescript
255
+ http.get("/organizations/:orgId/members/:memberId");
256
+ ```
257
+
258
+ Path params, query string, and JSON body still merge into one object checked by
259
+ `in` — same order as [HTTP · Request Parsing](/docs/elements/flow/http#request-parsing).
260
+
261
+ ### Dynamic parameters
262
+
263
+ `[id]` → `:id`. The folder name is the param key. Declare the same key on `in`:
264
+
265
+ ```typescript title="src/flows/orgs/[orgId]/members/[memberId]/get.ts"
266
+ import { on, flow, http } from "okengine";
267
+ import { z } from "zod";
268
+
269
+ export const get = on(
270
+ http.get({ in: z.object({ orgId: z.string(), memberId: z.string() }) }),
271
+ flow({
272
+ do: async ({ orgId, memberId }) => ({ orgId, memberId }),
273
+ }),
274
+ );
275
+ ```
276
+
277
+ Stamped to `GET /orgs/:orgId/members/:memberId`.
278
+
279
+ ### Catch-alls
280
+
281
+ `[...slug]` → `*` (greedy rest). Optional `[[...slug]]` is **not** supported —
282
+ generate fails with `Optional catch-all "[[...slug]]" is not supported — use [...slug] (param is "*").`
283
+
284
+ A route that includes `*` selects the Trie matcher automatically (the compiled
285
+ RegExp matcher cannot express wildcards).
286
+
287
+ ### Route groups
288
+
289
+ A folder `(ops)` is omitted from the URL. Use it to group files without adding a
290
+ segment:
291
+
292
+ ```text
293
+ src/flows/notes/(ops)/archive.ts → /notes/archive
294
+ ```
295
+
296
+ `(ops)` never enters the Flow name either (`notes.archive`).
297
+
298
+ ### The `main` unit
299
+
300
+ `main` is omitted from the URL prefix. Flow names still use `main.`:
301
+
302
+ | File | URL | Flow name |
303
+ | ---------------- | ------------- | -------------------------------------- |
304
+ | `main/health.ts` | `/health` | `main.health` |
305
+ | `main/route.ts` | `/` | `main.root` (from `export const root`) |
306
+ | `main/index.ts` | `/` (extract) | barrel — pass `http.get("/")` |
307
+
308
+ ### Skip list
309
+
310
+ These files are never routes (walk skips them; path inference returns nothing):
311
+
312
+ | Pattern | Why |
313
+ | --------------------------- | ------------------------------------------------ |
314
+ | `generated.ts` | Adopt barrel (`oke dev` / `oke build` writes it) |
315
+ | `shapes.ts` | Shared Zod / contracts |
316
+ | `signals.ts` | Signal declarations |
317
+ | `*.test.ts` / `*.test.tsx` | Tests |
318
+ | `_` prefix (file or folder) | Private helpers (`notes/_lib/util.ts`) |
319
+
320
+ Skip-list files may sit next to tree routes. They do **not** turn a tree into a
321
+ barrel.
322
+
323
+ ## Reserved Leaves
324
+
325
+ To avoid `/notes/get` and `/orders/list`, these filenames add **no** URL
326
+ segment — the same five CRUD names as `http.resource`, plus folder roots:
327
+
328
+ | Leaf | Typical trigger | Example file | Stamped path |
329
+ | -------- | --------------- | ----------------------------------- | --------------- |
330
+ | `list` | `http.get()` | `notes/list.ts` | `/notes` |
331
+ | `create` | `http.post()` | `notes/create.ts` | `/notes` |
332
+ | `get` | `http.get()` | `notes/[id]/get.ts` | `/notes/:id` |
333
+ | `update` | `http.patch()` | `notes/[id]/update.ts` | `/notes/:id` |
334
+ | `remove` | `http.delete()` | `notes/[id]/remove.ts` | `/notes/:id` |
335
+ | `index` | _(barrel only)_ | `notes/index.ts` | `/notes` |
336
+ | `route` | any | `notes/route.ts` or `main/route.ts` | `/notes` or `/` |
337
+
338
+ Any other leaf **is** a segment: `query.ts` → `/notes/query`.
339
+
340
+ In a tree unit, do **not** add `index.ts` beside other route files — that is a
341
+ generate error. Use `route.ts` (or `list.ts` / `create.ts`) for the collection
342
+ root.
343
+
344
+ ## Barrel vs Tree
345
+
346
+ `oke dev` / `oke build` scans each `src/flows/<unit>/` folder and writes
347
+ `generated.ts`. Two shapes, never mixed:
348
+
349
+ <Tabs items={["Tree", "Barrel", "App entry"]}>
350
+
351
+ <Tab value="Tree">
352
+
353
+ `[param]` folders, `(group)` folders, or extra route files. The barrel imports
354
+ each file and stamps path + name:
355
+
356
+ ```typescript
357
+ const notes = {
358
+ get: stampHttpPath(stampFlowName(notes_$id$_get.get, "notes.get"), "/notes/:id"),
359
+ list: stampHttpPath(stampFlowName(notes_list.list, "notes.list"), "/notes"),
360
+ };
361
+ export { notes };
362
+ registerFlowUnits({ notes });
363
+ ```
364
+
365
+ `oke()` drains `registerFlowUnits` into `$routes`. `.adopt({ notes })` is
366
+ optional and additive.
367
+
368
+ </Tab>
369
+
370
+ <Tab value="Barrel">
371
+
372
+ Only `index.ts` (+ skip-list). Re-export, no stamp:
373
+
374
+ ```typescript
375
+ import * as notes from "./notes/index.ts";
376
+ export { notes };
377
+ registerFlowUnits({ notes });
378
+ ```
379
+
380
+ Declare `http.get("/notes")` and `flow("notes.list", {…})` (or rely on adopt to
381
+ stamp the name from the export). Pathless HTTP fails **OKE1040**.
382
+
383
+ </Tab>
384
+
385
+ <Tab value="App entry">
386
+
387
+ ```typescript title="src/app.ts"
388
+ import "@/flows/generated";
389
+ import { oke } from "okengine";
390
+
391
+ export const app = oke({ name: "notes" });
392
+ export type App = typeof app;
393
+ ```
394
+
395
+ Do not edit `generated.ts` by hand. Adding a unit folder without regenerating
396
+ leaves a stale barrel — **OKE1030** in prod / `oke dev` with Compose.
397
+
398
+ </Tab>
399
+
400
+ </Tabs>
401
+
402
+ <Accordions>
403
+
404
+ <Accordion title="Mixed barrel + tree">
405
+ `index.ts` plus `[id]/get.ts` (or any other route file) throws at generate:
406
+
407
+ ```text
408
+ Unit "notes" mixes a barrel index.ts with tree route files. Use only index.ts (barrel), or move the collection path to route.ts and keep [id]/ beside it.
409
+ ```
410
+
411
+ Fix: delete `index.ts` and use `list.ts` / `route.ts`, or fold every route into
412
+ `index.ts` with explicit paths.
413
+
414
+ </Accordion>
415
+
416
+ <Accordion title="Export collisions">
417
+ Two files in the same unit cannot share an `export const` name:
418
+
419
+ ```text
420
+ Unit "notes" exports "get" from both list.ts and route.ts.
421
+ ```
422
+
423
+ Rename one export. The client method is the export name, not the filename.
424
+
425
+ </Accordion>
426
+
427
+ <Accordion title="Unit-prefix drift">
428
+ `flow("tasks.get", {…})` living under `src/flows/notes/` throws:
429
+
430
+ ```text
431
+ flow("tasks.…") in notes/get.ts does not match the folder "notes".
432
+ ```
433
+
434
+ Use `flow("notes.get", {…})`, a nameless `flow({ do })` (stamped `notes.get`
435
+ from the export), or move the file.
436
+
437
+ </Accordion>
438
+
439
+ </Accordions>
440
+
441
+ ## Names
442
+
443
+ Three names, one file:
444
+
445
+ | Surface | Source | Example |
446
+ | --------- | ------------------------------------------------------------------- | ----------------------- |
447
+ | HTTP path | File tree (default) or explicit `http.get("/x")` | `/notes/:id` |
448
+ | Flow name | `unit.export` from `flow({ do })` (default), or `flow("notes.get")` | `notes.get` |
449
+ | Client | Unit folder + `export const` | `api.notes.get({ id })` |
450
+
451
+ Nameless `flow({ do })` is the tree default — same rule as pathless HTTP. Pass
452
+ `flow("notes.get")` only for control (stable name, barrel, or matching unit
453
+ prefix). Wrong-unit prefixes fail generate.
454
+
455
+ Non-HTTP files still join the unit. A signal consumer in `notes/on-created.ts`
456
+ is `api.notes.onCreated` over RPC (`POST /_oke/notes/onCreated`), not HTTP.
457
+
458
+ HTTP flows that remain nameless after adopt fail **OKE1045**.
459
+
460
+ ## Runtime Matching
461
+
462
+ All adopted HTTP bindings go into one matcher. Wrong method on a known path is
463
+ **405** with `Allow`. No match is a bare **404** `Not Found`.
464
+
465
+ | `oke({ router })` | Default | What it does |
466
+ | ----------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
467
+ | `"default"` | yes | Compiled RegExp (O(1) static map + per-bucket regex for `:id`). Falls back to Trie when a path includes `*` |
468
+ | `"edge"` | | Linear scan, then Trie. No RegExp compile — cold-start / isolates |
469
+
470
+ p99 match stays under **1 ms** on the compiled matcher. You do not pick buckets
471
+ by hand — a catch-all in the table selects Trie for the whole app.
472
+
473
+ Duplicate `METHOD + path` fails boot (**OKE1041**), including a resource mount
474
+ plus a handwritten `http.get("/notes")`.
475
+
476
+ ## Troubleshooting
477
+
478
+ <Accordions>
479
+
480
+ <Accordion title="404 Not Found — route missing">
481
+ No Flow is bound to that method + path. Check the explicit path, or for pathless routes the
482
+ file-tree stamp (`notes/[id]/get.ts` → `GET /notes/:id`). A bare `404` with body `Not Found` means
483
+ the router found no match.
484
+ </Accordion>
485
+
486
+ <Accordion title="405 Method Not Allowed on valid route">
487
+ The path exists but has not been bound to the requested verb. `Allow` lists the methods that are.
488
+ `list.ts` with `http.get()` is GET-only — POST that URL is 405, not a missing file.
489
+ </Accordion>
490
+
491
+ <Accordion title="OKE1040 — pathless trigger never stamped">
492
+ Cause: `Flow "{flow}" bound {method} with no path — the file-tree stamp never ran.` Import
493
+ `@/flows/generated`, run `oke dev` / `oke build`, or pass `http.get("/…")`. Barrels do not stamp —
494
+ they need the explicit path.
495
+ </Accordion>
496
+
497
+ <Accordion title="OKE1030 — adopt barrel stale">
498
+ Cause: `src/flows/{unit} exists on disk but adopted no flows — the .adopt() barrel is stale.` Run
499
+ `oke dev` or `oke build` after adding a unit folder. Prod and Compose `oke dev` refuse to boot
500
+ this way.
501
+ </Accordion>
502
+
503
+ <Accordion title="OKE1041 — method + path bound twice">
504
+ Cause: `{method} {path} is bound twice (flow "{flow}").` Two tree files stamped the same verb +
505
+ path (`list.ts` and `route.ts` both `http.get()`), or a resource mount plus a handwritten route.
506
+ Drop one binding.
507
+ </Accordion>
508
+
509
+ <Accordion title="OKE1045 — HTTP flow unnamed">
510
+ Cause: `An HTTP flow on {method} {path} has no name.`
511
+ Use `flow("unit.export", {…})` or `export const` from a `src/flows/<unit>/`
512
+ file so the tree can stamp `unit.export`. `export default` is not picked up.
513
+ </Accordion>
514
+
515
+ <Accordion title="422 — path param missing from in">
516
+ `[id]` stamps `:id`. `in` must declare `id` (same key). A schema that expects `userId` while the
517
+ path is `:id` fails validation before `do`.
518
+ </Accordion>
519
+
520
+ <Accordion title="Catch-all input is empty / wrong key">
521
+ `[...slug]` does not bind `slug`. The router param is `"*"`. Declare
522
+ `in: z.object({ "*": z.string() })` and read `input["*"]`. Optional
523
+ `[[...slug]]` is rejected at generate.
524
+ </Accordion>
525
+
526
+ <Accordion title="Unit mixes index.ts with tree files">
527
+ Generate: `Unit "…" mixes a barrel index.ts with tree route files.` Use only `index.ts` (explicit
528
+ paths), or move the collection path to `route.ts` and keep `[id]/` beside it.
529
+ </Accordion>
530
+
531
+ </Accordions>
532
+
533
+ ## Learn more
534
+
535
+ - [HTTP](/docs/elements/flow/http) — verbs, envelopes, `http.resource`, live SSE
536
+ - [Client](/docs/client/calling) — `api.notes.get`, REST vs RPC, `$routes`
537
+ - [Errors](/docs/reference/errors) — OKE1040 · OKE1030 · OKE1041 · OKE1045
538
+ - [The Model](/docs/understand/the-model) — derived routes, no hand-written table
539
+ - [Gate](/docs/elements/gate) — `.gate(...)` / `.public()` on the same trigger
540
+
541
+ ## Next
542
+
543
+ <Cards>
544
+ <Card
545
+ title="HTTP"
546
+ description="REST verbs, RFC 10008 QUERY, CRUD mounts, and live SSE on Flow."
547
+ href="/docs/elements/flow/http"
548
+ />
549
+ <Card
550
+ title="Client"
551
+ description="Typed caller — createClient, envelopes, REST from $routes."
552
+ href="/docs/client/calling"
553
+ />
554
+ <Card
555
+ title="Consumers"
556
+ description="Signal workers, named Clock jobs, and SQL CDC — one Flow species."
557
+ href="/docs/elements/flow/consumers"
558
+ />
559
+ </Cards>