okengine 0.18.5 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (510) hide show
  1. package/AGENTS.md +18 -10
  2. package/README.md +2 -2
  3. package/package.json +51 -50
  4. package/site/content/docs/ai/llms-txt.mdx +1 -1
  5. package/site/content/docs/ai/meta.json +1 -1
  6. package/site/content/docs/ai/skills.mdx +4 -1
  7. package/site/content/docs/ai/try-it.mdx +58 -0
  8. package/site/content/docs/client/auth.mdx +208 -0
  9. package/site/content/docs/client/calling.mdx +451 -0
  10. package/site/content/docs/client/index.mdx +209 -0
  11. package/site/content/docs/client/live.mdx +234 -0
  12. package/site/content/docs/client/meta.json +5 -0
  13. package/site/content/docs/client/react.mdx +249 -0
  14. package/site/content/docs/elements/ai/agents.mdx +232 -0
  15. package/site/content/docs/elements/ai/index.mdx +341 -0
  16. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  17. package/site/content/docs/elements/ai/meta.json +5 -0
  18. package/site/content/docs/elements/ai/models.mdx +283 -0
  19. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  20. package/site/content/docs/elements/channel/email.mdx +266 -0
  21. package/site/content/docs/elements/channel/index.mdx +344 -0
  22. package/site/content/docs/elements/channel/meta.json +5 -0
  23. package/site/content/docs/elements/channel/push.mdx +218 -0
  24. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  25. package/site/content/docs/elements/channel/sms.mdx +264 -0
  26. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  27. package/site/content/docs/elements/clock/index.mdx +300 -0
  28. package/site/content/docs/elements/clock/meta.json +5 -0
  29. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  30. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  31. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  32. package/site/content/docs/elements/flow/http.mdx +1080 -0
  33. package/site/content/docs/elements/flow/index.mdx +618 -0
  34. package/site/content/docs/elements/flow/meta.json +5 -0
  35. package/site/content/docs/elements/flow/routing.mdx +559 -0
  36. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  37. package/site/content/docs/elements/gate/auth.mdx +371 -0
  38. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  39. package/site/content/docs/elements/gate/index.mdx +418 -0
  40. package/site/content/docs/elements/gate/meta.json +5 -0
  41. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  42. package/site/content/docs/elements/gate/rls.mdx +303 -0
  43. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  44. package/site/content/docs/elements/index.mdx +20 -10
  45. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  46. package/site/content/docs/elements/signal/index.mdx +352 -0
  47. package/site/content/docs/elements/signal/live.mdx +590 -0
  48. package/site/content/docs/elements/signal/meta.json +5 -0
  49. package/site/content/docs/elements/signal/once.mdx +596 -0
  50. package/site/content/docs/elements/store/files.mdx +659 -0
  51. package/site/content/docs/elements/store/index.mdx +310 -0
  52. package/site/content/docs/elements/store/kv.mdx +629 -0
  53. package/site/content/docs/elements/store/meta.json +5 -0
  54. package/site/content/docs/elements/store/search.mdx +946 -0
  55. package/site/content/docs/elements/store/sql.mdx +937 -0
  56. package/site/content/docs/elements/vault/config.mdx +256 -0
  57. package/site/content/docs/elements/vault/index.mdx +356 -0
  58. package/site/content/docs/elements/vault/meta.json +5 -0
  59. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  60. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  61. package/site/content/docs/index.mdx +63 -36
  62. package/site/content/docs/meta.json +8 -7
  63. package/site/content/docs/plugins/cors.mdx +2 -1
  64. package/site/content/docs/plugins/csrf.mdx +4 -1
  65. package/site/content/docs/plugins/headers.mdx +2 -1
  66. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  67. package/site/content/docs/plugins/magic-link.mdx +6 -0
  68. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  69. package/site/content/docs/plugins/oauth.mdx +1 -1
  70. package/site/content/docs/plugins/otp.mdx +12 -1
  71. package/site/content/docs/plugins/passkey.mdx +39 -15
  72. package/site/content/docs/plugins/two-factor.mdx +91 -34
  73. package/site/content/docs/plugins/username.mdx +1 -1
  74. package/site/content/docs/recipes/caddy.mdx +3 -3
  75. package/site/content/docs/recipes/index.mdx +18 -28
  76. package/site/content/docs/recipes/mailpit.mdx +1 -1
  77. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  78. package/site/content/docs/recipes/meta.json +1 -4
  79. package/site/content/docs/recipes/nginx.mdx +2 -2
  80. package/site/content/docs/recipes/openrouter.mdx +283 -0
  81. package/site/content/docs/recipes/pgdog.mdx +3 -3
  82. package/site/content/docs/recipes/postgres.mdx +1 -2
  83. package/site/content/docs/recipes/rustfs.mdx +2 -2
  84. package/site/content/docs/recipes/traefik.mdx +3 -3
  85. package/site/content/docs/reference/cli.mdx +231 -0
  86. package/site/content/docs/reference/configuration.mdx +30 -10
  87. package/site/content/docs/reference/environment-variables.mdx +93 -20
  88. package/site/content/docs/reference/errors.mdx +132 -29
  89. package/site/content/docs/reference/fx.mdx +137 -73
  90. package/site/content/docs/reference/index.mdx +13 -21
  91. package/site/content/docs/reference/meta.json +4 -5
  92. package/site/content/docs/reference/okid.mdx +42 -17
  93. package/site/content/docs/reference/plugins.mdx +4 -3
  94. package/site/content/docs/reference/security.mdx +197 -0
  95. package/site/content/docs/understand/meta.json +5 -0
  96. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  97. package/site/content/docs/understand/the-model.mdx +32 -0
  98. package/site/content/docs/understand/the-problem.mdx +74 -0
  99. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  100. package/src/auth/api-keys.ts +2 -1
  101. package/src/auth/bindings.ts +64 -16
  102. package/src/auth/gate-auth.test.ts +6 -1
  103. package/src/auth/identity.ts +152 -5
  104. package/src/auth/index.ts +29 -0
  105. package/src/auth/invites.ts +2 -1
  106. package/src/auth/method-context.ts +41 -0
  107. package/src/auth/oauth-as/crypto.ts +2 -1
  108. package/src/auth/oauth-as/stores.ts +2 -1
  109. package/src/auth/operator.ts +2 -1
  110. package/src/auth/sessions-jwt.test.ts +77 -0
  111. package/src/auth/sessions.ts +20 -4
  112. package/src/auth/tenants.ts +3 -2
  113. package/src/auth/two-factor-challenge.test.ts +61 -0
  114. package/src/auth/two-factor-challenge.ts +284 -0
  115. package/src/auth/verification.ts +5 -0
  116. package/src/bench/REPORT.md +49 -0
  117. package/src/bench/g03-signal-once.bench.ts +1 -1
  118. package/src/bench/g10-observability-contention.bench.ts +1 -1
  119. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  120. package/src/bench/load-app.ts +2 -10
  121. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  122. package/src/cli/ai-setup/apply.ts +294 -52
  123. package/src/cli/ai-setup/catalog.ts +238 -1342
  124. package/src/cli/ai-setup/index.ts +14 -99
  125. package/src/cli/ai-setup/prompts.ts +60 -443
  126. package/src/cli/ask-seed.test.ts +96 -0
  127. package/src/cli/ask-seed.ts +82 -0
  128. package/src/cli/ask-vault-gaps.test.ts +84 -0
  129. package/src/cli/ask-vault-gaps.ts +146 -0
  130. package/src/cli/build.ts +2 -2
  131. package/src/cli/client-add.test.ts +26 -1
  132. package/src/cli/client-add.ts +106 -27
  133. package/src/cli/db-seed.ts +2 -0
  134. package/src/cli/db.ts +150 -11
  135. package/src/cli/dev.ts +119 -211
  136. package/src/cli/docker-clean.ts +2 -2
  137. package/src/cli/docker-cli.test.ts +1 -1
  138. package/src/cli/doctor-diff.ts +4 -2
  139. package/src/cli/doctor-pii.test.ts +1 -1
  140. package/src/cli/doctor.ts +14 -1
  141. package/src/cli/hero-meta.test.ts +4 -2
  142. package/src/cli/load-config.images.test.ts +8 -10
  143. package/src/cli/load-config.ts +1 -1
  144. package/src/cli/registry.ts +22 -10
  145. package/src/cli/replay.ts +3 -1
  146. package/src/cli/start.ts +1 -1
  147. package/src/cli/tui/keys.ts +2 -3
  148. package/src/client/auth/cookies.ts +74 -0
  149. package/src/client/auth/create-auth-client.ts +636 -0
  150. package/src/client/auth/denials.ts +99 -0
  151. package/src/client/auth/session.ts +283 -0
  152. package/src/client/auth.test.ts +251 -0
  153. package/src/client/auth.ts +39 -114
  154. package/src/client/create-with-session.ts +245 -0
  155. package/src/client/create.ts +51 -5
  156. package/src/client/index.ts +11 -1
  157. package/src/client/live.ts +11 -79
  158. package/src/client/notes-contract.test.ts +5 -10
  159. package/src/client/sse.ts +137 -0
  160. package/src/client/stream.ts +147 -0
  161. package/src/client/transport.test.ts +32 -0
  162. package/src/client/transport.ts +123 -26
  163. package/src/client/types.ts +118 -14
  164. package/src/client-react/index.ts +185 -24
  165. package/src/client-react/use-live-query.ts +13 -3
  166. package/src/compiler/aot.test.ts +7 -4
  167. package/src/compiler/effects-embed.test.ts +56 -0
  168. package/src/compiler/effects-fetch.test.ts +43 -0
  169. package/src/compiler/effects-infer.ts +58 -2
  170. package/src/compiler/extract.test.ts +257 -43
  171. package/src/compiler/extract.ts +566 -48
  172. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  173. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  174. package/src/compiler/fixtures/skyport.expected.json +4 -4
  175. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  176. package/src/compiler/response.ts +2 -2
  177. package/src/compiler/search-writer-isolation.test.ts +40 -0
  178. package/src/config/index.ts +11 -0
  179. package/src/console/server/app.ts +17 -23
  180. package/src/console/server/bind.ts +4 -0
  181. package/src/console/server/console.test.ts +2 -2
  182. package/src/console/server/flows-invoke.test.ts +50 -34
  183. package/src/console/server/flows.ts +436 -255
  184. package/src/console/server/runs-ingest.test.ts +6 -3
  185. package/src/console/server/serve.ts +1 -1
  186. package/src/console/server/signals.test.ts +1 -5
  187. package/src/console/server/signals.ts +8 -6
  188. package/src/console/server/state.ts +6 -1
  189. package/src/console/server/store.ts +1 -1
  190. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  191. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  192. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  193. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  194. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  195. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  196. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  197. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  198. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  199. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  200. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  201. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  202. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  203. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  204. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  205. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  206. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  207. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  208. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  209. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  210. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  211. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  212. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  213. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  214. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  215. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  216. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  217. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  218. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  219. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  220. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  221. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  222. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  223. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  224. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  225. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  226. package/src/console/ui-next/dist/index.html +6 -13
  227. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  228. package/src/console/ui-next/src/client.ts +7 -2
  229. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  230. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  231. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  232. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  233. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  235. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  236. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  237. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  238. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  239. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  240. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  241. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  242. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  243. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  244. package/src/docker/ai-model-status.test.ts +1 -12
  245. package/src/docker/ai-model-status.ts +10 -38
  246. package/src/docker/compose-up.test.ts +100 -0
  247. package/src/docker/compose-up.ts +292 -0
  248. package/src/docker/compose.ts +4 -14
  249. package/src/docker/derive.ts +9 -34
  250. package/src/docker/docker.test.ts +16 -261
  251. package/src/docker/images-config.test.ts +13 -25
  252. package/src/docker/index.ts +1 -24
  253. package/src/docker/recipes/index.ts +0 -23
  254. package/src/docker/recipes/pgdog.ts +6 -4
  255. package/src/docker/stack-id.test.ts +2 -2
  256. package/src/docker/stack-id.ts +0 -1
  257. package/src/docker/types.ts +2 -2
  258. package/src/drivers/ai-anthropic.ts +10 -0
  259. package/src/drivers/ai-openai-compatible.ts +34 -7
  260. package/src/drivers/ai-providers.test.ts +0 -107
  261. package/src/drivers/ai-stream.test.ts +0 -34
  262. package/src/drivers/ai-types.ts +17 -8
  263. package/src/drivers/channel-fcm.ts +6 -1
  264. package/src/drivers/channel-msegat.ts +6 -1
  265. package/src/drivers/channel-resend.ts +5 -1
  266. package/src/drivers/channel-smtp.ts +5 -1
  267. package/src/drivers/channel-sndr.ts +10 -1
  268. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  269. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  270. package/src/drivers/channel-taqnyat.ts +6 -1
  271. package/src/drivers/channel-types.ts +10 -0
  272. package/src/drivers/channel-unifonic.ts +6 -1
  273. package/src/drivers/channel-wa-cloud.ts +6 -1
  274. package/src/drivers/channel-webpush.ts +6 -1
  275. package/src/drivers/external.ts +33 -0
  276. package/src/drivers/index.ts +0 -10
  277. package/src/drivers/meilisearch.ts +6 -0
  278. package/src/drivers/oauth-types.ts +4 -0
  279. package/src/drivers/postgres.test.ts +74 -3
  280. package/src/drivers/postgres.ts +175 -6
  281. package/src/drivers/signal-types.ts +5 -5
  282. package/src/drivers/types.ts +7 -0
  283. package/src/drivers/vault-types.ts +5 -0
  284. package/src/elements/ai/declare.ts +17 -4
  285. package/src/elements/ai/eval.ts +1 -1
  286. package/src/elements/ai/mcp-http.ts +1 -1
  287. package/src/elements/ai/pii.ts +1 -1
  288. package/src/elements/ai/providers.test.ts +289 -0
  289. package/src/elements/ai/providers.ts +169 -0
  290. package/src/elements/ai/runtime.ts +68 -5
  291. package/src/elements/ai/schema.ts +2 -2
  292. package/src/elements/ai.test.ts +7 -7
  293. package/src/elements/ai.ts +17 -1
  294. package/src/elements/channel/runtime.ts +105 -12
  295. package/src/elements/clock/cron-fields.test.ts +144 -0
  296. package/src/elements/clock/cron-fields.ts +185 -0
  297. package/src/elements/clock/declare.ts +247 -3
  298. package/src/elements/clock.ts +21 -1
  299. package/src/elements/index.ts +15 -0
  300. package/src/elements/signal/chaos-child.ts +1 -2
  301. package/src/elements/signal/declare.ts +65 -37
  302. package/src/elements/signal/delivery-modes.test.ts +11 -31
  303. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  304. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  305. package/src/elements/signal/key-ordering.test.ts +6 -26
  306. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  307. package/src/elements/signal/optional-emit.test.ts +6 -9
  308. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  309. package/src/elements/signal/orphan-messages.test.ts +4 -15
  310. package/src/elements/signal/reconcile.test.ts +2 -2
  311. package/src/elements/signal/runtime.ts +1 -1
  312. package/src/elements/signal/schema-emit.test.ts +4 -8
  313. package/src/elements/signal.test.ts +24 -49
  314. package/src/elements/signal.ts +9 -2
  315. package/src/elements/store/domain-ddl.test.ts +1 -1
  316. package/src/elements/store/live-http.test.ts +9 -4
  317. package/src/elements/store/prepare-row.test.ts +123 -0
  318. package/src/elements/store/resource.ts +43 -12
  319. package/src/elements/store/schema-decl.ts +117 -0
  320. package/src/elements/store/search-backfill.ts +205 -0
  321. package/src/elements/store/search-bind.ts +66 -0
  322. package/src/elements/store/search-bm25.ts +78 -0
  323. package/src/elements/store/search-ddl.ts +156 -0
  324. package/src/elements/store/search-embed-flow.ts +141 -0
  325. package/src/elements/store/search-errors.ts +34 -0
  326. package/src/elements/store/search-fusion.ts +112 -0
  327. package/src/elements/store/search-lsh.ts +179 -0
  328. package/src/elements/store/search-runtime.ts +300 -0
  329. package/src/elements/store/search.test.ts +144 -0
  330. package/src/elements/store/sql-session.test.ts +1 -0
  331. package/src/elements/store/sql-session.ts +83 -3
  332. package/src/elements/store/table.ts +23 -2
  333. package/src/elements/store/upsert-app.test.ts +1 -3
  334. package/src/elements/store.ts +50 -0
  335. package/src/full.ts +4 -2
  336. package/src/http.ts +4 -1
  337. package/src/i18n/catalogs/ar.ts +14 -6
  338. package/src/i18n/catalogs/en.ts +14 -6
  339. package/src/index.ts +6 -1
  340. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  341. package/src/kernel/adopt-routes.ts +9 -1
  342. package/src/kernel/app-auth.ts +5 -0
  343. package/src/kernel/app.ts +102 -9
  344. package/src/kernel/auto-cache.test.ts +6 -12
  345. package/src/kernel/auto-registry.test.ts +3 -3
  346. package/src/kernel/boot-bind/ai.test.ts +22 -19
  347. package/src/kernel/boot-bind/ai.ts +5 -43
  348. package/src/kernel/boot-bind/clock.ts +23 -5
  349. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  350. package/src/kernel/boot.test.ts +11 -6
  351. package/src/kernel/boot.ts +66 -16
  352. package/src/kernel/boundary-contract.ts +93 -0
  353. package/src/kernel/budget.test.ts +1 -1
  354. package/src/kernel/call.ts +89 -0
  355. package/src/kernel/capability.ts +6 -0
  356. package/src/kernel/client-descriptor.ts +123 -0
  357. package/src/kernel/clock-timezone.test.ts +80 -0
  358. package/src/kernel/correlation.test.ts +1 -1
  359. package/src/kernel/dry-run.ts +11 -8
  360. package/src/kernel/effects-stamping.test.ts +42 -9
  361. package/src/kernel/effects.test.ts +4 -2
  362. package/src/kernel/effects.ts +51 -9
  363. package/src/kernel/errors-channel.ts +17 -0
  364. package/src/kernel/errors-live-resume.ts +3 -2
  365. package/src/kernel/errors-tenant.ts +7 -4
  366. package/src/kernel/errors.registry-helpers.ts +96 -0
  367. package/src/kernel/errors.registry.test.ts +139 -25
  368. package/src/kernel/errors.ts +102 -23
  369. package/src/kernel/external-effects.test.ts +196 -0
  370. package/src/kernel/flow.test.ts +13 -4
  371. package/src/kernel/flow.ts +69 -71
  372. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  373. package/src/kernel/fx-dead-letters.test.ts +3 -3
  374. package/src/kernel/fx-fetch.ts +55 -0
  375. package/src/kernel/fx-live-stream.ts +2 -2
  376. package/src/kernel/fx-live.test.ts +8 -8
  377. package/src/kernel/fx.test.ts +17 -11
  378. package/src/kernel/fx.ts +180 -57
  379. package/src/kernel/horizontal-child.ts +1 -1
  380. package/src/kernel/http-query.test.ts +3 -6
  381. package/src/kernel/index.ts +13 -3
  382. package/src/kernel/instance-id.ts +1 -1
  383. package/src/kernel/instances.test.ts +40 -0
  384. package/src/kernel/instances.ts +47 -9
  385. package/src/kernel/live-http.test.ts +6 -7
  386. package/src/kernel/live-http.ts +6 -2
  387. package/src/kernel/live-resume.test.ts +1 -1
  388. package/src/kernel/mcp-tool.test.ts +3 -3
  389. package/src/kernel/on.ts +98 -4
  390. package/src/kernel/pipeline.test.ts +12 -15
  391. package/src/kernel/plugin-elements.test.ts +1 -1
  392. package/src/kernel/stamp-http.test.ts +3 -3
  393. package/src/kernel/triggers.ts +210 -95
  394. package/src/kernel-entry.ts +0 -1
  395. package/src/manifest/diff.ts +11 -1
  396. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  397. package/src/manifest/types.ts +46 -2
  398. package/src/mcp/docs-index.ts +3 -3
  399. package/src/mcp/docs-mcp.test.ts +2 -2
  400. package/src/mcp/docs-tools.ts +1 -1
  401. package/src/okid.test.ts +56 -0
  402. package/src/okid.ts +55 -11
  403. package/src/plugins/anonymous.ts +8 -4
  404. package/src/plugins/auth/shared.ts +27 -3
  405. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  406. package/src/plugins/auth-methods.security.test.ts +561 -23
  407. package/src/plugins/config-source.ts +1 -1
  408. package/src/plugins/csrf.test.ts +65 -0
  409. package/src/plugins/index.ts +2 -0
  410. package/src/plugins/magic-link.ts +36 -16
  411. package/src/plugins/oauth/shared.ts +3 -1
  412. package/src/plugins/oauth.ts +22 -14
  413. package/src/plugins/otp.ts +37 -21
  414. package/src/plugins/passkey-webauthn.ts +9 -6
  415. package/src/plugins/passkey.ts +98 -26
  416. package/src/plugins/pre-account-hijack.test.ts +223 -0
  417. package/src/plugins/two-factor.ts +466 -37
  418. package/src/plugins/username.ts +19 -7
  419. package/src/release/build-lib.ts +1 -0
  420. package/src/release/limits.ts +2 -2
  421. package/src/release/measure.ts +1 -1
  422. package/src/runs/collect.test.ts +0 -2
  423. package/src/runtime/json-code-block.test.ts +250 -20
  424. package/src/runtime/json-code-block.ts +1261 -41
  425. package/src/term.test.ts +1 -1
  426. package/src/test/create-test-app.test.ts +12 -12
  427. package/src/test/live-signals.test.ts +6 -6
  428. package/src/test/provisions.integration.test.ts +10 -14
  429. package/src/test/reset-element-registries.ts +1 -1
  430. package/src/test/tenant-isolation.test.ts +12 -6
  431. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  432. package/site/content/docs/deployment/docker.mdx +0 -227
  433. package/site/content/docs/deployment/index.mdx +0 -83
  434. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  435. package/site/content/docs/deployment/meta.json +0 -5
  436. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  437. package/site/content/docs/elements/ai.mdx +0 -385
  438. package/site/content/docs/elements/channel.mdx +0 -346
  439. package/site/content/docs/elements/clock.mdx +0 -244
  440. package/site/content/docs/elements/flow.mdx +0 -420
  441. package/site/content/docs/elements/gate.mdx +0 -436
  442. package/site/content/docs/elements/signal.mdx +0 -380
  443. package/site/content/docs/elements/store.mdx +0 -1099
  444. package/site/content/docs/elements/vault.mdx +0 -405
  445. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  446. package/site/content/docs/get-started/index.mdx +0 -43
  447. package/site/content/docs/get-started/installation.mdx +0 -220
  448. package/site/content/docs/get-started/introduction.mdx +0 -144
  449. package/site/content/docs/get-started/meta.json +0 -13
  450. package/site/content/docs/get-started/project-structure.mdx +0 -925
  451. package/site/content/docs/get-started/testing.mdx +0 -328
  452. package/site/content/docs/get-started/why.mdx +0 -114
  453. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  454. package/site/content/docs/recipes/ollama.mdx +0 -142
  455. package/site/content/docs/recipes/sglang.mdx +0 -105
  456. package/site/content/docs/recipes/vllm.mdx +0 -106
  457. package/site/content/docs/reference/cli.md +0 -232
  458. package/site/content/docs/reference/client.mdx +0 -469
  459. package/site/content/docs/reference/security.md +0 -74
  460. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  461. package/src/cli/ai-setup/recommend.test.ts +0 -225
  462. package/src/cli/ai-setup/recommend.ts +0 -225
  463. package/src/cli/dev-controls.test.ts +0 -122
  464. package/src/cli/dev-controls.ts +0 -164
  465. package/src/cli/tui/DevLive.tsx +0 -126
  466. package/src/console/ui-next/dist/assets/access-page-3-EFj-2G.js +0 -4
  467. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  468. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  469. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  470. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  471. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  472. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  473. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  474. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  475. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  476. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  477. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  478. package/src/console/ui-next/dist/assets/flows-page-cVFnA4HH.js +0 -1
  479. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  480. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  481. package/src/console/ui-next/dist/assets/index-CMIgUbD0.js +0 -66
  482. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  483. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  484. package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.js +0 -4
  485. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  486. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  487. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  488. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  489. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  490. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  491. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  492. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  493. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  494. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  495. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  496. package/src/console/ui-next/dist/assets/units-page-l8FeKfnP.js +0 -1
  497. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  498. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  499. package/src/console/ui-next/dist/assets/vault-page-CL-d_mLE.js +0 -2
  500. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  501. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  502. package/src/docker/ollama-pull.ts +0 -232
  503. package/src/docker/recipes/llama-cpp.ts +0 -298
  504. package/src/docker/recipes/ollama.ts +0 -44
  505. package/src/docker/recipes/sglang.ts +0 -55
  506. package/src/docker/recipes/vllm.ts +0 -44
  507. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  508. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  509. package/src/drivers/ai-ollama.ts +0 -389
  510. package/src/drivers/ollama.ts +0 -14
