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
@@ -0,0 +1,372 @@
1
+ ---
2
+ title: "Tenancy"
3
+ description: "Opt into gate.auth.tenant so requests resolve fx.tenant.id from claim, header, or subdomain."
4
+ icon: "Building2"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Tenancy is an identity **dimension** under `gate.auth.tenant`, not a separate gate you attach with
9
+ `.gate(...)`. When enabled, the runtime resolves a tenant for the request and exposes it as
10
+ `fx.tenant.id`. Your SQL / KV / files code (and optional RLS) use that id for isolation.
11
+
12
+ For developers shipping B2B or mixed B2C+B2B apps on okengine — enable the dimension, filter every
13
+ store access by `fx.tenant.id`.
14
+
15
+ <Callout title="The one rule">
16
+ Enable `gate.auth.tenant`, keep membership checks on — then filter every store access by
17
+ `fx.tenant.id`. Do not invent a `gate.auth.tenant` trigger handle.
18
+ </Callout>
19
+
20
+ ## Smallest Example
21
+
22
+ <Steps>
23
+
24
+ <Step>
25
+ ### Turn tenancy on
26
+
27
+ ```typescript title="src/app.ts"
28
+ import { oke } from "okengine";
29
+
30
+ export const app = oke({
31
+ name: "shop",
32
+ env: "dev",
33
+ gate: {
34
+ auth: {
35
+ tenant: true, // claim source · header x-oke-tenant · required: false
36
+ },
37
+ },
38
+ });
39
+ ```
40
+
41
+ Or pass options:
42
+
43
+ ```typescript
44
+ tenant: {
45
+ required: true, // every user-plane request needs a tenant
46
+ source: "header", // "claim" | "header" | "subdomain" | "resolve"
47
+ header: "x-oke-tenant",
48
+ }
49
+ ```
50
+
51
+ </Step>
52
+
53
+ <Step>
54
+ ### Protect the route and scope data
55
+
56
+ ```typescript title="src/flows/invoices/list.ts"
57
+ import { on, flow, http } from "okengine";
58
+ import { eq } from "drizzle-orm";
59
+ import { member } from "@/core/gate";
60
+ import { db, invoices } from "@/schema";
61
+
62
+ export const list = on(
63
+ http.get().gate(member),
64
+ flow({
65
+ do: async (_, fx) => {
66
+ const tenantId = fx.tenant.id;
67
+ if (!tenantId) return fx.fail("Forbidden", { reason: "tenant_required" });
68
+ return await fx.store(db).select().from(invoices).where(eq(invoices.tenantId, tenantId));
69
+ },
70
+ }),
71
+ );
72
+ ```
73
+
74
+ </Step>
75
+
76
+ <Step>
77
+ ### Switch tenant (session)
78
+
79
+ ```typescript
80
+ // Session-only
81
+ const session = await fx.auth.switchTenant("ten_acme");
82
+ // New access token carries tid; subsequent requests resolve fx.tenant.id
83
+ ```
84
+
85
+ </Step>
86
+
87
+ </Steps>
88
+
89
+ ## Progressive Patterns
90
+
91
+ From claim-based B2C+B2B to pure B2B, custom resolve, and Flow opt-out:
92
+
93
+ <Tabs items={["Claim", "Required", "Resolve", "Opt-out"]}>
94
+
95
+ <Tab value="Claim">
96
+
97
+ Default when `tenant: true`: `source: "claim"`, `required: false`, header name `x-oke-tenant`
98
+ (unused until you switch source).
99
+
100
+ The signed session / key claim supplies `tid`. Membership is still checked unless
101
+ `authoritative: true` on a custom `resolve`.
102
+
103
+ </Tab>
104
+
105
+ <Tab value="Required">
106
+
107
+ Pure B2B — every user-plane request must resolve a tenant:
108
+
109
+ ```typescript
110
+ tenant: {
111
+ required: true,
112
+ source: "header",
113
+ header: "x-oke-tenant",
114
+ }
115
+ ```
116
+
117
+ **Consequence:** missing tenant fails before `do` with
118
+ `Forbidden` · `reason: "tenant_required"`. Operator-plane Flows are not forced through the
119
+ same required path.
120
+
121
+ </Tab>
122
+
123
+ <Tab value="Resolve">
124
+
125
+ Custom resolver (tier-3 escape hatch). Membership is still checked unless `authoritative`:
126
+
127
+ ```typescript
128
+ tenant: {
129
+ source: "resolve",
130
+ resolve: ({ auth, request, claimTenantId }) => {
131
+ if (claimTenantId) return claimTenantId;
132
+ return request?.headers.get("x-workspace") ?? null;
133
+ },
134
+ // authoritative: true // trust resolve without membership query (fail-open — rare)
135
+ }
136
+ ```
137
+
138
+ </Tab>
139
+
140
+ <Tab value="Opt-out">
141
+
142
+ When tenancy is on, Flows default to tenant-scoped (role scopes may union into `fx.auth.scopes`).
143
+ Opt a Flow out with `tenantScoped: false`:
144
+
145
+ ```typescript
146
+ flow("billing.globalReport", {
147
+ plane: "operator",
148
+ tenantScoped: false,
149
+ do: async (_, fx) => {
150
+ // No tenant-role scope union; fx.tenant.id may still be set from the request
151
+ },
152
+ });
153
+ ```
154
+
155
+ </Tab>
156
+
157
+ </Tabs>
158
+
159
+ ## Resolution Sources
160
+
161
+ <Callout title="Detailed section">
162
+ Three tiers: signed claim (no membership query), client-supplied header/subdomain (membership
163
+ required), and custom `resolve` (membership unless `authoritative`).
164
+ </Callout>
165
+
166
+ <Tabs items={["claim", "header", "subdomain", "resolve"]}>
167
+
168
+ <Tab value="claim">
169
+
170
+ Signed `tid` on the session / API key. Fast path — no membership query:
171
+
172
+ ```typescript
173
+ tenant: true;
174
+ // expands to source: "claim", required: false, header: "x-oke-tenant"
175
+ ```
176
+
177
+ After `fx.auth.switchTenant(id)`, new access tokens carry `tid` for this source.
178
+
179
+ </Tab>
180
+
181
+ <Tab value="header">
182
+
183
+ Client sends the configured header; membership is required:
184
+
185
+ ```typescript
186
+ tenant: {
187
+ source: "header",
188
+ header: "x-oke-tenant", // default name
189
+ }
190
+ ```
191
+
192
+ ```bash
193
+ curl -X GET http://localhost:6530/invoices \
194
+ -H "authorization: Bearer …" \
195
+ -H "x-oke-tenant: ten_acme"
196
+ ```
197
+
198
+ Not a member → `Forbidden` · `reason: "not_member"`. Anonymous with a header →
199
+ `Unauthorized`.
200
+
201
+ </Tab>
202
+
203
+ <Tab value="subdomain">
204
+
205
+ First Host label is the tenant id (`acme.example.com` → `acme`). Needs at least three
206
+ labels; membership is required:
207
+
208
+ ```typescript
209
+ tenant: {
210
+ source: "subdomain";
211
+ }
212
+ ```
213
+
214
+ Internal / cron calls without an HTTP request keep the stamped claim when present.
215
+
216
+ </Tab>
217
+
218
+ <Tab value="resolve">
219
+
220
+ Callback receives `{ auth, request, claimTenantId }`. Membership still runs unless
221
+ `authoritative: true`:
222
+
223
+ ```typescript
224
+ tenant: {
225
+ source: "resolve",
226
+ resolve: ({ claimTenantId, request }) =>
227
+ claimTenantId ?? request?.headers.get("x-workspace") ?? null,
228
+ }
229
+ ```
230
+
231
+ **Consequence:** `authoritative: true` is fail-open — use only when you own the resolver’s
232
+ trust boundary.
233
+
234
+ </Tab>
235
+
236
+ </Tabs>
237
+
238
+ ## Options
239
+
240
+ | Option | Type | Default | Meaning |
241
+ | --------------- | ------------------------------------------------------- | -------------- | ------------------------------------------- |
242
+ | `required` | `boolean` | `false` | Reject user-plane requests without a tenant |
243
+ | `source` | `"claim"` \| `"header"` \| `"subdomain"` \| `"resolve"` | `"claim"` | Where the tenant id comes from |
244
+ | `header` | `string` | `x-oke-tenant` | Header name when `source: "header"` |
245
+ | `resolve` | `(ctx) => string \| null \| undefined` | — | Custom resolver; membership still checked |
246
+ | `authoritative` | `boolean` | `false` | Trust `resolve` without a membership query |
247
+
248
+ `tenant: true` expands to `{ required: false, source: "claim", header: "x-oke-tenant", authoritative: false }`.
249
+
250
+ ## `fx.auth` tenant methods
251
+
252
+ Session-only. API keys get `Forbidden` with `reason: "session_only"`:
253
+
254
+ | Method | Meaning |
255
+ | -------------------------------------------------- | ------------------------------------ |
256
+ | `listTenants()` | Tenants the user belongs to |
257
+ | `switchTenant(id)` | Mint a new session family with `tid` |
258
+ | `createTenant({ name, slug?, id? })` | Create + add caller as member |
259
+ | `deleteTenant(id)` | Remove tenant |
260
+ | `addMember` / `removeMember` | Membership |
261
+ | `listMembers(tenantId)` | Members of a tenant |
262
+ | `upsertTenantRole({ tenantId, roleName, scopes })` | Role → scopes (unioned when scoped) |
263
+
264
+ ```typescript title="src/flows/tenants/switch.ts"
265
+ import { on, flow, http } from "okengine";
266
+ import { z } from "zod";
267
+ import { member } from "@/core/gate";
268
+
269
+ export const switchTenant = on(
270
+ http.post().gate(member),
271
+ flow({
272
+ in: z.object({ tenantId: z.string() }),
273
+ do: async ({ tenantId }, fx) => fx.auth.switchTenant(tenantId),
274
+ }),
275
+ );
276
+ ```
277
+
278
+ ## Store isolation
279
+
280
+ | Facet | Pattern |
281
+ | ----- | ------------------------------------------------------------------------ |
282
+ | SQL | Filter / RLS by `fx.tenant.id` (and table tenant policies when declared) |
283
+ | KV | Optional `{tenantId}:` key prefix when the namespace is tenant-scoped |
284
+ | Files | Path / ACL under the active tenant |
285
+
286
+ RLS helper for a tenant column:
287
+
288
+ ```typescript
289
+ import { store, field } from "okengine";
290
+
291
+ export const invoices = store.schema.table(
292
+ "invoices",
293
+ {
294
+ id: field.text().primaryKey(),
295
+ tenantId: field.text(),
296
+ total: field.integer(),
297
+ },
298
+ [store.schema.policy.tenant("tenantId"), store.schema.rls()],
299
+ );
300
+ ```
301
+
302
+ Globally shared tables when tenancy is on need an explicit opt-out:
303
+
304
+ ```typescript
305
+ store.schema.table("plans", { id: field.text().primaryKey() }, [store.schema.unscoped()]);
306
+ ```
307
+
308
+ **Consequence:** Gate resolves identity; your Flow still owns the filter. A missing `where
309
+ tenant_id = …` is a data leak, not a Gate bug.
310
+
311
+ ## Denial Mapping
312
+
313
+ | Situation | Code | `error.data.reason` |
314
+ | ------------------------------------------ | -------------- | ------------------- |
315
+ | `required: true`, authenticated, no tenant | `Forbidden` | `tenant_required` |
316
+ | Header / subdomain / resolve, not a member | `Forbidden` | `not_member` |
317
+ | Header / subdomain without session | `Unauthorized` | — |
318
+ | Tenant admin from API key | `Forbidden` | `session_only` |
319
+
320
+ ## Troubleshooting
321
+
322
+ <Accordions>
323
+
324
+ <Accordion title="fx.tenant.id is null on every request">
325
+ Tenancy off, `required: false` with no claim/header, or membership failed. Enable
326
+ `gate.auth.tenant`, send the claim / header, and confirm the user is a member.
327
+ </Accordion>
328
+
329
+ <Accordion title="Forbidden · session_only on listTenants / switchTenant">
330
+ Tenant admin methods refuse API-key principals. Use a user session.
331
+ </Accordion>
332
+
333
+ <Accordion title="Tenant-granted scope does not authorize a route">
334
+ The Flow set `tenantScoped: false`, or the role was never upserted. Tenant-role union only applies
335
+ when the Flow is tenant-scoped (default when tenancy is on).
336
+ </Accordion>
337
+
338
+ <Accordion title="required: true rejects browser calls">
339
+ Pure B2B needs a tenant on every user-plane request — send `tid` (claim) or the configured header
340
+ before calling gated APIs.
341
+ </Accordion>
342
+
343
+ <Accordion title="Forbidden · not_member on header / subdomain">
344
+ The supplied tenant id is not in the user’s membership set. Add the member, or switch to `source:
345
+ "claim"` after `switchTenant` so the signed `tid` is trusted.
346
+ </Accordion>
347
+
348
+ </Accordions>
349
+
350
+ ## Learn more
351
+
352
+ - [Authentication](/docs/elements/gate/auth) — `gate.auth` and `fx.auth`
353
+ - [Authorization](/docs/elements/gate/authorization) — scopes after tenant-role union
354
+ - [RLS](/docs/elements/gate/rls) — `policy.tenant` and the SQL stamp
355
+ - [Store](/docs/elements/store) — SQL / KV / files facets
356
+ - [HTTP](/docs/elements/flow/http) — gated routes that read `fx.tenant`
357
+
358
+ ## Next
359
+
360
+ <Cards>
361
+ <Card
362
+ title="RLS"
363
+ description="policy.tenant and the SQL identity stamp."
364
+ href="/docs/elements/gate/rls"
365
+ />
366
+ <Card
367
+ title="Vault Element"
368
+ description="Secrets and protected configuration."
369
+ href="/docs/elements/vault"
370
+ />
371
+ <Card title="Gate Overview" description="Return to Gate overview." href="/docs/elements/gate" />
372
+ </Cards>
@@ -1,45 +1,86 @@
1
1
  ---
