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
@@ -181,6 +181,56 @@ export {
181
181
  } from "./store/files-policy.ts";
182
182
  export type { FileKeyWarning } from "./store/files-policy.ts";
183
183
 
184
+ export {
185
+ SearchConfigError,
186
+ SEARCH_LOW_CORPUS_WARN_N,
187
+ RRF_DEFAULT_K,
188
+ LSH_DEFAULT_K,
189
+ BM25_K1,
190
+ BM25_B,
191
+ } from "./store/search-errors.ts";
192
+ export { bm25fScore, tokenize, termFrequencies } from "./store/search-bm25.ts";
193
+ export {
194
+ generateHyperplanes,
195
+ hyperplaneSeed,
196
+ lshBucket,
197
+ lshBucketToSql,
198
+ lshBucketFromSql,
199
+ cosineSimilarity,
200
+ neighborBuckets,
201
+ serializePlanes,
202
+ deserializePlanes,
203
+ } from "./store/search-lsh.ts";
204
+ export { fuseRrf, fuseWeighted, fuseLists } from "./store/search-fusion.ts";
205
+ export type { FuseOptions, FuseStrategy, RankedHit } from "./store/search-fusion.ts";
206
+ export { runSqlSearch } from "./store/search-runtime.ts";
207
+ export type {
208
+ SqlSearchOptions,
209
+ SqlSearchResult,
210
+ SearchColumnMeta,
211
+ } from "./store/search-runtime.ts";
212
+ export {
213
+ searchDdlForTable,
214
+ ensureHyperplaneInserts,
215
+ embColumn,
216
+ lshColumn,
217
+ OKE_TSV_COL,
218
+ SEARCH_PG_MIN_MAJOR,
219
+ parsePgMajor,
220
+ } from "./store/search-ddl.ts";
221
+ export { runSearchBackfill } from "./store/search-backfill.ts";
222
+ export type { SearchBackfillOptions, SearchBackfillResult } from "./store/search-backfill.ts";
223
+ export {
224
+ searchEmbedFlowName,
225
+ tablesNeedingSearchEmbed,
226
+ applySearchEmbedCdc,
227
+ } from "./store/search-embed-flow.ts";
228
+ export { bindSearchEmbedFlows } from "./store/search-bind.ts";
229
+ export type {
230
+ SearchableOptions,
231
+ EmbedFieldOptions,
232
+ ColumnSearchDecl,
233
+ } from "./store/schema-decl.ts";
184
234
  export {
185
235
  createFilesImagePipeline,
186
236
  putImageToBucket,
package/src/full.ts CHANGED
@@ -12,9 +12,7 @@ export {
12
12
  on,
13
13
  flow,
14
14
  http,
15
- every,
16
15
  internal,
17
- table,
18
16
  fail,
19
17
  createFx,
20
18
  isFlow,
@@ -86,7 +84,11 @@ export {
86
84
  signal,
87
85
  createSignalRuntime,
88
86
  type SignalDecl,
87
+ type SignalLiveOptions,
88
+ type SignalNamespace,
89
89
  type SignalOptions,
90
+ type SignalRetention,
91
+ type SignalSharedOptions,
90
92
  type SignalRuntime,
91
93
  type DeadLetter,
92
94
  type SignalFailureReason,
package/src/http.ts CHANGED
@@ -18,7 +18,10 @@
18
18
 
19
19
  export { on, listBindings, resetBindings, type Binding } from "./kernel/on.ts";
20
20
  export { flow, isFlow, type FlowDef } from "./kernel/flow.ts";
21
- export { http, every, internal } from "./kernel/triggers.ts";
21
+ export { call } from "./kernel/call.ts";
22
+ export { http, internal } from "./kernel/triggers.ts";
23
+ export type { BoundaryContract } from "./kernel/boundary-contract.ts";
24
+ export { clock } from "./elements/clock/declare.ts";
22
25
  export { gate, GATE_PUBLIC_NAME } from "./elements/gate/declare.ts";
23
26
  export { fail, type FlowFailure } from "./kernel/errors.ts";
24
27
  export { isFlowFailure } from "./kernel/hooks.ts";
@@ -32,27 +32,35 @@ export const builtinAr = {
32
32
  cause: 'التدفق "{flow}" يستدعي التدفق "{resource}" دون الإعلان عنه.',
33
33
  fix: 'أضف "{resource}" إلى effects.calls لهذا التدفق.',
34
34
  },
35
- "1042": {
35
+ "1008": {
36
+ cause: 'التدفق "{flow}" يجلب "{resource}" دون الإعلان عنه.',
37
+ fix: 'أضف "{resource}" إلى effects.fetches لهذا التدفق.',
38
+ },
39
+ "1009": {
40
+ cause: 'التدفق "{flow}" يضمّن عبر "{resource}" دون الإعلان عنه.',
41
+ fix: 'أضف "{resource}" إلى effects.embeds لهذا التدفق.',
42
+ },
43
+ "1240": {
36
44
  cause: 'التدفق "{flow}" يُصدِر الإشارة "{resource}" بلا مشترك.',
37
45
  fix: "أضف on({resource}, …) أو عيّن الإشارة '{'optional: true'}'.",
38
46
  },
39
- "1014": {
47
+ "1210": {
40
48
  cause: 'مؤشر البث "{afterId}" ليس على شريط "{signal}".',
41
49
  fix: "أعد الاتصال بدون Last-Event-ID لإعادة تشغيل الشريط المتبقي.",
42
50
  },
43
- "1015": {
51
+ "1810": {
44
52
  cause: "هذه العملية تحتاج مستأجراً، ولم يُحدَّد مستأجر لهذا الطلب.",
45
53
  fix: "استدعِ fx.auth.switchTenant(id) أو أرسل مطالبة tid موقّعة أو رأس المستأجر.",
46
54
  },
47
- "1016": {
55
+ "1820": {
48
56
  cause: 'المتصل ليس عضواً في المستأجر "{tenant}".',
49
57
  fix: "اختر مستأجراً من fx.auth.listTenants() أو أضف المستخدم كعضو.",
50
58
  },
51
- "1017": {
59
+ "1830": {
52
60
  cause: 'نطاق دور المستأجر "{scope}" ليس نطاقاً تطبيقياً معلناً.',
53
61
  fix: "استخدم اسماً من كتالوج البيان لهذا التطبيق (وليس console:*).",
54
62
  },
55
- "1101": {
63
+ "1110": {
56
64
  cause: "جدول النطاق غير موجود — لم تُطبَّق الترحيلات.",
57
65
  fix: "شغّل `oke db migrate` على هذه البيئة.",
58
66
  },
@@ -32,27 +32,35 @@ export const builtinEn = {
32
32
  cause: 'Flow "{flow}" calls "{resource}" without declaring it.',
33
33
  fix: "Add \"{resource}\" to this flow''s effects.calls.",
34
34
  },
35
- "1042": {
35
+ "1008": {
36
+ cause: 'Flow "{flow}" fetches "{resource}" without declaring it.',
37
+ fix: "Add \"{resource}\" to this flow''s effects.fetches.",
38
+ },
39
+ "1009": {
40
+ cause: 'Flow "{flow}" embeds with "{resource}" without declaring it.',
41
+ fix: "Add \"{resource}\" to this flow''s effects.embeds.",
42
+ },
43
+ "1240": {
36
44
  cause: 'Flow "{flow}" emits signal "{resource}" with no subscriber.',
37
45
  fix: "Add on({resource}, …) or mark the signal '{'optional: true'}'.",
38
46
  },
39
- "1014": {
47
+ "1210": {
40
48
  cause: 'Live cursor "{afterId}" is not on the tape for "{signal}".',
41
49
  fix: "Reconnect without Last-Event-ID to replay the remaining tape.",
42
50
  },
43
- "1015": {
51
+ "1810": {
44
52
  cause: "This operation needs a tenant, but none is resolved for this request.",
45
53
  fix: "Call fx.auth.switchTenant(id), send a signed tid claim, or pass the tenant header.",
46
54
  },
47
- "1016": {
55
+ "1820": {
48
56
  cause: 'The caller is not a member of tenant "{tenant}".',
49
57
  fix: "Pick a tenant from fx.auth.listTenants() or add the user as a member.",
50
58
  },
51
- "1017": {
59
+ "1830": {
52
60
  cause: 'Tenant role scope "{scope}" is not a declared application scope.',
53
61
  fix: "Use a name from this app's Manifest catalog (never console:*).",
54
62
  },
55
- "1101": {
63
+ "1110": {
56
64
  cause: "domain table not found — migrations have not been applied.",
57
65
  fix: "run `oke db migrate` against this environment.",
58
66
  },
package/src/index.ts CHANGED
@@ -24,7 +24,9 @@ export {
24
24
  } from "./kernel/app.ts";
25
25
  export { on, type Binding } from "./kernel/on.ts";
26
26
  export { flow, isFlow, type FlowDef } from "./kernel/flow.ts";
27
- export { http, every, internal, table, mcp } from "./kernel/triggers.ts";
27
+ export { call } from "./kernel/call.ts";
28
+ export { http, internal, mcp } from "./kernel/triggers.ts";
29
+ export type { BoundaryContract } from "./kernel/boundary-contract.ts";
28
30
  export { registerFlowUnits } from "./kernel/flow-units.ts";
29
31
  export { stampFlowName, stampHttpPath } from "./kernel/stamp-http.ts";
30
32
  export { fail, type FlowFailure, type FlowErrorValue } from "./kernel/errors.ts";
@@ -82,8 +84,11 @@ export {
82
84
  signal,
83
85
  createSignalRuntime,
84
86
  type SignalDecl,
87
+ type SignalLiveOptions,
88
+ type SignalNamespace,
85
89
  type SignalOptions,
86
90
  type SignalRetention,
91
+ type SignalSharedOptions,
87
92
  type SignalRuntime,
88
93
  type DeadLetter,
89
94
  type SignalFailureReason,
@@ -2,9 +2,9 @@
2
2
  * Boot-level proof: a `src/flows/<unit>` folder on disk with no adopted
3
3
  * flow under that unit — the stale/missing `.adopt()` barrel case.
4
4
  *
5
- * Mirrors `effects-stamping.test.ts`'s OKE1008 shape exactly: opt-in only
5
+ * Mirrors `effects-stamping.test.ts`'s OKE1020 shape exactly: opt-in only
6
6
  * via `rootDir`, `test` warns once (dev-loop stays unbroken),
7
- * `dev`+compose / `prod` hard-fail (`OKE1009`) — never a silently-incomplete route
7
+ * `dev`+compose / `prod` hard-fail (`OKE1030`) — never a silently-incomplete route
8
8
  * table in a deploy-shaped environment.
9
9
  */
10
10
 
@@ -46,11 +46,11 @@ describe("assertAdoptBarrelFresh — direct", () => {
46
46
  }
47
47
  });
48
48
 
49
- test("stale: unit on disk, zero adopted flows for it — dev+compose hard-fails OKE1009", async () => {
49
+ test("stale: unit on disk, zero adopted flows for it — dev+compose hard-fails OKE1030", async () => {
50
50
  const root = await mkdtemp(join(tmpdir(), "oke-adopt-fresh-"));
51
51
  try {
52
52
  await makeUnitDir(root, "notes");
53
- await expect(assertAdoptBarrelFresh([], "dev", root, true)).rejects.toThrow(/OKE1009/);
53
+ await expect(assertAdoptBarrelFresh([], "dev", root, true)).rejects.toThrow(/OKE1030/);
54
54
  } finally {
55
55
  await rm(root, { recursive: true, force: true });
56
56
  }
@@ -60,7 +60,7 @@ describe("assertAdoptBarrelFresh — direct", () => {
60
60
  const root = await mkdtemp(join(tmpdir(), "oke-adopt-fresh-"));
61
61
  try {
62
62
  await makeUnitDir(root, "notes");
63
- await expect(assertAdoptBarrelFresh([], "prod", root)).rejects.toThrow(/OKE1009/);
63
+ await expect(assertAdoptBarrelFresh([], "prod", root)).rejects.toThrow(/OKE1030/);
64
64
  } finally {
65
65
  await rm(root, { recursive: true, force: true });
66
66
  }
@@ -78,7 +78,7 @@ describe("assertAdoptBarrelFresh — direct", () => {
78
78
  });
79
79
 
80
80
  describe("boot-level: stale barrel through a real oke() boot", () => {
81
- test("dev+compose: real app.boot() hard-fails OKE1009 when a unit folder was never adopted", async () => {
81
+ test("dev+compose: real app.boot() hard-fails OKE1030 when a unit folder was never adopted", async () => {
82
82
  const root = await mkdtemp(join(tmpdir(), "oke-adopt-fresh-"));
83
83
  try {
84
84
  // "notes" exists on disk but this app only ever adopted "main" —
@@ -109,7 +109,7 @@ describe("boot-level: stale barrel through a real oke() boot", () => {
109
109
  },
110
110
  },
111
111
  }),
112
- ).rejects.toThrow(/OKE1009/);
112
+ ).rejects.toThrow(/OKE1030/);
113
113
  } finally {
114
114
  await rm(root, { recursive: true, force: true });
115
115
  }
@@ -186,6 +186,7 @@ export function runtimeRouteFromFlow(flowDef: AnyFlowDef): RuntimeFlowRoute {
186
186
  if (trigger?.kind !== "http") return {};
187
187
  const liveName = trigger.liveSignal?.name ?? flowDef.live;
188
188
  const gates = trigger.gates.map((g) => (typeof g === "string" ? g : g.name));
189
+ const streamOnly = flowDef.stream === true && liveName === undefined;
189
190
  return {
190
191
  method: trigger.method,
191
192
  path: trigger.path,
@@ -196,7 +197,14 @@ export function runtimeRouteFromFlow(flowDef: AnyFlowDef): RuntimeFlowRoute {
196
197
  matchKey: httpPathParams(trigger.path),
197
198
  ...(gates.length > 0 ? { gates } : {}),
198
199
  }
199
- : {}),
200
+ : streamOnly
201
+ ? {
202
+ stream: true as const,
203
+ ...(gates.length > 0 ? { gates } : {}),
204
+ }
205
+ : gates.length > 0
206
+ ? { gates }
207
+ : {}),
200
208
  };
201
209
  }
202
210
 
@@ -10,6 +10,8 @@ import { auth as authPlugin } from "../auth/plugin.ts";
10
10
  import { createAuthHttpBindings, type AuthHttpMaterialization } from "../auth/bindings.ts";
11
11
  import { tokenFromCookieHeader } from "../auth/cookies.ts";
12
12
  import { setActiveGateAuthContext } from "../auth/method-context.ts";
13
+ import { createPendingTwoFactorStore, createStepUpStore } from "../auth/two-factor-challenge.ts";
14
+ import { createVerificationStore } from "../auth/verification.ts";
13
15
  import type { ResolvedGateConfig } from "../elements/gate/config.ts";
14
16
  import {
15
17
  createAppAuthBinding,
@@ -85,6 +87,9 @@ export function wireGateAuth(options: WireGateAuthOptions): WiredGateAuth {
85
87
  passwordPolicy: auth.passwordPolicy,
86
88
  password: auth.password,
87
89
  breachCheck: auth.breachCheck,
90
+ pendingTwoFactor: createPendingTwoFactorStore(),
91
+ stepUp: createStepUpStore(),
92
+ twoFactorVerifications: createVerificationStore(),
88
93
  });
89
94
 
90
95
  return {
package/src/kernel/app.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  type RoutesFromNamespace,
18
18
  type RuntimeRouteMap,
19
19
  } from "./adopt-routes.ts";
20
+ import { buildClientDescriptor } from "./client-descriptor.ts";
20
21
  import { liveExposureKey, liveGatesKey, liveMatchKeyFromPath } from "./live-http.ts";
21
22
  // `./boot.ts` pulls in every element + driver module (vault, store, signal,
22
23
  // clock, gate, channel, ai, runs) — a type-only import here keeps that whole
@@ -37,6 +38,7 @@ import {
37
38
  import { requirePackageModule } from "../shared/lazy-src.ts";
38
39
  import { lazyRequire } from "./lazy-require.ts";
39
40
  import type { DurableResult, RunDurableOptions } from "../elements/clock/durable.ts";
41
+ import { applyClockTimezoneDefaults } from "../elements/clock/declare.ts";
40
42
  import type { TemplateCatalog } from "../elements/channel/runtime.ts";
41
43
  import { parseAcceptLanguage } from "../elements/channel/locale.ts";
42
44
  import { runWithLocale } from "../i18n/locale-context.ts";
@@ -62,7 +64,8 @@ import {
62
64
  logDevRequest,
63
65
  shouldLogDevRequests,
64
66
  } from "../runtime/dev-request-log.ts";
65
- import { asBrowserJsonCodeBlock, httpNavGroups } from "../runtime/json-code-block.ts";
67
+ import { GATE_PUBLIC_NAME } from "../elements/gate/flatten.ts";
68
+ import type { JsonCodeAuth } from "../runtime/json-code-block.ts";
66
69
  import { resolveDurationMs } from "./elapsed.ts";
67
70
  import { fail, throwOke } from "./errors.ts";
68
71
  import { consumeRegisteredFlowUnits, type FlowUnitBag } from "./flow-units.ts";
@@ -131,7 +134,6 @@ import { isPendingHttpPath } from "./http-path-pending.ts";
131
134
  import { drainPendingResourceLiveMounts } from "./resource-live.ts";
132
135
  import type {
133
136
  CdcTrigger,
134
- EveryTrigger,
135
137
  HttpTrigger,
136
138
  InternalTrigger,
137
139
  SignalAsTrigger,
@@ -181,6 +183,15 @@ function loadDurable(): {
181
183
  return lazyRequire(import.meta.dir, ["clock", "durable"].join("-"));
182
184
  }
183
185
 
186
+ /**
187
+ * Browser JSON page helpers — loaded on `app.fetch` only.
188
+ * A static import pins the traces-language HTML/CSS graph on every Store-only
189
+ * `oke()` construction.
190
+ */
191
+ function loadJsonCodeBlock(): typeof import("../runtime/json-code-block.ts") {
192
+ return lazyRequire(`${import.meta.dir}/../runtime`, ["json", "code", "block"].join("-"));
193
+ }
194
+
184
195
  /** Options for {@link oke}. */
185
196
  export interface OkeOptions {
186
197
  /** Application name (Manifest `app`). */
@@ -265,6 +276,14 @@ export interface OkeOptions {
265
276
  readonly signals?: BootOptions["signals"];
266
277
  /** Named clock declarations. */
267
278
  readonly clocks?: BootOptions["clocks"];
279
+ /**
280
+ * Clock element defaults. `{ timezone: "Asia/Riyadh" }` applies to every
281
+ * `clock()` / helper that omits `timezone` (explicit per-clock wins).
282
+ * Prefer this over repeating `timezone` on each declaration.
283
+ */
284
+ readonly clock?: {
285
+ readonly timezone?: string;
286
+ };
268
287
  /** Store facet declarations to register. */
269
288
  readonly stores?: BootOptions["stores"];
270
289
  /**
@@ -275,8 +294,20 @@ export interface OkeOptions {
275
294
  * `store.schema.live(false)`. Default `false` — today's explicit-only
276
295
  * behavior, zero change to existing apps. Declaration ergonomics only;
277
296
  * never the runtime cost model.
297
+ *
298
+ * `{ search: { embed: { model, dims } } }` sets the project default for
299
+ * field `.embed()` so columns can write bare `.embed()` and inherit;
300
+ * per-field `{ model?, dims? }` still overrides.
278
301
  */
279
- readonly store?: { readonly live?: boolean };
302
+ readonly store?: {
303
+ readonly live?: boolean;
304
+ readonly search?: {
305
+ readonly embed?: {
306
+ readonly model: { readonly name: string } | string;
307
+ readonly dims: number;
308
+ };
309
+ };
310
+ };
280
311
  /** Channel runtime options. */
281
312
  readonly channel?: BootOptions["channel"];
282
313
  /** AI runtime options. */
@@ -838,7 +869,12 @@ export function oke(options: OkeOptions): OkeApp {
838
869
  const effectiveStores = mergeUnique(options.stores, registrySnapshot.stores);
839
870
  const effectiveSecrets = mergeUnique(options.secrets, registrySnapshot.secrets);
840
871
  const effectiveSignals = mergeUnique(options.signals, registrySnapshot.signals);
841
- const effectiveClocks = mergeUnique(options.clocks, registrySnapshot.clocks);
872
+ const mergedClocks = mergeUnique(options.clocks, registrySnapshot.clocks);
873
+ // Apply oke({ clock: { timezone } }) now; leave defaulted clocks intact when
874
+ // unset so bindClock can still honor defineConfig({ clock: { timezone } }).
875
+ const effectiveClocks = options.clock?.timezone
876
+ ? applyClockTimezoneDefaults(mergedClocks, options.clock.timezone)
877
+ : mergedClocks;
842
878
  const effectivePolicies = mergeUnique(options.gate?.policies, registrySnapshot.gates);
843
879
  /**
844
880
  * Fold registered `vault.env.required` names into the vault boot options so
@@ -954,6 +990,30 @@ export function oke(options: OkeOptions): OkeApp {
954
990
  }
955
991
  }
956
992
 
993
+ /** Once-per-app: system `_oke_search_embed_*` CDC bindings from Manifest. */
994
+ let searchEmbedFlowsBound = false;
995
+ /**
996
+ * Auto-register hybrid-search embed CDC flows when any `.embed()` column
997
+ * exists. Lazy-loads search-bind so edge graphs without search stay lean.
998
+ * Requires an explicit Manifest on `oke({ manifest })` / boot overrides —
999
+ * does not AoT-extract the project tree (that path is for capability stamping).
1000
+ *
1001
+ * @param manifest - Boot / options Manifest (optional)
1002
+ */
1003
+ async function ensureSearchEmbedFlows(
1004
+ manifest: BootOptions["manifest"] | undefined,
1005
+ ): Promise<void> {
1006
+ if (searchEmbedFlowsBound || !manifest) return;
1007
+ const { tablesNeedingSearchEmbed } = await import("../elements/store/search-embed-flow.ts");
1008
+ if (tablesNeedingSearchEmbed(manifest).length === 0) {
1009
+ searchEmbedFlowsBound = true;
1010
+ return;
1011
+ }
1012
+ const { bindSearchEmbedFlows } = await import("../elements/store/search-bind.ts");
1013
+ bindSearchEmbedFlows(adoptBinding, manifest);
1014
+ searchEmbedFlowsBound = true;
1015
+ }
1016
+
957
1017
  // Project-wide `store.live` default — drain deferred resource live mounts
958
1018
  // now that the flag is known. Off flag: pending state is discarded and the
959
1019
  // behavior is 100% today's explicit-only. On flag: every pending resource
@@ -1206,6 +1266,17 @@ export function oke(options: OkeOptions): OkeApp {
1206
1266
 
1207
1267
  const caps = pluginRegistry.capabilities();
1208
1268
  const pluginNames = new Set(Object.keys(caps));
1269
+
1270
+ // Soft-require csrf when gate.auth.cookies.enabled (cookie sessions need CSRF).
1271
+ if (gateConfig.auth?.cookies.enabled && !pluginNames.has("csrf")) {
1272
+ const msg =
1273
+ "gate.auth.cookies.enabled requires the csrf plugin — .plug(csrf({ allowNoHeader: false })) and cors with credentials when cross-origin";
1274
+ if (bootEnv === "prod") {
1275
+ throw new Error(msg);
1276
+ }
1277
+ console.warn(`[okengine] ${msg}`);
1278
+ }
1279
+
1209
1280
  const authGates = authMaterialization?.authGates ?? [];
1210
1281
  const baseGates = overrides?.gates ?? gateConfig.policies ?? [];
1211
1282
  const elementNeeds = resolveElementNeeds({
@@ -1290,6 +1361,7 @@ export function oke(options: OkeOptions): OkeApp {
1290
1361
  unguardedHttp,
1291
1362
  signals: [...baseSignals, ...pluginSignals],
1292
1363
  clocks: [...baseClocks, ...pluginClocks],
1364
+ clock: overrides?.clock ?? options.clock,
1293
1365
  stores: overrides?.stores ?? effectiveStores,
1294
1366
  channel: {
1295
1367
  ...(baseChannel ?? {}),
@@ -1347,6 +1419,9 @@ export function oke(options: OkeOptions): OkeApp {
1347
1419
  );
1348
1420
  }
1349
1421
  }
1422
+ // Built-in hybrid search — auto-register durable embed CDC flows when the
1423
+ // Manifest declares any `.embed()` column (writer flows stay embed-free).
1424
+ await ensureSearchEmbedFlows(overrides?.manifest ?? options.manifest);
1350
1425
  // otp() provider / app mode capability — fail loud at boot, never silent downgrade.
1351
1426
  if (result.channel) {
1352
1427
  const { assertOtpPluginCapability } = await import("../auth/otp-capability.ts");
@@ -2127,6 +2202,7 @@ export function oke(options: OkeOptions): OkeApp {
2127
2202
  let flowLabel: string | undefined;
2128
2203
  let runLabel: string | undefined;
2129
2204
  let cacheLabel: "hit" | "miss" | "none" | undefined;
2205
+ let authLabel: JsonCodeAuth | undefined;
2130
2206
  const url = new URL(request.url);
2131
2207
  const method = request.method.toUpperCase();
2132
2208
 
@@ -2146,13 +2222,15 @@ export function oke(options: OkeOptions): OkeApp {
2146
2222
  detail: await failureDetailFromResponse(response),
2147
2223
  });
2148
2224
  }
2149
- return asBrowserJsonCodeBlock(
2225
+ const jcb = loadJsonCodeBlock();
2226
+ return jcb.asBrowserJsonCodeBlock(
2150
2227
  request,
2151
2228
  response,
2152
2229
  options.name,
2153
- httpNavGroups(adopted, request),
2230
+ jcb.httpNavGroups(adopted, request),
2154
2231
  performance.now() - started,
2155
2232
  cacheLabel ?? "none",
2233
+ authLabel ?? { kind: "none" },
2156
2234
  );
2157
2235
  };
2158
2236
 
@@ -2175,8 +2253,9 @@ export function oke(options: OkeOptions): OkeApp {
2175
2253
  }
2176
2254
 
2177
2255
  if (method === "GET" && url.pathname === "/_oke/client.json") {
2256
+ const descriptor = buildClientDescriptor(routes, flowsByName);
2178
2257
  return respond(
2179
- new Response(JSON.stringify({ routes }), {
2258
+ new Response(JSON.stringify(descriptor), {
2180
2259
  headers: { "content-type": "application/json" },
2181
2260
  }),
2182
2261
  );
@@ -2207,6 +2286,11 @@ export function oke(options: OkeOptions): OkeApp {
2207
2286
  );
2208
2287
  runLabel = internalResult.runId;
2209
2288
  cacheLabel = internalResult.cache;
2289
+ authLabel = loadJsonCodeBlock().jsonCodeAuthFrom({
2290
+ userId: internalResult.fx.auth.userId,
2291
+ apiKeyId: internalResult.fx.auth.apiKeyId,
2292
+ operatorId: internalResult.fx.operator.id,
2293
+ });
2210
2294
  return respond(await encodeExecuteResult(internalResult));
2211
2295
  }
2212
2296
  }
@@ -2285,6 +2369,12 @@ export function oke(options: OkeOptions): OkeApp {
2285
2369
  });
2286
2370
  runLabel = result.runId;
2287
2371
  cacheLabel = result.cache;
2372
+ authLabel = loadJsonCodeBlock().jsonCodeAuthFrom({
2373
+ userId: result.fx.auth.userId,
2374
+ apiKeyId: result.fx.auth.apiKeyId,
2375
+ operatorId: result.fx.operator.id,
2376
+ publicGate: gateNamesOf(binding.trigger).includes(GATE_PUBLIC_NAME),
2377
+ });
2288
2378
 
2289
2379
  return respond(await encodeExecuteResult(result));
2290
2380
  },
@@ -2305,8 +2395,11 @@ export function oke(options: OkeOptions): OkeApp {
2305
2395
  async dispatchEvery(interval, extras) {
2306
2396
  const results: ExecuteResult[] = [];
2307
2397
  for (const b of adopted) {
2308
- if (b.trigger.kind === "every" && b.trigger.interval === interval) {
2309
- results.push(await execute(b.flow, undefined, b.trigger as EveryTrigger, extras));
2398
+ if (
2399
+ (b.trigger.kind === "clock" && b.trigger.name === interval) ||
2400
+ (b.trigger.kind === "every" && b.trigger.interval === interval)
2401
+ ) {
2402
+ results.push(await execute(b.flow, undefined, b.trigger, extras));
2310
2403
  }
2311
2404
  }
2312
2405
  return results;
@@ -44,9 +44,8 @@ describe("automatic tier-1 cache from effects", () => {
44
44
  const db = store.sql("app", { schema: { notes } });
45
45
  let lists = 0;
46
46
  const list = on(
47
- http.get("/notes").public(),
47
+ http.get("/notes", { out: z.array(NoteOut) }).public(),
48
48
  flow("notes.list", {
49
- out: z.array(NoteOut),
50
49
  effects: { reads: ["sql:notes"] },
51
50
  do: () => {
52
51
  lists += 1;
@@ -80,9 +79,8 @@ describe("automatic tier-1 cache from effects", () => {
80
79
  resetFlowSeq();
81
80
  const db = store.sql("app", { schema: { notes } });
82
81
  const list = on(
83
- http.get("/notes").public(),
82
+ http.get("/notes", { out: z.array(NoteOut) }).public(),
84
83
  flow("notes.list", {
85
- out: z.array(NoteOut),
86
84
  effects: { reads: ["sql:notes"] },
87
85
  do: () => [{ id: "n1", title: "Harbor" }],
88
86
  }),
@@ -146,9 +144,8 @@ describe("automatic tier-1 cache from effects", () => {
146
144
  const db = store.sql("app", { schema: { notes } });
147
145
  let lists = 0;
148
146
  const list = on(
149
- http.get("/notes").public(),
147
+ http.get("/notes", { out: z.array(NoteOut) }).public(),
150
148
  flow("notes.list", {
151
- out: z.array(NoteOut),
152
149
  do: async (_input, fx) => {
153
150
  lists += 1;
154
151
  const rows = await fx.store(db).select().from(notes);
@@ -201,9 +198,8 @@ describe("automatic tier-1 cache from effects", () => {
201
198
  }),
202
199
  );
203
200
  const create = on(
204
- http.post("/notes").public(),
201
+ http.post("/notes", { in: z.object({ title: z.string() }) }).public(),
205
202
  flow("notes.create", {
206
- in: z.object({ title: z.string() }),
207
203
  effects: { writes: ["sql:notes"] },
208
204
  do: (input) => ({ id: "n-new", title: input.title }),
209
205
  }),
@@ -231,9 +227,8 @@ describe("automatic tier-1 cache from effects", () => {
231
227
  const db = store.sql("app", { schema: { notes } });
232
228
  let lists = 0;
233
229
  const list = on(
234
- http.get("/notes").public(),
230
+ http.get("/notes", { out: z.array(NoteOut) }).public(),
235
231
  flow("notes.list", {
236
- out: z.array(NoteOut),
237
232
  do: async (_input, fx) => {
238
233
  lists += 1;
239
234
  const rows = await fx.store(db).select().from(notes);
@@ -242,9 +237,8 @@ describe("automatic tier-1 cache from effects", () => {
242
237
  }),
243
238
  );
244
239
  const create = on(
245
- http.post("/notes").public(),
240
+ http.post("/notes", { in: z.object({ title: z.string() }) }).public(),
246
241
  flow("notes.create", {
247
- in: z.object({ title: z.string() }),
248
242
  do: async (input, fx) => {
249
243
  const id = `n-${lists + 1}`;
250
244
  await fx.store(db).insert(notes).values({ id, title: input.title });
@@ -33,7 +33,7 @@ describe("oke() auto-registry — stores/secrets/signals/clocks/gates/channel.te
33
33
  const dbBefore = store.sql("before-app", { schema: {} });
34
34
  const filesBefore = store.files("before-uploads");
35
35
  const secretBefore = vault.secret("BEFORE_WEBHOOK_SECRET", { dev: "dev-secret-before" });
36
- const signalBefore = signal("before-note-created", { delivery: "once", optional: true });
36
+ const signalBefore = signal.once("before-note-created", { optional: true });
37
37
  const mailBefore = channel.email({ from: "Before <before@localhost>" });
38
38
  const templateBefore = mailBefore.template("before-note-created");
39
39
 
@@ -71,7 +71,7 @@ describe("oke() auto-registry — stores/secrets/signals/clocks/gates/channel.te
71
71
  store.sql("after-app", { schema: {} });
72
72
  store.files("after-uploads");
73
73
  const secretAfter = vault.secret("AFTER_WEBHOOK_SECRET", { dev: "dev-secret-after" });
74
- const signalAfter = signal("after-note-created", { delivery: "once", optional: true });
74
+ const signalAfter = signal.once("after-note-created", { optional: true });
75
75
  const mailAfter = channel.email({ from: "After <after@localhost>" });
76
76
  const templateAfter = mailAfter.template("after-note-created");
77
77
 
@@ -204,7 +204,7 @@ describe("oke() auto-registry — stores/secrets/signals/clocks/gates/channel.te
204
204
  test('registry: "consume" (default) drains stores/secrets/signals/channel.templates — a later app does not inherit them', async () => {
205
205
  store.sql("leak-app", { schema: {} });
206
206
  vault.secret("LEAK_SECRET", { dev: "dev-leak" });
207
- signal("leak-signal", { delivery: "once" });
207
+ signal.once("leak-signal");
208
208
  channel.email().template("leak-template");
209
209
 
210
210
  const appA = oke({