okengine 0.18.4 → 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 (512) 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/index.mdx +25 -6
  5. package/site/content/docs/ai/llms-txt.mdx +1 -1
  6. package/site/content/docs/ai/meta.json +1 -1
  7. package/site/content/docs/ai/skills.mdx +4 -1
  8. package/site/content/docs/ai/try-it.mdx +58 -0
  9. package/site/content/docs/client/auth.mdx +208 -0
  10. package/site/content/docs/client/calling.mdx +451 -0
  11. package/site/content/docs/client/index.mdx +209 -0
  12. package/site/content/docs/client/live.mdx +234 -0
  13. package/site/content/docs/client/meta.json +5 -0
  14. package/site/content/docs/client/react.mdx +249 -0
  15. package/site/content/docs/elements/ai/agents.mdx +232 -0
  16. package/site/content/docs/elements/ai/index.mdx +341 -0
  17. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  18. package/site/content/docs/elements/ai/meta.json +5 -0
  19. package/site/content/docs/elements/ai/models.mdx +283 -0
  20. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  21. package/site/content/docs/elements/channel/email.mdx +266 -0
  22. package/site/content/docs/elements/channel/index.mdx +344 -0
  23. package/site/content/docs/elements/channel/meta.json +5 -0
  24. package/site/content/docs/elements/channel/push.mdx +218 -0
  25. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  26. package/site/content/docs/elements/channel/sms.mdx +264 -0
  27. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  28. package/site/content/docs/elements/clock/index.mdx +300 -0
  29. package/site/content/docs/elements/clock/meta.json +5 -0
  30. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  31. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  32. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  33. package/site/content/docs/elements/flow/http.mdx +1080 -0
  34. package/site/content/docs/elements/flow/index.mdx +618 -0
  35. package/site/content/docs/elements/flow/meta.json +5 -0
  36. package/site/content/docs/elements/flow/routing.mdx +559 -0
  37. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  38. package/site/content/docs/elements/gate/auth.mdx +371 -0
  39. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  40. package/site/content/docs/elements/gate/index.mdx +418 -0
  41. package/site/content/docs/elements/gate/meta.json +5 -0
  42. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  43. package/site/content/docs/elements/gate/rls.mdx +303 -0
  44. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  45. package/site/content/docs/elements/index.mdx +52 -11
  46. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  47. package/site/content/docs/elements/signal/index.mdx +352 -0
  48. package/site/content/docs/elements/signal/live.mdx +590 -0
  49. package/site/content/docs/elements/signal/meta.json +5 -0
  50. package/site/content/docs/elements/signal/once.mdx +596 -0
  51. package/site/content/docs/elements/store/files.mdx +659 -0
  52. package/site/content/docs/elements/store/index.mdx +310 -0
  53. package/site/content/docs/elements/store/kv.mdx +629 -0
  54. package/site/content/docs/elements/store/meta.json +5 -0
  55. package/site/content/docs/elements/store/search.mdx +946 -0
  56. package/site/content/docs/elements/store/sql.mdx +937 -0
  57. package/site/content/docs/elements/vault/config.mdx +256 -0
  58. package/site/content/docs/elements/vault/index.mdx +356 -0
  59. package/site/content/docs/elements/vault/meta.json +5 -0
  60. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  61. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  62. package/site/content/docs/index.mdx +78 -30
  63. package/site/content/docs/meta.json +11 -8
  64. package/site/content/docs/plugins/cors.mdx +2 -1
  65. package/site/content/docs/plugins/csrf.mdx +4 -1
  66. package/site/content/docs/plugins/headers.mdx +2 -1
  67. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  68. package/site/content/docs/plugins/magic-link.mdx +6 -0
  69. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  70. package/site/content/docs/plugins/oauth.mdx +1 -1
  71. package/site/content/docs/plugins/otp.mdx +12 -1
  72. package/site/content/docs/plugins/passkey.mdx +39 -15
  73. package/site/content/docs/plugins/two-factor.mdx +91 -34
  74. package/site/content/docs/plugins/username.mdx +1 -1
  75. package/site/content/docs/recipes/caddy.mdx +3 -3
  76. package/site/content/docs/recipes/index.mdx +18 -28
  77. package/site/content/docs/recipes/mailpit.mdx +1 -1
  78. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  79. package/site/content/docs/recipes/meta.json +1 -4
  80. package/site/content/docs/recipes/nginx.mdx +2 -2
  81. package/site/content/docs/recipes/openrouter.mdx +283 -0
  82. package/site/content/docs/recipes/pgdog.mdx +3 -3
  83. package/site/content/docs/recipes/postgres.mdx +1 -2
  84. package/site/content/docs/recipes/rustfs.mdx +2 -2
  85. package/site/content/docs/recipes/traefik.mdx +3 -3
  86. package/site/content/docs/reference/cli.mdx +231 -0
  87. package/site/content/docs/reference/configuration.mdx +30 -10
  88. package/site/content/docs/reference/environment-variables.mdx +93 -20
  89. package/site/content/docs/reference/errors.mdx +132 -29
  90. package/site/content/docs/reference/fx.mdx +137 -73
  91. package/site/content/docs/reference/index.mdx +13 -21
  92. package/site/content/docs/reference/meta.json +4 -5
  93. package/site/content/docs/reference/okid.mdx +42 -17
  94. package/site/content/docs/reference/plugins.mdx +4 -3
  95. package/site/content/docs/reference/security.mdx +197 -0
  96. package/site/content/docs/understand/meta.json +5 -0
  97. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  98. package/site/content/docs/understand/the-model.mdx +32 -0
  99. package/site/content/docs/understand/the-problem.mdx +74 -0
  100. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  101. package/src/auth/api-keys.ts +2 -1
  102. package/src/auth/bindings.ts +64 -16
  103. package/src/auth/gate-auth.test.ts +6 -1
  104. package/src/auth/identity.ts +152 -5
  105. package/src/auth/index.ts +29 -0
  106. package/src/auth/invites.ts +2 -1
  107. package/src/auth/method-context.ts +41 -0
  108. package/src/auth/oauth-as/crypto.ts +2 -1
  109. package/src/auth/oauth-as/stores.ts +2 -1
  110. package/src/auth/operator.ts +2 -1
  111. package/src/auth/sessions-jwt.test.ts +77 -0
  112. package/src/auth/sessions.ts +20 -4
  113. package/src/auth/tenants.ts +3 -2
  114. package/src/auth/two-factor-challenge.test.ts +61 -0
  115. package/src/auth/two-factor-challenge.ts +284 -0
  116. package/src/auth/verification.ts +5 -0
  117. package/src/bench/REPORT.md +49 -0
  118. package/src/bench/g03-signal-once.bench.ts +1 -1
  119. package/src/bench/g10-observability-contention.bench.ts +1 -1
  120. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  121. package/src/bench/load-app.ts +2 -10
  122. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  123. package/src/cli/ai-setup/apply.ts +294 -52
  124. package/src/cli/ai-setup/catalog.ts +238 -1342
  125. package/src/cli/ai-setup/index.ts +14 -99
  126. package/src/cli/ai-setup/prompts.ts +60 -443
  127. package/src/cli/ask-seed.test.ts +96 -0
  128. package/src/cli/ask-seed.ts +82 -0
  129. package/src/cli/ask-vault-gaps.test.ts +84 -0
  130. package/src/cli/ask-vault-gaps.ts +146 -0
  131. package/src/cli/build.ts +2 -2
  132. package/src/cli/client-add.test.ts +26 -1
  133. package/src/cli/client-add.ts +106 -27
  134. package/src/cli/competitor-mention-removal.test.ts +1 -1
  135. package/src/cli/db-seed.ts +2 -0
  136. package/src/cli/db.ts +150 -11
  137. package/src/cli/dev.ts +119 -211
  138. package/src/cli/docker-clean.ts +2 -2
  139. package/src/cli/docker-cli.test.ts +1 -1
  140. package/src/cli/doctor-diff.ts +4 -2
  141. package/src/cli/doctor-pii.test.ts +1 -1
  142. package/src/cli/doctor.ts +14 -1
  143. package/src/cli/hero-meta.test.ts +4 -2
  144. package/src/cli/load-config.images.test.ts +8 -10
  145. package/src/cli/load-config.ts +1 -1
  146. package/src/cli/registry.ts +22 -10
  147. package/src/cli/replay.ts +3 -1
  148. package/src/cli/start.ts +1 -1
  149. package/src/cli/tui/keys.ts +2 -3
  150. package/src/client/auth/cookies.ts +74 -0
  151. package/src/client/auth/create-auth-client.ts +636 -0
  152. package/src/client/auth/denials.ts +99 -0
  153. package/src/client/auth/session.ts +283 -0
  154. package/src/client/auth.test.ts +251 -0
  155. package/src/client/auth.ts +39 -114
  156. package/src/client/create-with-session.ts +245 -0
  157. package/src/client/create.ts +51 -5
  158. package/src/client/index.ts +11 -1
  159. package/src/client/live.ts +11 -79
  160. package/src/client/notes-contract.test.ts +5 -10
  161. package/src/client/sse.ts +137 -0
  162. package/src/client/stream.ts +147 -0
  163. package/src/client/transport.test.ts +32 -0
  164. package/src/client/transport.ts +123 -26
  165. package/src/client/types.ts +118 -14
  166. package/src/client-react/index.ts +185 -24
  167. package/src/client-react/use-live-query.ts +13 -3
  168. package/src/compiler/aot.test.ts +7 -4
  169. package/src/compiler/effects-embed.test.ts +56 -0
  170. package/src/compiler/effects-fetch.test.ts +43 -0
  171. package/src/compiler/effects-infer.ts +58 -2
  172. package/src/compiler/extract.test.ts +258 -44
  173. package/src/compiler/extract.ts +566 -48
  174. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  175. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  176. package/src/compiler/fixtures/skyport.expected.json +4 -4
  177. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  178. package/src/compiler/response.ts +2 -2
  179. package/src/compiler/search-writer-isolation.test.ts +40 -0
  180. package/src/config/index.ts +11 -0
  181. package/src/console/server/app.ts +17 -23
  182. package/src/console/server/bind.ts +4 -0
  183. package/src/console/server/console.test.ts +2 -2
  184. package/src/console/server/flows-invoke.test.ts +50 -34
  185. package/src/console/server/flows.ts +436 -255
  186. package/src/console/server/runs-ingest.test.ts +6 -3
  187. package/src/console/server/serve.ts +1 -1
  188. package/src/console/server/signals.test.ts +1 -5
  189. package/src/console/server/signals.ts +8 -6
  190. package/src/console/server/state.ts +6 -1
  191. package/src/console/server/store.ts +1 -1
  192. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  193. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  194. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  195. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  196. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  197. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  198. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  199. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  200. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  201. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  202. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  203. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  204. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  205. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  206. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  207. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  208. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  209. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  210. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  211. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  212. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  213. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  214. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  215. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  216. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  217. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  218. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  219. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  220. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  221. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  222. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  223. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  224. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  225. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  226. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  227. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  228. package/src/console/ui-next/dist/index.html +6 -13
  229. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  230. package/src/console/ui-next/src/client.ts +7 -2
  231. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  232. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  233. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  235. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  236. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  237. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  238. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  239. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  240. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  241. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  242. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  243. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  244. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  245. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  246. package/src/docker/ai-model-status.test.ts +1 -12
  247. package/src/docker/ai-model-status.ts +10 -38
  248. package/src/docker/compose-up.test.ts +100 -0
  249. package/src/docker/compose-up.ts +292 -0
  250. package/src/docker/compose.ts +4 -14
  251. package/src/docker/derive.ts +9 -34
  252. package/src/docker/docker.test.ts +16 -261
  253. package/src/docker/images-config.test.ts +13 -25
  254. package/src/docker/index.ts +1 -24
  255. package/src/docker/recipes/index.ts +0 -23
  256. package/src/docker/recipes/pgdog.ts +6 -4
  257. package/src/docker/stack-id.test.ts +2 -2
  258. package/src/docker/stack-id.ts +0 -1
  259. package/src/docker/types.ts +2 -2
  260. package/src/drivers/ai-anthropic.ts +10 -0
  261. package/src/drivers/ai-openai-compatible.ts +34 -7
  262. package/src/drivers/ai-providers.test.ts +0 -107
  263. package/src/drivers/ai-stream.test.ts +0 -34
  264. package/src/drivers/ai-types.ts +17 -8
  265. package/src/drivers/channel-fcm.ts +6 -1
  266. package/src/drivers/channel-msegat.ts +6 -1
  267. package/src/drivers/channel-resend.ts +5 -1
  268. package/src/drivers/channel-smtp.ts +5 -1
  269. package/src/drivers/channel-sndr.ts +10 -1
  270. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  271. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  272. package/src/drivers/channel-taqnyat.ts +6 -1
  273. package/src/drivers/channel-types.ts +10 -0
  274. package/src/drivers/channel-unifonic.ts +6 -1
  275. package/src/drivers/channel-wa-cloud.ts +6 -1
  276. package/src/drivers/channel-webpush.ts +6 -1
  277. package/src/drivers/external.ts +33 -0
  278. package/src/drivers/index.ts +0 -10
  279. package/src/drivers/meilisearch.ts +6 -0
  280. package/src/drivers/oauth-types.ts +4 -0
  281. package/src/drivers/postgres.test.ts +74 -3
  282. package/src/drivers/postgres.ts +175 -6
  283. package/src/drivers/signal-types.ts +5 -5
  284. package/src/drivers/types.ts +7 -0
  285. package/src/drivers/vault-types.ts +5 -0
  286. package/src/elements/ai/declare.ts +17 -4
  287. package/src/elements/ai/eval.ts +1 -1
  288. package/src/elements/ai/mcp-http.ts +1 -1
  289. package/src/elements/ai/pii.ts +1 -1
  290. package/src/elements/ai/providers.test.ts +289 -0
  291. package/src/elements/ai/providers.ts +169 -0
  292. package/src/elements/ai/runtime.ts +68 -5
  293. package/src/elements/ai/schema.ts +2 -2
  294. package/src/elements/ai.test.ts +7 -7
  295. package/src/elements/ai.ts +17 -1
  296. package/src/elements/channel/runtime.ts +105 -12
  297. package/src/elements/clock/cron-fields.test.ts +144 -0
  298. package/src/elements/clock/cron-fields.ts +185 -0
  299. package/src/elements/clock/declare.ts +247 -3
  300. package/src/elements/clock.ts +21 -1
  301. package/src/elements/index.ts +15 -0
  302. package/src/elements/signal/chaos-child.ts +1 -2
  303. package/src/elements/signal/declare.ts +65 -37
  304. package/src/elements/signal/delivery-modes.test.ts +11 -31
  305. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  306. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  307. package/src/elements/signal/key-ordering.test.ts +6 -26
  308. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  309. package/src/elements/signal/optional-emit.test.ts +6 -9
  310. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  311. package/src/elements/signal/orphan-messages.test.ts +4 -15
  312. package/src/elements/signal/reconcile.test.ts +2 -2
  313. package/src/elements/signal/runtime.ts +1 -1
  314. package/src/elements/signal/schema-emit.test.ts +4 -8
  315. package/src/elements/signal.test.ts +24 -49
  316. package/src/elements/signal.ts +9 -2
  317. package/src/elements/store/domain-ddl.test.ts +1 -1
  318. package/src/elements/store/live-http.test.ts +9 -4
  319. package/src/elements/store/prepare-row.test.ts +123 -0
  320. package/src/elements/store/resource.ts +43 -12
  321. package/src/elements/store/schema-decl.ts +117 -0
  322. package/src/elements/store/search-backfill.ts +205 -0
  323. package/src/elements/store/search-bind.ts +66 -0
  324. package/src/elements/store/search-bm25.ts +78 -0
  325. package/src/elements/store/search-ddl.ts +156 -0
  326. package/src/elements/store/search-embed-flow.ts +141 -0
  327. package/src/elements/store/search-errors.ts +34 -0
  328. package/src/elements/store/search-fusion.ts +112 -0
  329. package/src/elements/store/search-lsh.ts +179 -0
  330. package/src/elements/store/search-runtime.ts +300 -0
  331. package/src/elements/store/search.test.ts +144 -0
  332. package/src/elements/store/sql-session.test.ts +1 -0
  333. package/src/elements/store/sql-session.ts +83 -3
  334. package/src/elements/store/table.ts +23 -2
  335. package/src/elements/store/upsert-app.test.ts +1 -3
  336. package/src/elements/store.ts +50 -0
  337. package/src/full.ts +4 -2
  338. package/src/http.ts +4 -1
  339. package/src/i18n/catalogs/ar.ts +14 -6
  340. package/src/i18n/catalogs/en.ts +14 -6
  341. package/src/index.ts +6 -1
  342. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  343. package/src/kernel/adopt-routes.ts +9 -1
  344. package/src/kernel/app-auth.ts +5 -0
  345. package/src/kernel/app.ts +102 -9
  346. package/src/kernel/auto-cache.test.ts +6 -12
  347. package/src/kernel/auto-registry.test.ts +3 -3
  348. package/src/kernel/boot-bind/ai.test.ts +22 -19
  349. package/src/kernel/boot-bind/ai.ts +5 -43
  350. package/src/kernel/boot-bind/clock.ts +23 -5
  351. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  352. package/src/kernel/boot.test.ts +11 -6
  353. package/src/kernel/boot.ts +66 -16
  354. package/src/kernel/boundary-contract.ts +93 -0
  355. package/src/kernel/budget.test.ts +1 -1
  356. package/src/kernel/call.ts +89 -0
  357. package/src/kernel/capability.ts +6 -0
  358. package/src/kernel/client-descriptor.ts +123 -0
  359. package/src/kernel/clock-timezone.test.ts +80 -0
  360. package/src/kernel/correlation.test.ts +1 -1
  361. package/src/kernel/dry-run.ts +11 -8
  362. package/src/kernel/effects-stamping.test.ts +42 -9
  363. package/src/kernel/effects.test.ts +4 -2
  364. package/src/kernel/effects.ts +51 -9
  365. package/src/kernel/errors-channel.ts +17 -0
  366. package/src/kernel/errors-live-resume.ts +3 -2
  367. package/src/kernel/errors-tenant.ts +7 -4
  368. package/src/kernel/errors.registry-helpers.ts +96 -0
  369. package/src/kernel/errors.registry.test.ts +139 -25
  370. package/src/kernel/errors.ts +102 -23
  371. package/src/kernel/external-effects.test.ts +196 -0
  372. package/src/kernel/flow.test.ts +13 -4
  373. package/src/kernel/flow.ts +69 -71
  374. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  375. package/src/kernel/fx-dead-letters.test.ts +3 -3
  376. package/src/kernel/fx-fetch.ts +55 -0
  377. package/src/kernel/fx-live-stream.ts +2 -2
  378. package/src/kernel/fx-live.test.ts +8 -8
  379. package/src/kernel/fx.test.ts +17 -11
  380. package/src/kernel/fx.ts +180 -57
  381. package/src/kernel/horizontal-child.ts +1 -1
  382. package/src/kernel/http-query.test.ts +3 -6
  383. package/src/kernel/index.ts +13 -3
  384. package/src/kernel/instance-id.ts +1 -1
  385. package/src/kernel/instances.test.ts +40 -0
  386. package/src/kernel/instances.ts +47 -9
  387. package/src/kernel/live-http.test.ts +6 -7
  388. package/src/kernel/live-http.ts +6 -2
  389. package/src/kernel/live-resume.test.ts +1 -1
  390. package/src/kernel/mcp-tool.test.ts +3 -3
  391. package/src/kernel/on.ts +98 -4
  392. package/src/kernel/pipeline.test.ts +12 -15
  393. package/src/kernel/plugin-elements.test.ts +1 -1
  394. package/src/kernel/stamp-http.test.ts +3 -3
  395. package/src/kernel/triggers.ts +210 -95
  396. package/src/kernel-entry.ts +0 -1
  397. package/src/manifest/diff.ts +11 -1
  398. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  399. package/src/manifest/types.ts +46 -2
  400. package/src/mcp/docs-index.ts +3 -3
  401. package/src/mcp/docs-mcp.test.ts +2 -2
  402. package/src/mcp/docs-tools.ts +1 -1
  403. package/src/okid.test.ts +56 -0
  404. package/src/okid.ts +55 -11
  405. package/src/plugins/anonymous.ts +8 -4
  406. package/src/plugins/auth/shared.ts +27 -3
  407. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  408. package/src/plugins/auth-methods.security.test.ts +561 -23
  409. package/src/plugins/config-source.ts +1 -1
  410. package/src/plugins/csrf.test.ts +65 -0
  411. package/src/plugins/index.ts +2 -0
  412. package/src/plugins/magic-link.ts +36 -16
  413. package/src/plugins/oauth/shared.ts +3 -1
  414. package/src/plugins/oauth.ts +22 -14
  415. package/src/plugins/otp.ts +37 -21
  416. package/src/plugins/passkey-webauthn.ts +9 -6
  417. package/src/plugins/passkey.ts +98 -26
  418. package/src/plugins/pre-account-hijack.test.ts +223 -0
  419. package/src/plugins/two-factor.ts +466 -37
  420. package/src/plugins/username.ts +19 -7
  421. package/src/release/build-lib.ts +1 -0
  422. package/src/release/limits.ts +2 -2
  423. package/src/release/measure.ts +1 -1
  424. package/src/runs/collect.test.ts +0 -2
  425. package/src/runtime/json-code-block.test.ts +250 -20
  426. package/src/runtime/json-code-block.ts +1261 -41
  427. package/src/term.test.ts +1 -1
  428. package/src/test/create-test-app.test.ts +12 -12
  429. package/src/test/live-signals.test.ts +6 -6
  430. package/src/test/provisions.integration.test.ts +10 -14
  431. package/src/test/reset-element-registries.ts +1 -1
  432. package/src/test/tenant-isolation.test.ts +12 -6
  433. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  434. package/site/content/docs/deployment/docker.mdx +0 -227
  435. package/site/content/docs/deployment/index.mdx +0 -83
  436. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  437. package/site/content/docs/deployment/meta.json +0 -5
  438. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  439. package/site/content/docs/elements/ai.mdx +0 -385
  440. package/site/content/docs/elements/channel.mdx +0 -346
  441. package/site/content/docs/elements/clock.mdx +0 -244
  442. package/site/content/docs/elements/flow.mdx +0 -420
  443. package/site/content/docs/elements/gate.mdx +0 -436
  444. package/site/content/docs/elements/signal.mdx +0 -380
  445. package/site/content/docs/elements/store.mdx +0 -1099
  446. package/site/content/docs/elements/vault.mdx +0 -405
  447. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  448. package/site/content/docs/get-started/index.mdx +0 -43
  449. package/site/content/docs/get-started/installation.mdx +0 -220
  450. package/site/content/docs/get-started/introduction.mdx +0 -132
  451. package/site/content/docs/get-started/meta.json +0 -13
  452. package/site/content/docs/get-started/project-structure.mdx +0 -925
  453. package/site/content/docs/get-started/testing.mdx +0 -328
  454. package/site/content/docs/get-started/why.mdx +0 -162
  455. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  456. package/site/content/docs/recipes/ollama.mdx +0 -142
  457. package/site/content/docs/recipes/sglang.mdx +0 -105
  458. package/site/content/docs/recipes/vllm.mdx +0 -106
  459. package/site/content/docs/reference/cli.md +0 -232
  460. package/site/content/docs/reference/client.mdx +0 -469
  461. package/site/content/docs/reference/security.md +0 -74
  462. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  463. package/src/cli/ai-setup/recommend.test.ts +0 -225
  464. package/src/cli/ai-setup/recommend.ts +0 -225
  465. package/src/cli/dev-controls.test.ts +0 -122
  466. package/src/cli/dev-controls.ts +0 -164
  467. package/src/cli/tui/DevLive.tsx +0 -126
  468. package/src/console/ui-next/dist/assets/access-page-De7Lc2JC.js +0 -4
  469. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  470. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  471. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  472. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  473. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  474. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  475. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  476. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  477. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  478. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  479. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  480. package/src/console/ui-next/dist/assets/flows-page-RGy7VEA_.js +0 -1
  481. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  482. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  483. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  484. package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
  485. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  486. package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.js +0 -4
  487. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  488. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  489. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  490. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  491. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  492. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  493. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  494. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  495. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  496. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  497. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  498. package/src/console/ui-next/dist/assets/units-page-4rHOePuE.js +0 -1
  499. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  500. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  501. package/src/console/ui-next/dist/assets/vault-page-DISPgxLM.js +0 -2
  502. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  503. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  504. package/src/docker/ollama-pull.ts +0 -232
  505. package/src/docker/recipes/llama-cpp.ts +0 -298
  506. package/src/docker/recipes/ollama.ts +0 -44
  507. package/src/docker/recipes/sglang.ts +0 -55
  508. package/src/docker/recipes/vllm.ts +0 -44
  509. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  510. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  511. package/src/drivers/ai-ollama.ts +0 -389
  512. package/src/drivers/ollama.ts +0 -14