2
2
  title: "Elements"
3
- description: "The eight irreducible parts of an OKE backend Flow through AI, one page each."
3
+ description: "The closed set of eight semantic primitives forming the entire OKEngine backend model."
4
4
  icon: "Boxes"
5
5
  source: "docs/spec/unified-theory.md"
6
6
  ---
7
7
 
8
- Every backend concern collapses to one of these eight. Pick the element you need.
8
+ Forty backend concerns collapse into eight semantic primitives. An element earns its place only with **irreducible physics**.
9
9
 
10
- ## Pages
10
+ <Callout title="Closed primitive set">
11
+ There is no ninth element. Every backend capability belongs to one of the eight elements. New
12
+ infrastructure creates a protocol driver or plugin, preserving a small mental model.
13
+ </Callout>
14
+
15
+ ```text
16
+ Elements define the model.
17
+ Plugins extend the model's capabilities.
18
+ Drivers connect the model to infrastructure.
19
+ Providers and Recipes choose where that infrastructure runs.
20
+ ```
21
+
22
+ ## The Structural Anatomy
23
+
24
+ Every backend concern is mapped across three conceptual tiers:
25
+
26
+ | Tier | Question Answered | Definition & Scope |
27
+ | ---------------- | ----------------------------------- | --------------------------------------------------------------------------- |
28
+ | **Elements** | _What is the thing?_ | The 8 closed primitives representing irreducible backend physics. |
29
+ | **Capabilities** | _What can it do?_ | Explicit facets, triggers, and execution mechanics within each element. |
30
+ | **Composition** | _What happens when they cooperate?_ | Emergent system properties (Realtime, Live Queries, Multi-Tenancy, Agents). |
31
+
32
+ ## The Eight Primitives
11
33
 
