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
@@ -1,328 +0,0 @@
1
- ---
2
- title: Testing
3
- description: Write deterministic tests for your Flows with createTestApp — freeze the clock, mock AI, drain signals, and prove side effects.
4
- icon: FlaskConical
5
- ---
6
-
7
- `createTestApp` boots the **same app** you deploy, but with memory drivers and a
8
- frozen clock. You drive it through `t.api`, `t.auth`, `t.signals`, `t.clock`,
9
- and `t.channels` — every assertion is deterministic.
10
-
11
- <Callout title="The one rule">
12
- Boot the same `app` your server boots. Assert only through the harness surfaces (`t.api`,
13
- `t.auth`, `t.signals`, `t.clock`, `t.channels`, `t.ai`, `t.effects`) — never reach into internal
14
- runtimes.
15
- </Callout>
16
-
17
- ## Import
18
-
19
- The harness ships as a separate subpath so production bundles stay small:
20
-
21
- ```typescript title="tests/orders.test.ts"
22
- import { describe, expect, test } from "bun:test";
23
- import { createTestApp } from "okengine/testing"; // or "okengine/test"
24
- import { app } from "../src/app";
25
-
26
- test("orders flow", async () => {
27
- const t = await createTestApp(app);
28
- // ...
29
- await t.close();
30
- });
31
- ```
32
-
33
- Both `okengine/testing` and `okengine/test` are aliases. Use `okengine/testing`
34
- (→ `dist/testing.js`) for published packages and hoisted monorepos; `okengine/test`
35
- is the source-only path older starters use.
36
-
37
- ## Quick start
38
-
39
- <Steps>
40
-
41
- <Step>
42
- ### Adopt your Flows
43
-
44
- Every behavior on the app is reachable. No separate test database or server.
45
-
46
- ```typescript title="src/flows/orders/index.ts"
47
- import { on, flow, http } from "okengine";
48
- import { z } from "zod";
49
-
50
- export const create = on(
51
- http.post("/orders").gate(member),
52
- flow("orders.create", {
53
- in: z.object({ sku: z.string(), qty: z.number() }),
54
- out: z.object({ id: z.string() }),
55
- do: async (input, fx) => {
56
- const id = fx.id();
57
- await fx.emit(orderPlaced, { orderId: id, ...input });
58
- return { id };
59
- },
60
- }),
61
- );
62
- ```
63
-
64
- </Step>
65
-
66
- <Step>
67
- ### Boot the harness
68
-
69
- ```typescript title="tests/orders.test.ts"
70
- const t = await createTestApp(app, { gates: [member] });
71
- ```
72
-
73
- </Step>
74
-
75
- <Step>
76
- ### Login and call
77
-
78
- ```typescript
79
- const u = await t.auth.loginAs({ scopes: ["order:create"] });
80
- const { data, error } = await t.api.orders.create({ sku: "COFFEE", qty: 2 }, { as: u });
81
- expect(error).toBeNull();
82
- expect(data).toEqual({ id: expect.any(String) });
83
- ```
84
-
85
- </Step>
86
-
87
- <Step>
88
- ### Advance time and drain signals
89
-
90
- Signal handlers and Clocks are processed deterministically:
91
-
92
- ```typescript
93
- await t.signals.drain(); // run queued signal work
94
- await t.clock.advance("2m"); // tick scheduled Clocks forward
95
- expect(t.channels.sent()).toContainEqual(expect.objectContaining({ template: "order-confirmed" }));
96
- ```
97
-
98
- </Step>
99
-
100
- </Steps>
101
-
102
- ## Harness surface
103
-
104
- | Property | What it does |
105
- | ------------------------------------------- | -------------------------------------------------------------------------------------- |
106
- | `t.api.<unit>.<flow>(input, opts?)` | Invoke an adopted Flow directly with a `{ as }` principal and optional `{ tenant }` |
107
- | `t.auth.loginAs(options)` | Returns a verified `TestUser` with `id`, `scopes`, `verified`, and optional `tenantId` |
108
- | `t.clock.advance(by)` / `t.clock.now()` | Freeze and move the harness clock (used by durable sleeps and Clocks) |
109
- | `t.cron.run(name)` | Run a named Clock / `every()` interval now, still leader-elected |
110
- | `t.signals.drain()` | Drain the signal bus until idle (deterministic queued work) |
111
- | `t.signals.subscribeLive(signal, handlers)` | Subscribe to a `delivery: "live"` signal's event stream (deterministic) |
112
- | `t.signals.waitForLive(signal, predicate)` | Resolve once a live event matching `predicate` arrives |
113
- | `t.channels.sent()` | Receipts / inbox entries sent during the test |
114
- | `t.ai.mock(prompt, output)` | Register a canned mock response for a Prompt |
115
- | `t.ai.cost()` | Accumulated AI cost across `fx.ask` calls |
116
- | `t.effects.of(runId)` | Effect ledger for a recorded run (reads / writes / emits / sends) |
117
- | `t.runs()` | All wide events recorded during the test |
118
- | `t.close()` | Close booted element runtimes |
119
-
120
- ## Multi-tenancy & RLS
121
-
122
- With `gate.auth: { tenant: true }` you can test tenant isolation with real
123
- row-level security.
124
-
125
- ```typescript title="src/db/documents.ts"
126
- import { store, field } from "okengine";
127
-
128
- export const documents = store.schema.table(
129
- "documents",
130
- {
131
- id: field.text().primaryKey(),
132
- tenant_id: field.text().notNull(),
133
- title: field.text().notNull(),
134
- },
135
- [store.schema.policy.tenant("tenant_id", { for: "all" })],
136
- );
137
- ```
138
-
139
- Give each test user a tenant, and drive distinct tenants against the same
140
-
141
- Flow:
142
-
143
- ```typescript title="tests/tenant.test.ts"
144
- const t = await createTestApp(app, {
145
- gates: [member],
146
- boot: { config: { drivers: { store: { sql: { test: "pglite" } } } } },
147
- });
148
-
149
- const alice = await t.auth.loginAs({ id: "alice", tenantId: "acme" });
150
- const bob = await t.auth.loginAs({ id: "bob", tenantId: "globex" });
151
-
152
- await t.api.docs.create({ title: "Acme Roadmap" }, { as: alice });
153
- await t.api.docs.create({ title: "Globex Secrets" }, { as: bob });
154
-
155
- const acmeDocs = await t.api.docs.list(undefined, { as: alice });
156
- expect(acmeDocs.data).toHaveLength(1); // only Acme Roadmap
157
- ```
158
-
159
- Re-scope a single call to another tenant with `{ tenant }`, independent of the
160
- principal's own tenant:
161
-
162
- ```typescript
163
- const carol = await t.auth.loginAs({ id: "carol", tenantId: "acme" });
164
- const { data } = await t.api.docs.create(
165
- { title: "Globex Carol" },
166
- { as: carol, tenant: "globex" },
167
- );
168
- expect(data.tenantId).toBe("globex");
169
- ```
170
-
171
- RLS policies are row-level: tenant-scoped tables need `store.schema.policy.tenant`
172
- (or `store.schema.unscoped()` for genuinely global tables). Harness boots do not
173
- run migrations — in a real app `oke db push` installs those policies.
174
-
175
- ## Deterministic live signals
176
-
177
- Signals with `delivery: "live"` back client feeds and SSE streams. The harness
178
- exposes the retained event stream so you can assert both sides deterministically:
179
-
180
- ```typescript title="tests/live.test.ts"
181
- const orderStatus = signal("order-status", {
182
- delivery: "live",
183
- retention: { maxCount: 10 },
184
- });
185
-
186
- on(
187
- http.post("/orders/status").public(),
188
- flow("orders.updateStatus", {
189
- in: z.object({ orderId: z.string(), status: z.string() }),
190
- effects: { emits: ["order-status"] },
191
- do: async (input, fx) => {
192
- await fx.emit(orderStatus, input);
193
- return { ok: true };
194
- },
195
- }),
196
- );
197
- ```
198
-
199
- ```typescript
200
- const seen: Array<{ orderId: string; status: string }> = [];
201
-
202
- const unsubscribe = t.signals.subscribeLive(orderStatus, {
203
- onEvent: (event) => seen.push(event),
204
- });
205
-
206
- await t.api.orders.updateStatus({ orderId: "o1", status: "placed" });
207
- await t.signals.drain();
208
- expect(seen.map((e) => e.status)).toEqual(["placed"]);
209
-
210
- // Resolve a promise the moment a matching event arrives.
211
- const deliveredPromise = t.signals.waitForLive(
212
- orderStatus,
213
- (event) => event.status === "delivered",
214
- );
215
- await t.api.orders.updateStatus({ orderId: "o1", status: "delivered" });
216
- await t.signals.drain();
217
- const delivered = await deliveredPromise;
218
- expect(delivered.status).toBe("delivered");
219
-
220
- unsubscribe(); // no further events observed
221
- ```
222
-
223
- Call `t.signals.drain()` after each emit — live events are staged until the bus
224
- drains. `retention` caps the replayed tape (`maxCount` / `maxAge`); it is only
225
- valid on `delivery: "live"` signals.
226
-
227
- ## Time travel
228
-
229
- `t.clock` freezes time. `t.clock.advance("2m")` moves the clock forward and
230
- resumes any durable sleeps that become due. `t.cron.run("expire-stale")` runs a
231
- named Clock now:
232
-
233
- ```typescript
234
- await t.clock.advance("30s"); // durable sleeps resume
235
- await t.cron.run("expire-stale"); // named Clock fires
236
- expect(t.channels.sent()).toHaveLength(1); // side effect observed
237
- ```
238
-
239
- ## AI & channels
240
-
241
- `fx.ask` routes to a mock driver. Register canned outputs and read accumulated
242
- cost:
243
-
244
- ```typescript
245
- t.ai.mock(summarizePrompt, { title: "Mock summary" });
246
- const { data } = await t.api.posts.summarize({ postId: "p_1" }, { as: u });
247
- expect(data).toEqual({ title: "Mock summary" });
248
- expect(t.ai.cost()).toBe(0);
249
- ```
250
-
251
- Channels write to an inbox instead of a transport:
252
-
253
- ```typescript
254
- expect(t.channels.sent()).toContainEqual(
255
- expect.objectContaining({ template: "order-confirmed", to: u.id }),
256
- );
257
- ```
258
-
259
- ## Troubleshooting
260
-
261
- <Accordions>
262
-
263
- <Accordion title="createTestApp fails to boot — missing secrets or stores">
264
- The starter patches test drivers and fallback secrets on the app options. If
265
- your `oke({ ... })` references a Vault secret or Store that the template does
266
- not define, pass them explicitly:
267
-
268
- ```typescript
269
- await createTestApp(app, {
270
- secrets: [openAiKey],
271
- vaultSecrets: { OPENAI_KEY: "sk-test" },
272
- });
273
- ```
274
-
275
- </Accordion>
276
-
277
- <Accordion title="My live subscription never receives events">
278
- - Live events are staged until `t.signals.drain()` — await `drain()` after
279
- every emitting call.
280
- - Register `subscribeLive` / `waitForLive` **before** you emit.
281
- - A signal with a schema drops violating emits — assert `res.error`.
282
-
283
- </Accordion>
284
-
285
- <Accordion title="Cross-tenant reads return a stale cached row">
286
- Tier-1 read caching keys by flow, input, and user id — tenant is a row-level
287
- RLS scope, not a cache dimension. For reads under a `{ tenant }` override, use
288
- a distinct call principal (or write first) so the cache key differs.
289
-
290
- </Accordion>
291
-
292
- <Accordion title="PGlite RLS policies aren't applied in the harness">
293
- Test boots never run migrations — `oke db push` installs DDL and
294
- `store.schema.policy.tenant` policies in real apps.
295
-
296
- Assert real RLS by installing the policy + `oke.*` helpers on the booted
297
- primary connection (as the repo's `sql-rls-isolation.test.ts` does).
298
-
299
- </Accordion>
300
-
301
- </Accordions>
302
-
303
- ## Learn more
304
-
305
- - [Flow](/docs/elements/flow) — triggers, contracts, effects, and composition
306
- - [Store](/docs/elements/store) — SQL, KV, files, index, and RLS policies
307
- - [Signal](/docs/elements/signal) — delivery physics, retention, and live feeds
308
- - [Client](/docs/reference/client) — the typed client for real HTTP calls
309
-
310
- ## Next
311
-
312
- <Cards>
313
- <Card
314
- title="Project structure"
315
- description="Folders are the URL; unit plus export is the name."
316
- href="/docs/get-started/project-structure"
317
- />
318
- <Card
319
- title="Flow"
320
- description="Triggers, contracts, effects, and composition."
321
- href="/docs/elements/flow"
322
- />
323
- <Card
324
- title="Signal"
325
- description="Delivery physics, retention, and deterministic live feeds."
326
- href="/docs/elements/signal"
327
- />
328
- </Cards>
@@ -1,114 +0,0 @@
1
- ---
2
- title: Why OKE
3
- description: The problem of seams across independent backend tools, the insight, and the smaller model.
4
- source: docs/spec/unified-theory.md
5
- icon: Compass
6
- ---
7
-
8
- ## The Problem: The Seams You Own
9
-
10
- Modern backends accumulate many independently adopted systems: router, queue, cron, websockets, cache, secrets, mailer, AI wrappers, and observability.
11
-
12
- <Callout title="A note on the count">
13
- 'Forty' is a representative illustration of the number of backend concerns developers commonly
14
- assemble across modern stacks, not a literal census.
15
- </Callout>
16
-
17
- ```text
18
- many systems → many seams → many contracts → many mental models
19
- ```
20
-
21
- Every TypeScript backend works on day one. The bill arrives later in the seams:
22
-
23
- - **Cache that lies:** You update a writer, but forget the cache key in checkout.
24
- - **Secret that fails at 2am:** Deploy boots fine; the first charge fails because the env var was missed.
25
- - **Permission checks in the wrong place:** Auth logic scattered across handlers instead of verified at the trigger.
26
- - **The dashboard that doesn't know you:** Observability tools learn routes from traffic samples instead of the compiled model.
27
-
28
- ## The Insight: One Programming Model
29
-
30
- These concerns do not need to become separate programming concepts. They collapse into one closed set:
31
-
32
- ```text
33
- Many backend concerns → One programming model
34
- ```
35
-
36
- > **One law. Eight elements. One contract.**
37
-
38
- ## Wrong vs. Right Mental Model
39
-
40
- Understanding OKE begins by rejecting the conventional feature-pile model:
41
-
42
- | ❌ Wrong Mental Model (Feature Bundle) | ✅ OKEngine Model (Unified Primitives) |
43
- | -------------------------------------- | -------------------------------------- |
44
- | Router + Queue + Cron + Auth + ORM | `on(Trigger) → Flow` (One species) |
45
- | Separate mental model per tool | Eight closed semantic elements |
46
- | Ad-hoc side effects everywhere | Single door to the world: `fx` |
47
- | Hand-maintained glue & OpenAPI | Compiled Manifest contract |
48
- | Unchecked runtime drift | Derived, inspectable surfaces |
49
-
50
- The difference is not how many features OKE has. It is how few concepts you need to understand.
51
-
52
- ## The Law and the `fx` Rule
53
-
54
- Every backend behavior is a Flow:
55
-
56
- ```typescript
57
- import { on, flow, http } from "okengine/http";
58
-
59
- export const health = on(http.get().public(), flow({ do: () => ({ ok: true }) }));
60
- ```
61
-
62
- **All world access goes through `fx`.** A Flow that calls `fetch` directly, imports `node:fs`, or uses `Date.now()` is a defect.
63
-
64
- ```text
65
- Flow → fx → observable Effects → Compiler → Manifest → Surfaces
66
- ```
67
-
68
- Because all effects pass through `fx`, the compiler infers cache keys, capability matrices, and trace trees without manual annotations.
69
-
70
- ## One Contract, Many Surfaces
71
-
72
- The source of truth is the backend model expressed in code. The **Manifest** is the compiled, versioned contract representing that model.
73
-
74
- | Surface | Port | You Maintain? |
75
- | --------------------------------- | ------------------ | ----------------------------- |
76
- | Typed client (`okengine/client`) | your app code | No — derived from Manifest |
77
- | Console panels, traces, explorers | `:6533` | No — reads the Manifest |
78
- | MCP for agents | `:6535` | No — reads the Manifest |
79
- | Architecture diagram | Console | No — it _is_ the effect graph |
80
- | Capability matrix + cache keys | compiler / runtime | No — inferred from `fx` |
81
-
82
- Operational surfaces are derived, not separately maintained.
83
-
84
- ## See the Model Compose
85
-
86
- OKE does not add new subsystems when new architectural requirements emerge. The eight closed primitives compose naturally:
87
-
88
- - **Realtime:** `Store + Gate + Signal + Flow → Live Query` (Global CDC + RLS re-check + SSE).
89
- - **Security:** `Gate + Store/RLS + Tenant + fx → Secure execution` (Unified user, operator, and agent boundaries).
90
- - **Agents:** `MCP + Gate + OAuth + Flow → Agent-accessible backend` (Exposing Flows as MCP tools).
91
- - **Operations:** `Manifest + Effects + Runs → Inspectable backend` (Wide-event telemetry and live graphs).
92
-
93
- > **None of these required a ninth primitive.**
94
-
95
- ## Core Philosophy
96
-
97
- > **Keep the model small. Let the backend grow without growing the mental model.**
98
-
99
- Your backend is not just executable. It is inspectable.
100
-
101
- ## Next Steps
102
-
103
- <Cards>
104
- <Card
105
- title="Introduction"
106
- description="The Law, Flow anatomy, and the eight elements."
107
- href="/docs/get-started/introduction"
108
- />
109
- <Card
110
- title="Installation"
111
- description="Scaffold your first project with create-oke."
112
- href="/docs/get-started/installation"
113
- />
114
- </Cards>
@@ -1,151 +0,0 @@
1
- ---
2
- title: "llama.cpp"
3
- description: "Default local AI image — OpenAI-compatible llama-server, loopback-only publish, pinned build ≥ b8146."
4
- icon: "Bot"
5
- source: "docs/spec/unified-theory.md"
6
- ---
7
-
8
- llama.cpp is the default `images.ai` pin for local inference. It runs
9
- `llama-server` with an OpenAI-compatible `/v1` API — lightest resource footprint
10
- for single-user / dev. Driver id stays `openai-compatible`.
11
-
12
- <Callout title="The one rule">
13
- Pin a verified build ≥ `b8146`, publish only on loopback, and load models only from curated
14
- registries (Docker Hub `ai/`) — never arbitrary untrusted GGUF.
15
- </Callout>
16
-
17
- ## Quick start
18
-
19
- <Steps>
20
-
21
- <Step>
22
- ### Pin driver + image
23
-
24
- ```typescript title="oke.config.ts"
25
- drivers: {
26
- ai: { dev: "openai-compatible", test: "mock", prod: "openai-compatible" },
27
- },
28
- images: {
29
- ai: "ghcr.io/ggml-org/llama.cpp:server-b10450", // never :latest
30
- },
31
- ```
32
-
33
- Or `oke ai setup --provider llama-cpp` (TTY: banner → Ultra Fast / Fast /
34
- Balanced / Smart → up to 20 curated Docker Hub `ai/` picks per tier) / `--yes`
35
- for `granite3.3:2b`.
36
-
37
- </Step>
38
-
39
- <Step>
40
- ### Env written by the stack
41
-
42
- ```bash title=".env.local"
43
- OKE_AI_URL=http://127.0.0.1:8080/v1
44
- OKE_AI_MODEL=granite3.3:2b
45
- ```
46
-
47
- `OKE_AI_MODEL` is a Docker Hub `ai/<id>` model. The recipe writes
48
- `.oke/llama-entrypoint.py` (generated, gitignored), Hub-pulls into the cache
49
- volume, then starts `llama-server -m <gguf> --alias <id>` (single-model).
50
-
51
- Never set `LLAMA_ARG_MODELS_PRESET` / `LLAMA_ARG_DOCKER_REPO` — those hang on
52
- b10290+. `oke dev` shows the model id and polls `/v1/models` until `ready`
53
- (first boot may take minutes).
54
-
55
- </Step>
56
-
57
- <Step>
58
- ### Ask through the OpenAI-compatible driver
59
-
60
- ```typescript
61
- import { ai } from "okengine";
62
-
63
- export const smart = ai.model("smart", {
64
- provider: "openai-compatible",
65
- model: process.env.OKE_AI_MODEL ?? "granite3.3:2b",
66
- });
67
- ```
68
-
69
- </Step>
70
-
71
- </Steps>
72
-
73
- ## Security (hard requirements)
74
-
75
- | Control | Requirement |
76
- | -------------------- | ---------------------------------------------------------------------------- |
77
- | Host publish | `127.0.0.1:8080:8080` only — never `0.0.0.0` |
78
- | Image pin | Explicit build ≥ **b8146** (CVE-2026-27940 / CVE-2026-33298); never `latest` |
79
- | Model source | Docker Hub [`ai/`](https://hub.docker.com/u/ai) namespace (or known HF GGUF) |
80
- | Untrusted GGUF | **Forbidden** — crafted files can RCE the parser on unpatched builds |
81
- | RPC / extra backends | Not published — OpenAI HTTP only |
82
-
83
- Inside the container the server listens on `0.0.0.0` so the Compose network and
84
- loopback map work. The **host** bind is loopback — same isolation idea as
85
- Postgres/Redis, stricter on the published interface because of GGUF CVE risk.
86
-
87
- ## Required env
88
-
89
- | Variable | Required? | Meaning |
90
- | -------------- | ----------------- | --------------------------------------------- |
91
- | `OKE_AI_URL` | **Yes** in docker | Base URL including `/v1` |
92
- | `OKE_AI_MODEL` | Recommended | Docker Hub `ai/` id (default `granite3.3:2b`) |
93
-
94
- ## What the recipe configures
95
-
96
- | Field | Value |
97
- | -------------- | ------------------------------------------------------------ |
98
- | Container port | `8080` |
99
- | Host publish | `127.0.0.1:8080:8080` |
100
- | Healthcheck | `GET /health`, every 5s, 24 retries, 900s start |
101
- | Connection URL | `http://host:8080/v1` |
102
- | Model load | `.oke/llama-entrypoint.py` → Hub pull (incl. CNCF) then `-m` |
103
-
104
- ## When to choose something else
105
-
106
- | Workload | Prefer |
107
- | ------------------------------------------ | --------------------------------------- |
108
- | Single-user / dev, lightest footprint | **llama.cpp** (this recipe) |
109
- | Local DX with library pull UX | [Ollama](/docs/recipes/ollama) |
110
- | Multi-user / production concurrency on GPU | [vLLM](/docs/recipes/vllm) |
111
- | Structured / agent workloads on GPU | [SGLang](/docs/recipes/sglang) |
112
- | Managed cloud | Anthropic / OpenAI / … (no `images.ai`) |
113
-
114
- ## Troubleshooting
115
-
116
- <Accordions>
117
- <Accordion title="Connection refused on :8080">
118
-
119
- Confirm compose published `127.0.0.1:8080:8080` (not bare `8080:8080` on all
120
- interfaces). `OKE_AI_URL` must include `/v1`.
121
-
122
- </Accordion>
123
- <Accordion title="Model fails to load / slow first boot">
124
-
125
- First start Hub-pulls the curated `ai/` model into the named cache volume
126
- (see logs: `oke ai: ensuring…` / download %). Prefer `oke ai setup` tiers
127
- (Ultra Fast → `granite3.3:2b`) for smoke tests.
128
-
129
- Confirm `OKE_AI_MODEL` in `.env.local`. Watch `oke
130
- dev` until AI status is `ready`.
131
-
132
- If status stays `loading` on Compose that still uses `--models-preset`,
133
- regenerate `docker/` and recreate AI. Never mount random GGUF or set
134
- `LLAMA_ARG_MODELS_PRESET` / `LLAMA_ARG_DOCKER_REPO`.
135
-
136
- </Accordion>
137
- </Accordions>
138
-
139
- ## Learn more
140
-
141
- - [AI](/docs/elements/ai) — `fx.ask`, prompts, drivers
142
- - [Ollama](/docs/recipes/ollama) — fully supported alternative
143
- - [Environment variables](/docs/reference/environment-variables) — `OKE_AI_*`
144
-
145
- ## Next
146
-
147
- <Cards>
148
- <Card title="Ollama" description="Library UX alternative." href="/docs/recipes/ollama" />
149
- <Card title="vLLM" description="Production GPU serving." href="/docs/recipes/vllm" />
150
- <Card title="AI" description="Prompts, models, guardrails." href="/docs/elements/ai" />
151
- </Cards>