@@ -6,11 +6,14 @@
6
6
  */
7
7
 
8
8
  import { flattenGateArgs, GATE_PUBLIC_NAME, type GateAllDecl } from "../elements/gate/flatten.ts";
9
+ import type { ClockDecl } from "../elements/clock/declare.ts";
10
+ import type { BoundaryContract } from "./boundary-contract.ts";
9
11
  import type { NamedRef } from "./fx.ts";
10
12
  import { HTTP_PATH_PENDING, type HttpPathPending } from "./http-path-pending.ts";
11
13
  import { lazyRequire } from "./lazy-require.ts";
12
14
 
13
15
  export { HTTP_PATH_PENDING, isPendingHttpPath, type HttpPathPending } from "./http-path-pending.ts";
16
+ export type { BoundaryContract } from "./boundary-contract.ts";
14
17
 
15
18
  /** HTTP methods accepted by {@link http}. */
16
19
  export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "QUERY";
@@ -27,15 +30,25 @@ export type GateAttach<T> = (...gates: GateArg[]) => T;
27
30
  /**
28
31
  * HTTP trigger value. Method and path are literal type parameters so
29
32
  * `typeof app` / the client can derive REST wire shape from the declaration.
33
+ * `C` preserves the invoke-contract bag for {@link on} → `$routes` typing.
30
34
  *
31
35
  * @typeParam M - HTTP method literal
32
36
  * @typeParam P - Path template literal (`/notes/:id`)
37
+ * @typeParam C - Invoke contract bag (or `undefined` when omitted)
33
38
  */