12
34
  <Cards>
13
- <Card title="Flow" description="Behavior — on(Trigger) → Effects." href="/docs/elements/flow" />
35
+ <Card
36
+ title="Flow"
37
+ description="Behavior — on(Trigger) → Effects via fx. Unified endpoints, jobs, consumers, and durable sagas."
38
+ href="/docs/elements/flow"
39
+ />
14
40
  <Card
15
41
  title="Signal"
16
- description="Data in motion — queues, pub/sub, streams."
42
+ description="Data in motion — once, broadcast, and live with mandatory delivery physics."
17
43
  href="/docs/elements/signal"
18
44
  />
19
45
  <Card
20
46
  title="Store"
21
- description="Data at rest — sql, kv, files, index."
47
+ description="Data at rest — SQL, KV, files with image transforms, and search behind one handle."
22
48
  href="/docs/elements/store"
23
49
  />
24
50
  <Card
25
51
  title="Clock"
26
- description="Time — schedules, intervals, durable sleeps."
52
+ description="Time — schedules, intervals, durable sleep, and deterministic time travel."
27
53
  href="/docs/elements/clock"
28
54
  />
29
55
  <Card
30
56
  title="Gate"
31
- description="Permission to act — auth and rate limits."
57
+ description="Permission to act — auth, tenancy, ABAC/RBAC, and rate limits at the trigger."
32
58
  href="/docs/elements/gate"