@@ -0,0 +1,445 @@
1
+ ---
2
+ title: "Durable Sleep"
3
+ description: "Journaled pauses that resume across restarts — fx.clock.sleep(label, duration) on durable Flows."
4
+ icon: "Moon"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Durable sleep suspends a Flow until a future instant without holding a worker thread.
9
+ Call `await fx.clock.sleep(label, duration)` inside a `durable: true` Flow — the journal
10
+ stores `wakeAt`, releases the run lease, and any instance may resume when due.
11
+
12
+ For developers building trial reminders, delayed digests, and multi-day provisions on okengine.
13
+
14
+ <Callout title="The one rule">
15
+ Signature is `fx.clock.sleep(label, duration)` — two arguments. A single duration string is
16
+ treated as the **label**, not the wait. Sleep only parks when the Flow is durable.
17
+ </Callout>
18
+
19
+ <ClockSleep />
20
+
21
+ ## Smallest Example
22
+
23
+ <Steps>
24
+
25
+ <Step>
26
+ ### Sleep inside a durable Flow
27
+
28
+ ```typescript title="src/flows/trials/start.ts"
29
+ import { on, flow, http } from "okengine";
30
+ import { z } from "zod";
31
+
32
+ export const start = on(
33
+ http.post(),
34
+ flow({
35
+ durable: true,
36
+ in: z.object({ email: z.string().email() }),
37
+ do: async ({ email }, fx) => {
38
+ await fx.step("mark-trial", async () => {
39
+ await fx.call(startTrial, { email });
40
+ });
41
+ await fx.clock.sleep("expiry-window", "3d");
42
+ await fx.step("notify", async () => {
43
+ await fx.send(trialExpiringEmail, { to: email });
44
+ });
45
+ },
46
+ }),
47
+ );
48
+ ```
49
+
50
+ </Step>
51
+
52
+ <Step>
53
+ ### Call the endpoint
54
+
55
+ ```bash
56
+ curl -X POST http://localhost:6530/trials/start \
57
+ -H "content-type: application/json" \
58
+ -d '{"email":"ada@example.com"}'
59
+ ```
60
+
61
+ Response: **`204 No Content`** (empty body). The HTTP client is done — wake continues on a
62
+ worker three days later. Wrap side effects in `fx.step` so replay does not re-send mail.
63
+
64
+ </Step>
65
+
66
+ </Steps>
67
+
68
+ <Callout title="Detailed section">
69
+ If you only need a pause, the example above is enough. Below: park physics, wake-early,
70
+ nested-call limits, non-durable no-ops, and how sleep fits with steps / compensation.
71
+ </Callout>
72
+
73
+ ## Progressive Patterns
74
+
75
+ From a labelled pause to HTTP parking, nested-call limits, and non-durable behavior:
76
+
77
+ <Tabs items={["Label + duration", "HTTP park", "After a step", "Non-durable"]}>
78
+
79
+ <Tab value="Label + duration">
80
+
81
+ Durations: `"200ms"` · `"30s"` · `"2m"` · `"1h"` · `"7d"`. Labels show up in the journal
82
+ and Console:
83
+
84
+ ```typescript
85
+ await fx.clock.sleep("morning-window", "8h");
86
+ await fx.clock.sleep("verify-window", "2m");
87
+ ```
88
+
89
+ **Wrong:** `fx.clock.sleep("8h")` — `"8h"` is the label; duration is missing → immediate
90
+ resolve / unexpected behavior.
91
+
92
+ </Tab>
93
+
94
+ <Tab value="HTTP park">
95
+
96
+ Sleep on an HTTP-triggered durable Flow returns success with an empty body (`204`). Return
97
+ a body **before** sleep if the caller must see an id:
98
+
99
+ ```typescript title="src/flows/workspaces/create.ts"
100
+ import { on, flow, http } from "okengine";
101
+ import { z } from "zod";
102
+
103
+ export const create = on(
104
+ http.post(),
105
+ flow({
106
+ durable: true,
107
+ in: z.object({ email: z.string().email() }),
108
+ do: async ({ email }, fx) => {
109
+ await fx.step("create", async () => {
110
+ await fx.call(createWorkspace, { email });
111
+ });
112
+ await fx.emit(workspaceProvisioned, { email });
113
+ await fx.clock.sleep("welcome-delay", "8h");
114
+ await fx.step("notify", async () => {
115
+ await fx.send(welcomeEmail, { to: email });
116
+ });
117
+ },
118
+ }),
119
+ );
120
+ ```
121
+
122
+ After sleep the HTTP client is already done (`204`). Need a JSON body? Return from a
123
+ Flow that does **not** sleep, and park on a Signal consumer instead. See
124
+ [Workflows · Durable Sleep](/docs/elements/flow/workflows#durable-sleep).
125
+
126
+ </Tab>
127
+
128
+ <Tab value="After a step">
129
+
130
+ Checkpoint work **before** the pause so a crash mid-provision does not re-run after wake:
131
+
132
+ ```typescript
133
+ await fx.step("provision", async () => {
134
+ await fx.call(createWorkspace, { email });
135
+ });
136
+ await fx.clock.sleep("morning-window", "8h");
137
+ await fx.step("notify", async () => {
138
+ await fx.send(welcomeEmail, { to: email });
139
+ });
140
+ ```
141
+
142
+ Do not hold `fx.using` resources across sleep — acquire again after wake.
143
+
144
+ </Tab>
145
+
146
+ <Tab value="Non-durable">
147
+
148
+ Without a journal, `fx.clock.sleep` resolves **immediately**. There is no thread sleep and
149
+ no `setTimeout`. Use durable Flows for real delays; use frozen clock + advance in tests.
150
+
151
+ </Tab>
152
+
153
+ </Tabs>
154
+
155
+ ## Sleep Reference
156
+
157
+ | Call / option | Type | Default | Meaning |
158
+ | --------------------------------- | ----------- | ------- | -------------------------------------------------- |
159
+ | `durable: true` | Flow option | `false` | Journals steps and sleep; required to park |
160
+ | `fx.clock.sleep(label, duration)` | park | — | Writes `wakeAt`, status `sleeping`, releases lease |
161
+ | `label` | `string` | — | Journal / Console step name |
162
+ | `duration` | `string` | — | `"200ms"` · `"30s"` · `"2m"` · `"1h"` · `"7d"` |
163
+
164
+ Outcomes of a durable attempt that hits sleep: status `"sleeping"` with `wakeAt` and
165
+ `label`. After wake, prior `fx.step` bodies replay from the journal and do not re-execute.
166
+
167
+ ### Duration units
168
+
169
+ Same grammar as `fx.clock.ago` / `fromNow` / `clock.every`:
170
+
171
+ | Unit | Example | Milliseconds |
172
+ | ---- | --------- | ------------ |
173
+ | `ms` | `"200ms"` | 200 |
174
+ | `s` | `"30s"` | 30_000 |
175
+ | `m` | `"2m"` | 120_000 |
176
+ | `h` | `"1h"` | 3_600_000 |
177
+ | `d` | `"7d"` | 604_800_000 |
178
+
179
+ Integer + unit only — no weeks. `"d"` is exactly 86_400_000 ms, not a calendar day across
180
+ DST. Unknown strings parse as `0` ms (wake immediately).
181
+
182
+ ## Park Physics
183
+
184
+ <Callout title="Detailed section">
185
+ If you only need `await fx.clock.sleep("label", "8h")`, jump past this section. The park writes a
186
+ journal entry, sets status `sleeping`, and **releases the run lease** so a parked flow does not
187
+ hold a 30s lock for days.
188
+ </Callout>
189
+
190
+ ```text
191
+ fx.clock.sleep(label, duration)
192
+ → journal entry { kind: "sleep", label, duration, wakeAt }
193
+ → status = sleeping, lease released
194
+ → HTTP / caller sees success (often 204)
195
+ → later: claim due sleep → resume → replay steps → continue after sleep
196
+ ```
197
+
198
+ Any instance may claim the row when `wakeAt` is due (shared journal + lease). Resume replays
199
+ completed `fx.step` values from the journal, then continues past the sleep entry.
200
+
201
+ | Phase | Status | Lease | What happens |
202
+ | -------------- | ---------------------- | ------------ | --------------------------------------------- |
203
+ | Before sleep | `running` | Held | Steps append; side effects execute once |
204
+ | At sleep | `sleeping` | **Released** | `wakeAt` stored; worker free |
205
+ | After `wakeAt` | claim → `running` | Re-acquired | Replay steps; sleep entry is a no-op past due |
206
+ | Done | `completed` / `failed` | Released | Terminal — resume refused |
207
+
208
+ **Consequence:** multi-day sleeps are safe across deploys — the journal row is the schedule,
209
+ not an in-memory timer.
210
+
211
+ ## With Steps
212
+
213
+ Each verb of durable work binds the same way — checkpoint, park, then more checkpoints:
214
+
215
+ <Tabs items={["Checkpoint sandwich", "HTTP body + sleep", "Signal consumer"]}>
216
+
217
+ <Tab value="Checkpoint sandwich">
218
+
219
+ Wrap every side effect in a uniquely named `fx.step`. Sleep sits **between** steps:
220
+
221
+ ```typescript title="src/flows/onboarding/welcome.ts"
222
+ import { on, flow } from "okengine";
223
+ import { userSignedUp } from "@/signals";
224
+ import { welcomeEmail } from "@/channels/welcome";
225
+
226
+ export const sendWelcome = on(
227
+ userSignedUp,
228
+ flow("onboarding.welcome", {
229
+ durable: true,
230
+ do: async ({ email }, fx) => {
231
+ await fx.step("provision", async () => {
232
+ await fx.call(createWorkspace, { email });
233
+ });
234
+ await fx.clock.sleep("morning-window", "8h");
235
+ await fx.step("notify", async () => {
236
+ await fx.send(welcomeEmail, { to: email });
237
+ });
238
+ },
239
+ }),
240
+ );
241
+ ```
242
+
243
+ **Consequence:** after wake, `provision` returns the journaled value and never re-runs;
244
+ `notify` runs for the first time.
245
+
246
+ </Tab>
247
+
248
+ <Tab value="HTTP body + sleep">
249
+
250
+ Parking an HTTP Flow always answers **`204`** (suspend returns `undefined`). When the
251
+ caller must see an id, **do not sleep on that route** — return the body, emit, and park
252
+ on a consumer:
253
+
254
+ ```typescript title="src/flows/trials/create.ts"
255
+ import { on, flow, http } from "okengine";
256
+ import { z } from "zod";
257
+
258
+ export const create = on(
259
+ http.post(),
260
+ flow({
261
+ durable: true,
262
+ in: z.object({ email: z.string().email() }),
263
+ out: z.object({ trialId: z.string() }),
264
+ do: async ({ email }, fx) => {
265
+ const trialId = await fx.step("create", async () => {
266
+ return await fx.call(createTrial, { email });
267
+ });
268
+ await fx.emit(trialStarted, { trialId, email });
269
+ return { trialId };
270
+ },
271
+ }),
272
+ );
273
+ ```
274
+
275
+ </Tab>
276
+
277
+ <Tab value="Signal consumer">
278
+
279
+ The consumer owns the multi-day wait (paired with the HTTP Flow above):
280
+
281
+ ```typescript title="src/flows/trials/remind.ts"
282
+ import { on, flow } from "okengine";
283
+ import { trialStarted } from "@/signals";
284
+ import { trialExpiringEmail } from "@/channels/trials";
285
+
286
+ export const remind = on(
287
+ trialStarted,
288
+ flow("trials.remind", {
289
+ durable: true,
290
+ do: async ({ trialId, email }, fx) => {
291
+ await fx.clock.sleep("expiry-window", "3d");
292
+ await fx.step("notify", async () => {
293
+ await fx.send(trialExpiringEmail, { to: email, trialId });
294
+ });
295
+ },
296
+ }),
297
+ );
298
+ ```
299
+
300
+ </Tab>
301
+
302
+ </Tabs>
303
+
304
+ ## Nested Calls
305
+
306
+ <Callout title="Detailed section">
307
+ If you sleep only on the root durable Flow, skip this section. `fx.call` waits for the callee to
308
+ return — a sleeping callee does not keep the caller parked.
309
+ </Callout>
310
+
311
+ `fx.call` of a durable sleeper: the caller receives `undefined` and continues; the child
312
+ wakes later as its own run.
313
+
314
+ | Pattern | Safe? | Why |
315
+ | --------------------------------------------- | ----- | ------------------------------------------ |
316
+ | Sleep on the root durable Flow | Yes | One journal row, clear park |
317
+ | `fx.emit` → durable consumer that sleeps | Yes | Separate run owns the wait |
318
+ | `fx.call(sleeperFlow, …)` then use the result | No | Caller gets `undefined`; child parks alone |
319
+
320
+ **Consequence:** sleep on the **root** durable Flow, or split with `fx.emit` to a consumer —
321
+ do not nest sleep behind `fx.call`.
322
+
323
+ ## Wake Early
324
+
325
+ Operators can advance `wakeAt` to **now** from Console (waiting-on / wake-early). With a
326
+ flow resolver, the run resumes immediately; without it, only the wake time moves forward.
327
+
328
+ | Outcome | Meaning |
329
+ | ---------------------------- | ---------------------------------------------------------------- |
330
+ | Resumed | `wakeAt` set to now and `runDurable` continued past the sleep |
331
+ | Wake time only | `wakeAt` advanced; scheduler / next claim picks it up |
332
+ | `ClockResourceNotFoundError` | `run "{id}" not found` — missing id, or status is not `sleeping` |
333
+
334
+ Missing or non-sleeping run id → `ClockResourceNotFoundError` — `run "{id}" not found`.
335
+
336
+ ## Non-durable & Tests
337
+
338
+ Without a journal session, `fx.clock.sleep` resolves immediately (tests and sync Flows).
339
+ There is no thread sleep and no `setTimeout`.
340
+
341
+ For deterministic waits in tests, use a frozen clock and advance:
342
+
343
+ ```typescript
344
+ import { createTimeTravel } from "okengine";
345
+
346
+ const t = createTimeTravel(0);
347
+ // Park a durable run with now: () => t.now()
348
+ t.advance("7d");
349
+ // Resume — sleep entry is past due and continues
350
+ ```
351
+
352
+ Pin journal for the env you need:
353
+
354
+ | Driver | Default env | Best for |
355
+ | ---------- | -------------- | ---------------------------------------------------- |
356
+ | `postgres` | `dev`, `prod` | Shared durable runs across replicas (`DATABASE_URL`) |
357
+ | `memory` | `test` | Process-local; lost on exit |
358
+ | `file` | pin explicitly | One machine — `.oke/journal.json` |
359
+
360
+ Unknown ids throw `oke boot: unknown journal driver "…" (expected memory · file · postgres)`.
361
+ Postgres without a URL throws `oke boot: journal driver "postgres" needs DATABASE_URL`.
362
+
363
+ Full lease / orphan / status tables live on [Workflows · Journal](/docs/elements/flow/workflows#journal).
364
+
365
+ ## Troubleshooting
366
+
367
+ <Accordions>
368
+
369
+ <Accordion title="Sleep returns immediately / work runs twice after wait">
370
+ Missing `durable: true`, or `fx.clock.sleep("8h")` with one argument. Use `fx.clock.sleep("label",
371
+ "8h")`. Non-durable sleep is a no-op.
372
+ </Accordion>
373
+
374
+ <Accordion title="HTTP 204 with empty body after POST">
375
+ The Flow parked on `fx.clock.sleep` — success, not a missing handler. The original client is done;
376
+ wake continues on a worker. Return a body before sleep if needed, or emit to a Signal consumer for
377
+ the long wait.
378
+ </Accordion>
379
+
380
+ <Accordion title="Mail / charge ran again after resume">
381
+ The side effect was outside `fx.step`. Wrap provider calls in uniquely named steps so replay
382
+ returns the journaled value.
383
+ </Accordion>
384
+
385
+ <Accordion title="Connection held across sleep">
386
+ `fx.using` is same-attempt cleanup — do not hold handles across `fx.clock.sleep`. Acquire again
387
+ after wake.
388
+ </Accordion>
389
+
390
+ <Accordion title="ClockResourceNotFoundError on wake">
391
+ Cause: `run "{id}" not found`. The wake-early target is missing or not `sleeping` — check the run
392
+ id from Console / durable result.
393
+ </Accordion>
394
+
395
+ <Accordion title="fx.call of a durable sleeper returned undefined">
396
+ The callee parked. Sleep on the root Flow, or emit to a durable consumer instead of calling a
397
+ sleeper inline.
398
+ </Accordion>
399
+
400
+ <Accordion title="Unknown duration wakes immediately">
401
+ Strings that do not match `integer + ms|s|m|h|d` parse as `0` ms. Use `"8h"`, not `"8 hours"` or
402
+ `"1w"`.
403
+ </Accordion>
404
+
405
+ <Accordion title='journal: run "…" is leased by another instance'>
406
+ Resume lost the lease race (`JournalLeaseBusy`). The other holder continues; this instance skips.
407
+ Shared `postgres` journal + default **30s** lease — same physics as Signal claims.
408
+ </Accordion>
409
+
410
+ <Accordion title="GET /_/ready is 503 reason orphan_scan">
411
+ Boot is still reclaiming `running` / `sleeping` / `compensating` rows with no live lease. Wait for
412
+ the orphan scan; future sleeps stay scheduled until `wakeAt`.
413
+ </Accordion>
414
+
415
+ </Accordions>
416
+
417
+ ## Learn more
418
+
419
+ - [Workflows](/docs/elements/flow/workflows) — `durable`, `fx.step`, compensate, full sleep section
420
+ - [HTTP](/docs/elements/flow/http) — request envelope; `204` from park / `undefined`
421
+ - [Clock overview](/docs/elements/clock) — schedules and `fx.clock` helpers
422
+ - [Schedules](/docs/elements/clock/schedules) — cron / every (calendar time, not durable pause)
423
+ - [fx](/docs/reference/fx) — `fx.clock.sleep`, `fx.step`, `fx.using`
424
+ - [Configuration](/docs/reference/configuration) — `drivers.journal`
425
+ - [Errors](/docs/reference/errors) — `ClockResourceNotFoundError`
426
+
427
+ ## Next
428
+
429
+ <Cards>
430
+ <Card
431
+ title="Durable Workflows"
432
+ description="Step journaling, undo, and multi-day runs."
433
+ href="/docs/elements/flow/workflows"
434
+ />
435
+ <Card
436
+ title="Schedules"
437
+ description="Cron helpers, intervals, and IANA timezones."
438
+ href="/docs/elements/clock/schedules"
439
+ />
440
+ <Card
441
+ title="Clock Overview"
442
+ description="Return to the Clock element overview."
443
+ href="/docs/elements/clock"
444
+ />
445
+ </Cards>