34
- export interface HttpTrigger<M extends HttpMethod = HttpMethod, P extends string = string> {
39
+ export interface HttpTrigger<
40
+ M extends HttpMethod = HttpMethod,
41
+ P extends string = string,
42
+ // Default `any` so `Trigger` accepts contracted + contractless HTTP triggers;
43
+ // verb overloads still pin `C` to `undefined` or the authored bag.
44
+ C extends BoundaryContract | undefined = any,
45
+ > {
35
46
  readonly kind: "http";
36
47
  readonly method: M;
37
48
  readonly path: P;
38
49
  readonly gates: readonly GateRef[];
50
+ /** Invoke contract authored on the verb options bag. */
51
+ readonly contract?: C extends undefined ? never : C;
39
52
  /**
40
53
  * Signal this GET exposes as a live SSE feed (`undefined` when not a live route).
41
54
  */
@@ -43,17 +56,17 @@ export interface HttpTrigger<M extends HttpMethod = HttpMethod, P extends string
43
56
  /**
44
57
  * Attach gates (registration order). `gate.all` handles and arrays flatten.
45
58
  */
46
- readonly gate: GateAttach<HttpTrigger<M, P>>;
59
+ readonly gate: GateAttach<HttpTrigger<M, P, C>>;
47
60
  /**
48
61
  * Attach the unauthenticated public sentinel.
49
62
  */
50
- public(): HttpTrigger<M, P>;
63
+ public(): HttpTrigger<M, P, C>;
51
64
  /**
52
65
  * Expose a `delivery: "live"` signal as SSE on this GET.
53
66
  *
54
67
  * @param signal - Live signal handle
55
68
  */
56
- live(signal: SignalSource): LiveHttpTrigger<M, P>;
69
+ live(signal: SignalSource): LiveHttpTrigger<M, P, C>;
57
70
  /**
58
71
  * Declare a live query surface over a table on this GET: same CDC +
59
72
  * per-subscriber RLS classification physics as
@@ -62,7 +75,7 @@ export interface HttpTrigger<M extends HttpMethod = HttpMethod, P extends string
62
75
  *
63
76
  * @param table - `store.schema.table` (or drizzle/table handle) binding
64
77
  */
65
- live(table: object): LiveHttpTrigger<M, P>;
78
+ live(table: object): LiveHttpTrigger<M, P, C>;
66
79
  }
67
80
 
68
81
  /**
@@ -73,14 +86,23 @@ export interface HttpTrigger<M extends HttpMethod = HttpMethod, P extends string
73
86
  *
74
87
  * @typeParam M - HTTP method literal
75
88
  * @typeParam P - Path template literal
89
+ * @typeParam C - Invoke contract bag (or `undefined` when omitted)
76
90
  */
77
91
  export interface LiveHttpTrigger<
78
92
  M extends HttpMethod = "GET",
79
93
  P extends string = string,
80
- > extends HttpTrigger<M, P> {
94
+ C extends BoundaryContract | undefined = any,
95
+ > extends HttpTrigger<M, P, C> {
81
96
  readonly liveSignal: SignalSource;
82
- readonly gate: GateAttach<LiveHttpTrigger<M, P>>;
83
- public(): LiveHttpTrigger<M, P>;
97
+ readonly gate: GateAttach<LiveHttpTrigger<M, P, C>>;
98
+ public(): LiveHttpTrigger<M, P, C>;
99
+ }
100
+
101
+ /** Clock / cron trigger (`clock("daily", { every: "1d" })`). */
102
+ export interface ClockTrigger {
103
+ readonly kind: "clock";
104
+ readonly name: string;
105
+ readonly clock?: ClockDecl;
84
106
  }
85
107
 
86
108
  /** Clock / interval trigger (`every("1h")`). */
@@ -124,17 +146,20 @@ export interface InternalTrigger {
124
146
  * Gates are required (typically `gate.auth` + `gate.scope(...)`) exactly
125
147
  * like sensitive HTTP routes.
126
148
  */
127
- export interface McpToolTrigger {
149
+ export interface McpToolTrigger<C extends BoundaryContract | undefined = any> {
128
150
  readonly kind: "mcp";
129
151
  /** Tool name exposed in MCP `tools/list`. */
130
152
  readonly name: string;
131
153
  readonly gates: readonly GateRef[];
132
- readonly gate: GateAttach<McpToolTrigger>;
154
+ /** Invoke contract authored on `mcp.tool(name, bag)`. */
155
+ readonly contract?: C extends undefined ? never : C;
156
+ readonly gate: GateAttach<McpToolTrigger<C>>;
133
157
  }
134
158
 
135
159
  /** Discriminated union of all trigger kinds. */
136
160
  export type Trigger =
137
161
  | HttpTrigger
162
+ | ClockTrigger
138
163
  | EveryTrigger
139
164
  | SignalAsTrigger
140
165
  | CdcTrigger
@@ -164,34 +189,54 @@ export function createGateAttach<T>(
164
189
  * @param path - Route path
165
190
  * @param gates - Attached gate refs
166
191
  * @param liveSignal - Live signal when `.live(signal)` was applied
192
+ * @param contract - Invoke contract bag from the verb options
167
193
  */
168
- export function createHttpTrigger<M extends HttpMethod, P extends string>(
194
+ export function createHttpTrigger<
195
+ M extends HttpMethod,
196
+ P extends string,
197
+ C extends BoundaryContract | undefined = undefined,
198
+ >(
169
199
  method: M,
170
200
  path: P,
171
201
  gates: readonly GateRef[],
172
202
  liveSignal: SignalSource,
173
- ): LiveHttpTrigger<M, P>;
174
- export function createHttpTrigger<M extends HttpMethod, P extends string>(
203
+ contract?: C,
204
+ ): LiveHttpTrigger<M, P, C>;
205
+ export function createHttpTrigger<
206
+ M extends HttpMethod,
207
+ P extends string,
208
+ C extends BoundaryContract | undefined = undefined,
209
+ >(
175
210
  method: M,
176
211
  path: P,
177
212
  gates?: readonly GateRef[],
178
213
  liveSignal?: SignalSource,
179
- ): HttpTrigger<M, P>;
180
- export function createHttpTrigger<M extends HttpMethod, P extends string>(
214
+ contract?: C,
215
+ ): HttpTrigger<M, P, C>;
216
+ export function createHttpTrigger<
217
+ M extends HttpMethod,
218
+ P extends string,
219
+ C extends BoundaryContract | undefined = undefined,
220
+ >(
181
221
  method: M,
182
222
  path: P,
183
223
  gates: readonly GateRef[] = [],
184
224
  liveSignal?: SignalSource,
185
- ): HttpTrigger<M, P> {
186
- const trigger: HttpTrigger<M, P> = {
187
- kind: "http",
225
+ contract?: C,
226
+ ): HttpTrigger<M, P, C> {
227
+ const trigger = {
228
+ kind: "http" as const,
188
229
  method,
189
230
  path,
190
231
  gates,
232
+ ...(contract !== undefined ? { contract } : {}),
191
233
  ...(liveSignal !== undefined ? { liveSignal } : {}),
192
- gate: createGateAttach((next) => createHttpTrigger(method, path, next, liveSignal), gates),
234
+ gate: createGateAttach(
235
+ (next) => createHttpTrigger(method, path, next, liveSignal, contract),
236
+ gates,
237
+ ),
193
238
  public() {
194
- return createHttpTrigger(method, path, [...gates, GATE_PUBLIC_NAME], liveSignal);
239
+ return createHttpTrigger(method, path, [...gates, GATE_PUBLIC_NAME], liveSignal, contract);
195
240
  },
196
241
  live(source: SignalSource | object) {
197
242
  if (typeof source === "object" && !("name" in source)) {
@@ -203,12 +248,12 @@ export function createHttpTrigger<M extends HttpMethod, P extends string>(
203
248
  "table",
204
249
  );
205
250
  const signal = { name: `oke/live/sql:${storeTable.resolveTableName(source)}` };
206
- return createHttpTrigger(method, path, gates, signal);
251
+ return createHttpTrigger(method, path, gates, signal, contract);
207
252
  }
208
- return createHttpTrigger(method, path, gates, source as SignalSource);
253
+ return createHttpTrigger(method, path, gates, source as SignalSource, contract);
209
254
  },
210
255
  };
211
- return trigger;
256
+ return trigger as HttpTrigger<M, P, C>;
212
257
  }
213
258
 
214
259
  /** Flow shape accepted by {@link http.resource} (duck-typed — any FlowDef). */
@@ -272,64 +317,113 @@ function loadHttpResource(): typeof import("./http-resource.ts") {
272
317
  /**
273
318
  * Shape of the {@link http} trigger namespace. Each method keeps `P` as a
274
319
  * generic type parameter so callers (and the client) retain literal path
275
- * types for param extraction.
320
+ * types for param extraction. Invoke contracts use an options bag
321
+ * (`http.post({ in, out })` or `http.post("/notes", { in, out })`); the bag
322
+ * type is preserved so {@link on} can project `in` / `out` / `errors` onto
323
+ * `FlowDef` / `$routes`.
276
324
  */
277
325
  export interface HttpTriggerNamespace {
278
- /**
279
- * Pathless file-tree stamp fills the URL. Unresolved sentinel fails boot.
280
- */
281
- get(): HttpTrigger<"GET", HttpPathPending>;
326
+ /** Pathless — file-tree stamp fills the URL. Unresolved sentinel fails boot. */
327
+ get<C extends BoundaryContract | undefined = undefined>(
328
+ contract?: C,
329
+ ): HttpTrigger<"GET", HttpPathPending, C>;
282
330
  /**
283
331
  * @param path - Route path (`/:id` params supported)
332
+ * @param contract - Invoke contract bag
284
333
  */
285
- get<P extends string>(path: P): HttpTrigger<"GET", P>;
334
+ get<P extends string, C extends BoundaryContract | undefined = undefined>(
335
+ path: P,
336
+ contract?: C,
337
+ ): HttpTrigger<"GET", P, C>;
286
338
  /** Pathless — file-tree stamp fills the URL. */
287
- post(): HttpTrigger<"POST", HttpPathPending>;
339
+ post<C extends BoundaryContract | undefined = undefined>(
340
+ contract?: C,
341
+ ): HttpTrigger<"POST", HttpPathPending, C>;
288
342
  /**
289
343
  * @param path - Route path
344
+ * @param contract - Invoke contract bag
290
345
  */
291
- post<P extends string>(path: P): HttpTrigger<"POST", P>;
346
+ post<P extends string, C extends BoundaryContract | undefined = undefined>(
347
+ path: P,
348
+ contract?: C,
349
+ ): HttpTrigger<"POST", P, C>;
292
350
  /** Pathless — file-tree stamp fills the URL. */
293
- put(): HttpTrigger<"PUT", HttpPathPending>;
351
+ put<C extends BoundaryContract | undefined = undefined>(
352
+ contract?: C,
353
+ ): HttpTrigger<"PUT", HttpPathPending, C>;
294
354
  /**
295
355
  * @param path - Route path
356
+ * @param contract - Invoke contract bag
296
357
  */
297
- put<P extends string>(path: P): HttpTrigger<"PUT", P>;
358
+ put<P extends string, C extends BoundaryContract | undefined = undefined>(
359
+ path: P,
360
+ contract?: C,
361
+ ): HttpTrigger<"PUT", P, C>;
298
362
  /** Pathless — file-tree stamp fills the URL. */
299
- patch(): HttpTrigger<"PATCH", HttpPathPending>;
363
+ patch<C extends BoundaryContract | undefined = undefined>(
364
+ contract?: C,
365
+ ): HttpTrigger<"PATCH", HttpPathPending, C>;
300
366
  /**
301
367
  * @param path - Route path
368
+ * @param contract - Invoke contract bag
302
369
  */
303
- patch<P extends string>(path: P): HttpTrigger<"PATCH", P>;
370
+ patch<P extends string, C extends BoundaryContract | undefined = undefined>(
371
+ path: P,
372
+ contract?: C,
373
+ ): HttpTrigger<"PATCH", P, C>;
304
374
  /** Pathless — file-tree stamp fills the URL. */
305
- delete(): HttpTrigger<"DELETE", HttpPathPending>;
375
+ delete<C extends BoundaryContract | undefined = undefined>(
376
+ contract?: C,
377
+ ): HttpTrigger<"DELETE", HttpPathPending, C>;
306
378
  /**
307
379
  * @param path - Route path
380
+ * @param contract - Invoke contract bag
308
381
  */
309
- delete<P extends string>(path: P): HttpTrigger<"DELETE", P>;
382
+ delete<P extends string, C extends BoundaryContract | undefined = undefined>(
383
+ path: P,
384
+ contract?: C,
385
+ ): HttpTrigger<"DELETE", P, C>;
310
386
  /** Pathless — file-tree stamp fills the URL. */
311
- options(): HttpTrigger<"OPTIONS", HttpPathPending>;
387
+ options<C extends BoundaryContract | undefined = undefined>(
388
+ contract?: C,
389
+ ): HttpTrigger<"OPTIONS", HttpPathPending, C>;
312
390
  /**
313
391
  * @param path - Route path
392
+ * @param contract - Invoke contract bag
314
393
  */
315
- options<P extends string>(path: P): HttpTrigger<"OPTIONS", P>;
394
+ options<P extends string, C extends BoundaryContract | undefined = undefined>(
395
+ path: P,
396
+ contract?: C,
397
+ ): HttpTrigger<"OPTIONS", P, C>;
316
398
  /** Pathless — file-tree stamp fills the URL. */
317
- head(): HttpTrigger<"HEAD", HttpPathPending>;
399
+ head<C extends BoundaryContract | undefined = undefined>(
400
+ contract?: C,
401
+ ): HttpTrigger<"HEAD", HttpPathPending, C>;
318
402
  /**
319
403
  * @param path - Route path
404
+ * @param contract - Invoke contract bag
320
405
  */
321
- head<P extends string>(path: P): HttpTrigger<"HEAD", P>;
406
+ head<P extends string, C extends BoundaryContract | undefined = undefined>(
407
+ path: P,
408
+ contract?: C,
409
+ ): HttpTrigger<"HEAD", P, C>;
322
410
  /**
323
411
  * Safe, idempotent read that carries a JSON body (RFC 10008).
324
412
  * Pathless — file-tree stamp fills the URL.
325
413
  */
326
- query(): HttpTrigger<"QUERY", HttpPathPending>;
414
+ query<C extends BoundaryContract | undefined = undefined>(
415
+ contract?: C,
416
+ ): HttpTrigger<"QUERY", HttpPathPending, C>;
327
417
  /**
328
418
  * Safe, idempotent read that carries a JSON body (RFC 10008).
329
419
  *
330
420
  * @param path - Route path
421
+ * @param contract - Invoke contract bag
331
422
  */
332
- query<P extends string>(path: P): HttpTrigger<"QUERY", P>;
423
+ query<P extends string, C extends BoundaryContract | undefined = undefined>(
424
+ path: P,
425
+ contract?: C,
426
+ ): HttpTrigger<"QUERY", P, C>;
333
427
  /**
334
428
  * Mount a CRUD resource (list/create on `path`, get/update/remove on
335
429
  * `path/:id`) for the `on(http.resource(…))` overload. Chain `.gate(...)`
@@ -344,17 +438,44 @@ export interface HttpTriggerNamespace {
344
438
  live(signal: SignalSource): LiveHttpTrigger<"GET">;
345
439
  }
346
440
 
441
+ /** True when `value` looks like a {@link BoundaryContract} options bag (not a path). */
442
+ function isHttpContractBag(value: unknown): value is BoundaryContract {
443
+ if (typeof value !== "object" || value === null) return false;
444
+ const o = value as Record<string, unknown>;
445
+ return "in" in o || "out" in o || "errors" in o || "breaking" in o;
446
+ }
447
+
347
448
  /** Bind an HTTP verb constructor (`http.get`, `http.query`, …). */
348
449
  function httpVerb<M extends HttpMethod>(
349
450
  method: M,
350
451
  ): {
351
- (): HttpTrigger<M, HttpPathPending>;
352
- <P extends string>(path: P): HttpTrigger<M, P>;
452
+ <C extends BoundaryContract | undefined = undefined>(
453
+ contract?: C,
454
+ ): HttpTrigger<M, HttpPathPending, C>;
455
+ <P extends string, C extends BoundaryContract | undefined = undefined>(
456
+ path: P,
457
+ contract?: C,
458
+ ): HttpTrigger<M, P, C>;
353
459
  } {
354
- return ((path?: string) =>
355
- createHttpTrigger(method, path === undefined ? HTTP_PATH_PENDING : path)) as {
356
- (): HttpTrigger<M, HttpPathPending>;
357
- <P extends string>(path: P): HttpTrigger<M, P>;
460
+ return ((pathOrContract?: string | BoundaryContract, maybeContract?: BoundaryContract) => {
461
+ if (pathOrContract === undefined) {
462
+ return createHttpTrigger(method, HTTP_PATH_PENDING);
463
+ }
464
+ if (typeof pathOrContract === "string") {
465
+ return createHttpTrigger(method, pathOrContract, [], undefined, maybeContract);
466
+ }
467
+ if (isHttpContractBag(pathOrContract)) {
468
+ return createHttpTrigger(method, HTTP_PATH_PENDING, [], undefined, pathOrContract);
469
+ }
470
+ throw new TypeError(`http.${method.toLowerCase()}(…): expected a path string or contract bag`);
471
+ }) as {
472
+ <C extends BoundaryContract | undefined = undefined>(
473
+ contract?: C,
474
+ ): HttpTrigger<M, HttpPathPending, C>;
475
+ <P extends string, C extends BoundaryContract | undefined = undefined>(
476
+ path: P,
477
+ contract?: C,
478
+ ): HttpTrigger<M, P, C>;
358
479
  };
359
480
  }
360
481
 
@@ -378,12 +499,19 @@ export const http: HttpTriggerNamespace = {
378
499
  };
379
500
 
380
501
  /**
381
- * Clock trigger run on an interval (`every("10m")`, `every("1h")`).
502
+ * True when `value` is a declared clock handle (`clock("daily", { every: "1d" })`).
382
503
  *
383
- * @param interval - Duration string
504
+ * @param value - Unknown
384
505
  */
385
- export function every(interval: string): EveryTrigger {
386
- return { kind: "every", interval };
506
+ export function isClockDecl(value: unknown): value is ClockDecl {
507
+ if (typeof value !== "object" || value === null) return false;
508
+ const v = value as Record<string, unknown>;
509
+ return (
510
+ typeof v.name === "string" &&
511
+ !("kind" in v) &&
512
+ !("do" in v) &&
513
+ ("cron" in v || "every" in v || "timezone" in v)
514
+ );
387
515
  }
388
516
 
389
517
  /**
@@ -427,34 +555,6 @@ export function isSignalTriggerSource(value: unknown): value is SignalSource {
427
555
  return true;
428
556
  }
429
557
 
430
- /** Table handle returned by {@link table}. */
431
- export interface TableHandle {
432
- readonly name: string;
433
- /**
434
- * CDC trigger when `column` (or any column) changes.
435
- *
436
- * @param column - Optional column name
437
- */
438
- changed(column?: string): CdcTrigger;
439
- }
440
-
441
- /**
442
- * CDC table handle — `table("orders").changed("status")`.
443
- *
444
- * @param name - Table name
445
- * @param store - Optional store name
446
- */
447
- export function table(name: string, store?: string): TableHandle {
448
- return {
449
- name,
450
- changed(column?: string): CdcTrigger {
451
- return column === undefined
452
- ? { kind: "cdc", table: name, store }
453
- : { kind: "cdc", table: name, column, store };
454
- },
455
- };
456
- }
457
-
458
558
  /**
459
559
  * Explicit internal / call-only trigger.
460
560
  * Prefer an untriggered `flow(name, {…})` when no trigger value is needed.
@@ -462,42 +562,51 @@ export function table(name: string, store?: string): TableHandle {
462
562
  export const internal: InternalTrigger = { kind: "internal" };
463
563
 
464
564
  /**
465
- * MCP tool namespace — `mcp.tool("bookings.create")` marks a flow as an
466
- * explicitly exposed MCP tool for OAuth user-plane clients. Chain `.gate(...)`
467
- * like HTTP triggers; no gates ⇒ not exposed (deny-by-default).
565
+ * MCP tool namespace — `mcp.tool("bookings.create", { in, out })` marks a flow
566
+ * as an explicitly exposed MCP tool for OAuth user-plane clients. Chain
567
+ * `.gate(...)` like HTTP triggers; no gates ⇒ not exposed (deny-by-default).
468
568
  *
469
569
  * @param name - Tool name (namespaced, e.g. `bookings.create`)
470
570
  */
471
571
  export const mcp: {
472
572
  /**
473
573
  * @param name - Tool name
574
+ * @param contract - Invoke contract bag
474
575
  */
475
- tool(name: string): McpToolTrigger;
576
+ tool<C extends BoundaryContract | undefined = undefined>(
577
+ name: string,
578
+ contract?: C,
579
+ ): McpToolTrigger<C>;
476
580
  } = {
477
- tool(name: string): McpToolTrigger {
581
+ tool(name: string, contract?: BoundaryContract): McpToolTrigger {
478
582
  if (typeof name !== "string" || name.trim().length === 0) {
479
583
  throw new TypeError("mcp.tool(name): name is required");
480
584
  }
481
- return withMcpGates(name, []);
585
+ return withMcpGates(name, [], contract);
482
586
  },
483
587
  };
484
588
 
485
589
  /** @internal Attach a resolved gate list onto a fresh {@link McpToolTrigger}. */
486
- function withMcpGates(name: string, gates: readonly GateRef[]): McpToolTrigger {
590
+ function withMcpGates<C extends BoundaryContract | undefined = undefined>(
591
+ name: string,
592
+ gates: readonly GateRef[],
593
+ contract?: C,
594
+ ): McpToolTrigger<C> {
487
595
  return {
488
596
  kind: "mcp",
489
597
  name,
490
598
  gates,
491
- gate: createGateAttach((next) => withMcpGates(name, next), gates),
492
- };
599
+ ...(contract !== undefined ? { contract } : {}),
600
+ gate: createGateAttach((next) => withMcpGates(name, next, contract), gates),
601
+ } as McpToolTrigger<C>;
493
602
  }
494
603
 
495
604
  /**
496
605
  * Normalize anything accepted by {@link on} into a {@link Trigger}.
497
606
  *
498
- * @param value - Trigger or signal handle
607
+ * @param value - Trigger, clock, or signal handle
499
608
  */
500
- export function normalizeTrigger(value: Trigger | SignalSource): Trigger {
609
+ export function normalizeTrigger(value: Trigger | SignalSource | ClockDecl): Trigger {
501
610
  if (typeof value !== "object" || value === null) {
502
611
  throw new TypeError("on() expected a trigger or signal handle");
503
612
  }
@@ -505,6 +614,7 @@ export function normalizeTrigger(value: Trigger | SignalSource): Trigger {
505
614
  const kind = (value as Trigger).kind;
506
615
  if (
507
616
  kind === "http" ||
617
+ kind === "clock" ||
508
618
  kind === "every" ||
509
619
  kind === "signal" ||
510
620
  kind === "cdc" ||
@@ -514,6 +624,9 @@ export function normalizeTrigger(value: Trigger | SignalSource): Trigger {
514
624
  return value as Trigger;
515
625
  }
516
626
  }
627
+ if (isClockDecl(value)) {
628
+ return { kind: "clock", name: value.name, clock: value };
629
+ }
517
630
  if (isSignalTriggerSource(value)) {
518
631
  return asSignalTrigger(value);
519
632
  }
@@ -527,6 +640,8 @@ export function normalizeTrigger(value: Trigger | SignalSource): Trigger {
527
640
  */
528
641
  export type BoundTriggerOf<T> = T extends Trigger
529
642
  ? T
530
- : T extends SignalSource
531
- ? SignalAsTrigger
532
- : Trigger;
643
+ : T extends ClockDecl
644
+ ? ClockTrigger
645
+ : T extends SignalSource
646
+ ? SignalAsTrigger
647
+ : Trigger;
@@ -9,7 +9,6 @@ export {
9
9
  on,
10
10
  flow,
11
11
  http,
12
- every,
13
12
  internal,
14
13
  fail,
15
14
  createFx,
@@ -42,7 +42,17 @@ const CATEGORY_RANK: Record<DiffCategory, number> = {
42
42
  "no-impact": 0,
43
43
  };
44
44
 
45
- const EFFECT_KEYS = ["reads", "writes", "emits", "sends", "asks", "secrets", "calls"] as const;
45
+ const EFFECT_KEYS = [
46
+ "reads",
47
+ "writes",
48
+ "emits",
49
+ "sends",
50
+ "asks",
51
+ "embeds",
52
+ "secrets",
53
+ "calls",
54
+ "fetches",
55
+ ] as const;
46
56
 
47
57
  /** Isolation strength: higher = stronger tenant separation. */
48
58
  const ISOLATION_RANK: Record<string, number> = {
@@ -15,7 +15,7 @@
15
15
  "secrets": []
16
16
  },
17
17
  "slo": { "availability": "99.9%", "latency": { "p99": "200ms" } },
18
- "source": "src/flows/bookings/index.ts:18"
18
+ "source": "src/flows/bookings/index.ts:24"
19
19
  },
20
20
  "bookings.mine": { "cacheKeys": "computed:sql:bookings/userId" },
21
21
  "payments.chargeBooking": {
@@ -89,7 +89,8 @@ export type JsonSchema = string | Record<string, unknown>;
89
89
  *
90
90
  * `secrets` is a capability (not an irreversible effect).
91
91
  * `calls` portals to the callee's transitive effects.
92
- * `sends` / `asks` are irreversible (asks also nondeterministic + cost).
92
+ * `sends` / `asks` / `embeds` / `fetches` are irreversible
93
+ * (asks/embeds also nondeterministic + cost).
93
94
  */
94
95
  export interface Effects {
95
96
  /** Store reads, plus `"runs"` for `fx.runs` and `signal:name` for `fx.deadLetters` / `fx.live`. */
@@ -108,12 +109,28 @@ export interface Effects {
108
109
  sends?: TemplateRef[];
109
110
  /** AI prompt asks (irreversible, nondeterministic, cost). */
110
111
  asks?: PromptRef[];
112
+ /**
113
+ * AI embedding model refs from `fx.embed` (irreversible, nondeterministic, cost).
114
+ * Distinct from {@link asks} — never conflated with prompt asks.
115
+ */
116
+ embeds?: EmbedRef[];
111
117
  /** Vault secret capabilities. */
112
118
  secrets?: SecretRef[];
113
119
  /** Nested flow calls (transitive effects). */
114
120
  calls?: FlowRef[];
121
+ /**
122
+ * Outbound HTTP hosts from `fx.fetch` (irreversible).
123
+ * Hostname only (e.g. `"api.stripe.com"`), never a full URL.
124
+ */
125
+ fetches?: FetchHostRef[];
115
126
  }
116
127
 
128
+ /** Embedding model ref for `effects.embeds` / `fx.embed` (model name). */
129
+ export type EmbedRef = string;
130
+
131
+ /** Host ref for `effects.fetches` / `fx.fetch` (hostname). */
132
+ export type FetchHostRef = string;
133
+
117
134
  /** HTTP trigger surface. */
118
135
  export interface HttpTrigger {
119
136
  method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS" | "QUERY";
@@ -299,6 +316,14 @@ export interface DeclaredColumn extends ColumnClassification {
299
316
  description?: string;
300
317
  /** Foreign key when `.references()` was declared. */
301
318
  references?: DeclaredColumnReference;
319
+ /**
320
+ * Built-in hybrid search — BM25 when present; LSH when `embed` is set.
321
+ * Weight is BM25F field weight (default 1).
322
+ */
323
+ searchable?: { weight: number };
324
+ /** Async embedding + LSH — requires `searchable` and a configured AI element. */
325
+ /** Concrete after extract resolves project defaults — `dims` is always set. */
326
+ embed?: { model?: string; dims: number };
302
327
  }
303
328
 
304
329
  /** Field classification value forms. */
@@ -331,6 +356,15 @@ export interface Table {
331
356
  * defaulting.
332
357
  */
333
358
  live?: boolean;
359
+ /**
360
+ * Derived hybrid-search posture for Console / doctor inspectability.
361
+ * Present when any column has `.searchable()` / `.embed()`.
362
+ */
363
+ search?: {
364
+ engines: Array<"bm25" | "lsh">;
365
+ /** True when push detected existing rows needing `oke db search-backfill`. */
366
+ backfillRequired?: boolean;
367
+ };
334
368
  }
335
369
 
336
370
  /** One Store declaration. */
@@ -494,10 +528,20 @@ export interface Plugin {
494
528
  tables?: Record<string, PluginTable>;
495
529
  }
496
530
 
497
- /** Store-wide live-query defaulting configuration. */
531
+ /** Store-wide live-query / search defaulting configuration. */
498
532
  export interface StoreLive {
499
533
  /** `oke({ store: { live: true } })` is on — new tables are live by default. */
500
534
  live?: boolean;
535
+ /**
536
+ * Project default for field `.embed()` — `oke({ store: { search: { embed } } })`.
537
+ * Per-field `.embed({ model?, dims? })` overrides these when set.
538
+ */
539
+ search?: {
540
+ embed?: {
541
+ model: string;
542
+ dims: number;
543
+ };
544
+ };
501
545
  }
502
546
 
503
547
  /** Tenancy configuration (resolver is code; isolation is data). */