33
59
  />
34
60
  <Card
35
61
  title="Vault"
36
- description="Protected knowledge — secrets and keys."
62
+ description="Protected knowledge — fail-loud secret contracts, dynamic config, and redacted values."
37
63
  href="/docs/elements/vault"
38
64
  />
39
65
  <Card
40
66
  title="Channel"
41
- description="Reaching humans — email, SMS, push."
67
+ description="Reaching humans — email, SMS, WhatsApp, and push with built-in consent."
42
68
  href="/docs/elements/channel"
43
69
  />
44
- <Card title="AI" description="Reaching machine intelligence." href="/docs/elements/ai" />
70
+ <Card
71
+ title="AI"
72
+ description="Reaching machine intelligence — models, prompts, agents, and MCP tool boundaries."
73
+ href="/docs/elements/ai"
74
+ />
45
75
  </Cards>
76
+
77
+ ## See How They Compose
78
+
79
+ The closed elements compose into full backend capabilities:
80
+
81
+ | Composition Target | Formula | How It Works |
82
+ | ------------------ | ----------------------------------------------- | --------------------------------------------------------- |
83
+ | **Realtime** | Store + Gate + Signal + Flow → Live Query | CDC changes re-checked against Gate RLS, streamed as SSE |
84
+ | **Security** | Gate + Store/RLS + Tenant + fx → Secure runtime | Tenant-isolated queries with least-privilege capability |
85
+ | **Agents** | MCP + Gate + OAuth + Flow → Agent-ready backend | Declared Flows exposed on :6535 behind auth confirmation |
86
+ | **Operations** | Manifest + Effects + Runs → Inspectable backend | Inferred effects feed Console (:6533) and wide-event logs |