okengine 0.18.5 → 0.19.1

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/llms-txt.mdx +1 -1
  5. package/site/content/docs/ai/skills.mdx +4 -1
  6. package/site/content/docs/client/auth.mdx +208 -0
  7. package/site/content/docs/client/calling.mdx +451 -0
  8. package/site/content/docs/client/index.mdx +208 -0
  9. package/site/content/docs/client/live.mdx +234 -0
  10. package/site/content/docs/client/meta.json +5 -0
  11. package/site/content/docs/client/react.mdx +249 -0
  12. package/site/content/docs/elements/ai/agents.mdx +235 -0
  13. package/site/content/docs/elements/ai/index.mdx +342 -0
  14. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  15. package/site/content/docs/elements/ai/meta.json +5 -0
  16. package/site/content/docs/elements/ai/models.mdx +283 -0
  17. package/site/content/docs/elements/ai/prompts.mdx +257 -0
  18. package/site/content/docs/elements/channel/email.mdx +269 -0
  19. package/site/content/docs/elements/channel/index.mdx +344 -0
  20. package/site/content/docs/elements/channel/meta.json +5 -0
  21. package/site/content/docs/elements/channel/push.mdx +218 -0
  22. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  23. package/site/content/docs/elements/channel/sms.mdx +264 -0
  24. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  25. package/site/content/docs/elements/clock/index.mdx +301 -0
  26. package/site/content/docs/elements/clock/meta.json +5 -0
  27. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  28. package/site/content/docs/elements/clock/sleep.mdx +448 -0
  29. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  30. package/site/content/docs/elements/flow/http.mdx +1080 -0
  31. package/site/content/docs/elements/flow/index.mdx +618 -0
  32. package/site/content/docs/elements/flow/meta.json +5 -0
  33. package/site/content/docs/elements/flow/routing.mdx +559 -0
  34. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  35. package/site/content/docs/elements/gate/auth.mdx +371 -0
  36. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  37. package/site/content/docs/elements/gate/index.mdx +418 -0
  38. package/site/content/docs/elements/gate/meta.json +5 -0
  39. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  40. package/site/content/docs/elements/gate/rls.mdx +303 -0
  41. package/site/content/docs/elements/gate/tenancy.mdx +375 -0
  42. package/site/content/docs/elements/index.mdx +20 -10
  43. package/site/content/docs/elements/signal/broadcast.mdx +519 -0
  44. package/site/content/docs/elements/signal/index.mdx +352 -0
  45. package/site/content/docs/elements/signal/live.mdx +591 -0
  46. package/site/content/docs/elements/signal/meta.json +5 -0
  47. package/site/content/docs/elements/signal/once.mdx +597 -0
  48. package/site/content/docs/elements/store/files.mdx +667 -0
  49. package/site/content/docs/elements/store/index.mdx +313 -0
  50. package/site/content/docs/elements/store/kv.mdx +637 -0
  51. package/site/content/docs/elements/store/meta.json +5 -0
  52. package/site/content/docs/elements/store/search.mdx +950 -0
  53. package/site/content/docs/elements/store/sql.mdx +941 -0
  54. package/site/content/docs/elements/vault/config.mdx +259 -0
  55. package/site/content/docs/elements/vault/index.mdx +356 -0
  56. package/site/content/docs/elements/vault/meta.json +5 -0
  57. package/site/content/docs/elements/vault/rotation.mdx +276 -0
  58. package/site/content/docs/elements/vault/secrets.mdx +288 -0
  59. package/site/content/docs/index.mdx +52 -40
  60. package/site/content/docs/meta.json +8 -7
  61. package/site/content/docs/plugins/cors.mdx +2 -1
  62. package/site/content/docs/plugins/csrf.mdx +4 -1
  63. package/site/content/docs/plugins/headers.mdx +2 -1
  64. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  65. package/site/content/docs/plugins/magic-link.mdx +6 -0
  66. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  67. package/site/content/docs/plugins/oauth.mdx +1 -1
  68. package/site/content/docs/plugins/otp.mdx +12 -1
  69. package/site/content/docs/plugins/passkey.mdx +39 -15
  70. package/site/content/docs/plugins/two-factor.mdx +91 -34
  71. package/site/content/docs/plugins/username.mdx +1 -1
  72. package/site/content/docs/recipes/caddy.mdx +3 -3
  73. package/site/content/docs/recipes/index.mdx +18 -28
  74. package/site/content/docs/recipes/mailpit.mdx +1 -1
  75. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  76. package/site/content/docs/recipes/meta.json +1 -4
  77. package/site/content/docs/recipes/nginx.mdx +2 -2
  78. package/site/content/docs/recipes/openrouter.mdx +283 -0
  79. package/site/content/docs/recipes/pgdog.mdx +3 -3
  80. package/site/content/docs/recipes/postgres.mdx +1 -2
  81. package/site/content/docs/recipes/rustfs.mdx +2 -2
  82. package/site/content/docs/recipes/traefik.mdx +3 -3
  83. package/site/content/docs/reference/cli.mdx +231 -0
  84. package/site/content/docs/reference/configuration.mdx +30 -10
  85. package/site/content/docs/reference/environment-variables.mdx +93 -20
  86. package/site/content/docs/reference/errors.mdx +132 -29
  87. package/site/content/docs/reference/fx.mdx +138 -73
  88. package/site/content/docs/reference/index.mdx +13 -21
  89. package/site/content/docs/reference/meta.json +4 -5
  90. package/site/content/docs/reference/okid.mdx +42 -17
  91. package/site/content/docs/reference/plugins.mdx +4 -3
  92. package/site/content/docs/reference/security.mdx +197 -0
  93. package/site/content/docs/understand/meta.json +5 -0
  94. package/site/content/docs/understand/the-architecture.mdx +264 -0
  95. package/site/content/docs/understand/try-it.mdx +58 -0
  96. package/src/auth/api-keys.ts +2 -1
  97. package/src/auth/bindings.ts +64 -16
  98. package/src/auth/gate-auth.test.ts +6 -1
  99. package/src/auth/identity.ts +152 -5
  100. package/src/auth/index.ts +29 -0
  101. package/src/auth/invites.ts +2 -1
  102. package/src/auth/method-context.ts +41 -0
  103. package/src/auth/oauth-as/crypto.ts +2 -1
  104. package/src/auth/oauth-as/stores.ts +2 -1
  105. package/src/auth/operator.ts +2 -1
  106. package/src/auth/sessions-jwt.test.ts +77 -0
  107. package/src/auth/sessions.ts +20 -4
  108. package/src/auth/tenants.ts +3 -2
  109. package/src/auth/two-factor-challenge.test.ts +61 -0
  110. package/src/auth/two-factor-challenge.ts +284 -0
  111. package/src/auth/verification.ts +5 -0
  112. package/src/bench/REPORT.md +80 -0
  113. package/src/bench/g03-signal-once.bench.ts +1 -1
  114. package/src/bench/g10-observability-contention.bench.ts +1 -1
  115. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  116. package/src/bench/load-app.ts +2 -10
  117. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  118. package/src/cli/ai-setup/apply.ts +294 -52
  119. package/src/cli/ai-setup/catalog.ts +238 -1342
  120. package/src/cli/ai-setup/index.ts +14 -99
  121. package/src/cli/ai-setup/prompts.ts +60 -443
  122. package/src/cli/ask-seed.test.ts +96 -0
  123. package/src/cli/ask-seed.ts +82 -0
  124. package/src/cli/ask-vault-gaps.test.ts +84 -0
  125. package/src/cli/ask-vault-gaps.ts +146 -0
  126. package/src/cli/build.ts +2 -2
  127. package/src/cli/client-add.test.ts +26 -1
  128. package/src/cli/client-add.ts +106 -27
  129. package/src/cli/db-seed.ts +2 -0
  130. package/src/cli/db.ts +150 -11
  131. package/src/cli/dev.ts +119 -211
  132. package/src/cli/docker-clean.ts +2 -2
  133. package/src/cli/docker-cli.test.ts +1 -1
  134. package/src/cli/doctor-diff.ts +4 -2
  135. package/src/cli/doctor-pii.test.ts +1 -1
  136. package/src/cli/doctor.ts +14 -1
  137. package/src/cli/hero-meta.test.ts +4 -2
  138. package/src/cli/load-config.images.test.ts +8 -10
  139. package/src/cli/load-config.ts +1 -1
  140. package/src/cli/registry.ts +22 -10
  141. package/src/cli/replay.ts +3 -1
  142. package/src/cli/start.ts +1 -1
  143. package/src/cli/tui/keys.ts +2 -3
  144. package/src/client/auth/cookies.ts +74 -0
  145. package/src/client/auth/create-auth-client.ts +636 -0
  146. package/src/client/auth/denials.ts +99 -0
  147. package/src/client/auth/session.ts +283 -0
  148. package/src/client/auth.test.ts +251 -0
  149. package/src/client/auth.ts +39 -114
  150. package/src/client/create-with-session.ts +245 -0
  151. package/src/client/create.ts +51 -5
  152. package/src/client/index.ts +11 -1
  153. package/src/client/live.ts +11 -79
  154. package/src/client/notes-contract.test.ts +5 -10
  155. package/src/client/sse.ts +137 -0
  156. package/src/client/stream.ts +147 -0
  157. package/src/client/transport.test.ts +32 -0
  158. package/src/client/transport.ts +123 -26
  159. package/src/client/types.ts +118 -14
  160. package/src/client-react/index.ts +185 -24
  161. package/src/client-react/use-live-query.ts +13 -3
  162. package/src/compiler/aot.test.ts +7 -4
  163. package/src/compiler/effects-embed.test.ts +56 -0
  164. package/src/compiler/effects-fetch.test.ts +43 -0
  165. package/src/compiler/effects-infer.ts +58 -2
  166. package/src/compiler/extract.test.ts +257 -43
  167. package/src/compiler/extract.ts +566 -48
  168. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  169. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  170. package/src/compiler/fixtures/skyport.expected.json +4 -4
  171. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  172. package/src/compiler/response.ts +2 -2
  173. package/src/compiler/search-writer-isolation.test.ts +40 -0
  174. package/src/config/index.ts +11 -0
  175. package/src/console/server/app.ts +17 -23
  176. package/src/console/server/bind.ts +4 -0
  177. package/src/console/server/console.test.ts +2 -2
  178. package/src/console/server/flows-invoke.test.ts +50 -34
  179. package/src/console/server/flows.ts +436 -255
  180. package/src/console/server/runs-ingest.test.ts +6 -3
  181. package/src/console/server/serve.ts +1 -1
  182. package/src/console/server/signals.test.ts +1 -5
  183. package/src/console/server/signals.ts +8 -6
  184. package/src/console/server/state.ts +6 -1
  185. package/src/console/server/store.ts +1 -1
  186. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  187. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  188. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  189. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  190. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  191. package/src/console/ui-next/dist/assets/access-page-C_qLDhTq.js +4 -0
  192. package/src/console/ui-next/dist/assets/agent-disclosure-BHVqr3TN.js +1 -0
  193. package/src/console/ui-next/dist/assets/cache-glyph-CKe92lRQ.js +1 -0
  194. package/src/console/ui-next/dist/assets/call-pii-button-DEwTl8ZX.js +1 -0
  195. package/src/console/ui-next/dist/assets/collapsible-BCBtDrCt.js +1 -0
  196. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  197. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  198. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  199. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  200. package/src/console/ui-next/dist/assets/duration-tone-JroqeuCp.js +9 -0
  201. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  202. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  203. package/src/console/ui-next/dist/assets/flows-page-CVHa0RTt.js +1 -0
  204. package/src/console/ui-next/dist/assets/highlighted-json-DjJW6hqe.js +154 -0
  205. package/src/console/ui-next/dist/assets/http-method-DC5HBdLU.js +1 -0
  206. package/src/console/ui-next/dist/assets/index-CYjiZ3WO.js +63 -0
  207. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  208. package/src/console/ui-next/dist/assets/observability-page-CAYMyKb3.js +4 -0
  209. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  210. package/src/console/ui-next/dist/assets/replica-lag-yAQYLv75.js +18 -0
  211. package/src/console/ui-next/dist/assets/request-meta-D0yusGxJ.js +1 -0
  212. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  213. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  214. package/src/console/ui-next/dist/assets/store-page-BTKJeJ02.js +41 -0
  215. package/src/console/ui-next/dist/assets/trace-detail-sheet-Bp-Yygs5.js +2 -0
  216. package/src/console/ui-next/dist/assets/tree-expand-toggle-DoaVDfAM.js +55 -0
  217. package/src/console/ui-next/dist/assets/units-page-BRz7xyYL.js +1 -0
  218. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  219. package/src/console/ui-next/dist/assets/vault-page-3jQt-bOJ.js +2 -0
  220. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  221. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  222. package/src/console/ui-next/dist/index.html +6 -13
  223. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  224. package/src/console/ui-next/src/client.ts +7 -2
  225. package/src/console/ui-next/src/features/flows/graph/element-map.test.ts +1 -1
  226. package/src/console/ui-next/src/features/flows/graph/element-map.ts +5 -3
  227. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  228. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  229. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  230. package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +4 -5
  231. package/src/console/ui-next/src/features/flows/traces/trace-gates.ts +3 -6
  232. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  233. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  234. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  235. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  236. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  237. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  238. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  239. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  240. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  241. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  242. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  243. package/src/docker/ai-model-status.test.ts +1 -12
  244. package/src/docker/ai-model-status.ts +10 -38
  245. package/src/docker/compose-up.test.ts +100 -0
  246. package/src/docker/compose-up.ts +292 -0
  247. package/src/docker/compose.ts +4 -14
  248. package/src/docker/derive.ts +9 -34
  249. package/src/docker/docker.test.ts +16 -261
  250. package/src/docker/images-config.test.ts +13 -25
  251. package/src/docker/index.ts +1 -24
  252. package/src/docker/recipes/index.ts +0 -23
  253. package/src/docker/recipes/pgdog.ts +6 -4
  254. package/src/docker/stack-id.test.ts +2 -2
  255. package/src/docker/stack-id.ts +0 -1
  256. package/src/docker/types.ts +2 -2
  257. package/src/drivers/ai-anthropic.ts +10 -0
  258. package/src/drivers/ai-openai-compatible.ts +34 -7
  259. package/src/drivers/ai-providers.test.ts +0 -107
  260. package/src/drivers/ai-stream.test.ts +0 -34
  261. package/src/drivers/ai-types.ts +17 -8
  262. package/src/drivers/channel-fcm.ts +6 -1
  263. package/src/drivers/channel-msegat.ts +6 -1
  264. package/src/drivers/channel-resend.ts +5 -1
  265. package/src/drivers/channel-smtp.ts +5 -1
  266. package/src/drivers/channel-sndr.ts +10 -1
  267. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  268. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  269. package/src/drivers/channel-taqnyat.ts +6 -1
  270. package/src/drivers/channel-types.ts +10 -0
  271. package/src/drivers/channel-unifonic.ts +6 -1
  272. package/src/drivers/channel-wa-cloud.ts +6 -1
  273. package/src/drivers/channel-webpush.ts +6 -1
  274. package/src/drivers/external.ts +33 -0
  275. package/src/drivers/index.ts +0 -10
  276. package/src/drivers/meilisearch.ts +6 -0
  277. package/src/drivers/oauth-types.ts +4 -0
  278. package/src/drivers/postgres.test.ts +74 -3
  279. package/src/drivers/postgres.ts +175 -6
  280. package/src/drivers/signal-types.ts +5 -5
  281. package/src/drivers/types.ts +7 -0
  282. package/src/drivers/vault-types.ts +5 -0
  283. package/src/elements/ai/declare.ts +17 -4
  284. package/src/elements/ai/eval.ts +1 -1
  285. package/src/elements/ai/mcp-http.ts +1 -1
  286. package/src/elements/ai/pii.ts +1 -1
  287. package/src/elements/ai/providers.test.ts +289 -0
  288. package/src/elements/ai/providers.ts +169 -0
  289. package/src/elements/ai/runtime.ts +68 -5
  290. package/src/elements/ai/schema.ts +2 -2
  291. package/src/elements/ai.test.ts +7 -7
  292. package/src/elements/ai.ts +17 -1
  293. package/src/elements/channel/runtime.ts +105 -12
  294. package/src/elements/clock/cron-fields.test.ts +144 -0
  295. package/src/elements/clock/cron-fields.ts +185 -0
  296. package/src/elements/clock/declare.ts +247 -3
  297. package/src/elements/clock.ts +21 -1
  298. package/src/elements/gate/declare.ts +1 -1
  299. package/src/elements/gate.ts +1 -1
  300. package/src/elements/index.ts +15 -0
  301. package/src/elements/signal/chaos-child.ts +1 -2
  302. package/src/elements/signal/declare.ts +65 -37
  303. package/src/elements/signal/delivery-modes.test.ts +11 -31
  304. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  305. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  306. package/src/elements/signal/key-ordering.test.ts +6 -26
  307. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  308. package/src/elements/signal/optional-emit.test.ts +6 -9
  309. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  310. package/src/elements/signal/orphan-messages.test.ts +4 -15
  311. package/src/elements/signal/reconcile.test.ts +2 -2
  312. package/src/elements/signal/runtime.ts +1 -1
  313. package/src/elements/signal/schema-emit.test.ts +4 -8
  314. package/src/elements/signal.test.ts +24 -49
  315. package/src/elements/signal.ts +9 -2
  316. package/src/elements/store/domain-ddl.test.ts +1 -1
  317. package/src/elements/store/live-http.test.ts +9 -4
  318. package/src/elements/store/prepare-row.test.ts +123 -0
  319. package/src/elements/store/resource.ts +43 -12
  320. package/src/elements/store/schema-decl.ts +117 -0
  321. package/src/elements/store/search-backfill.ts +205 -0
  322. package/src/elements/store/search-bind.ts +66 -0
  323. package/src/elements/store/search-bm25.ts +78 -0
  324. package/src/elements/store/search-ddl.ts +156 -0
  325. package/src/elements/store/search-embed-flow.ts +141 -0
  326. package/src/elements/store/search-errors.ts +34 -0
  327. package/src/elements/store/search-fusion.ts +112 -0
  328. package/src/elements/store/search-lsh.ts +214 -0
  329. package/src/elements/store/search-runtime.pglite.test.ts +186 -0
  330. package/src/elements/store/search-runtime.ts +314 -0
  331. package/src/elements/store/search.test.ts +226 -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 +52 -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 +2 -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 -144
  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 -114
  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-3-EFj-2G.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-cVFnA4HH.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-CMIgUbD0.js +0 -66
  484. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  485. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  486. package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.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-l8FeKfnP.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-CL-d_mLE.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,375 @@
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
271
+ .post({
272
+ in: z.object({ tenantId: z.string() }),
273
+ })
274
+ .gate(member),
275
+ flow({
276
+ do: async ({ tenantId }, fx) => fx.auth.switchTenant(tenantId),
277
+ }),
278
+ );
279
+ ```
280
+
281
+ ## Store isolation
282
+
283
+ | Facet | Pattern |
284
+ | ----- | ------------------------------------------------------------------------ |
285
+ | SQL | Filter / RLS by `fx.tenant.id` (and table tenant policies when declared) |
286
+ | KV | Optional `{tenantId}:` key prefix when the namespace is tenant-scoped |
287
+ | Files | Path / ACL under the active tenant |
288
+
289
+ RLS helper for a tenant column:
290
+
291
+ ```typescript
292
+ import { store, field } from "okengine";
293
+
294
+ export const invoices = store.schema.table(
295
+ "invoices",
296
+ {
297
+ id: field.text().primaryKey(),
298
+ tenantId: field.text(),
299
+ total: field.integer(),
300
+ },
301
+ [store.schema.policy.tenant("tenantId"), store.schema.rls()],
302
+ );
303
+ ```
304
+
305
+ Globally shared tables when tenancy is on need an explicit opt-out:
306
+
307
+ ```typescript
308
+ store.schema.table("plans", { id: field.text().primaryKey() }, [store.schema.unscoped()]);
309
+ ```
310
+
311
+ **Consequence:** Gate resolves identity; your Flow still owns the filter. A missing `where
312
+ tenant_id = …` is a data leak, not a Gate bug.
313
+
314
+ ## Denial Mapping
315
+
316
+ | Situation | Code | `error.data.reason` |
317
+ | ------------------------------------------ | -------------- | ------------------- |
318
+ | `required: true`, authenticated, no tenant | `Forbidden` | `tenant_required` |
319
+ | Header / subdomain / resolve, not a member | `Forbidden` | `not_member` |
320
+ | Header / subdomain without session | `Unauthorized` | — |
321
+ | Tenant admin from API key | `Forbidden` | `session_only` |
322
+
323
+ ## Troubleshooting
324
+
325
+ <Accordions>
326
+
327
+ <Accordion title="fx.tenant.id is null on every request">
328
+ Tenancy off, `required: false` with no claim/header, or membership failed. Enable
329
+ `gate.auth.tenant`, send the claim / header, and confirm the user is a member.
330
+ </Accordion>
331
+
332
+ <Accordion title="Forbidden · session_only on listTenants / switchTenant">
333
+ Tenant admin methods refuse API-key principals. Use a user session.
334
+ </Accordion>
335
+
336
+ <Accordion title="Tenant-granted scope does not authorize a route">
337
+ The Flow set `tenantScoped: false`, or the role was never upserted. Tenant-role union only applies
338
+ when the Flow is tenant-scoped (default when tenancy is on).
339
+ </Accordion>
340
+
341
+ <Accordion title="required: true rejects browser calls">
342
+ Pure B2B needs a tenant on every user-plane request — send `tid` (claim) or the configured header
343
+ before calling gated APIs.
344
+ </Accordion>
345
+
346
+ <Accordion title="Forbidden · not_member on header / subdomain">
347
+ The supplied tenant id is not in the user’s membership set. Add the member, or switch to `source:
348
+ "claim"` after `switchTenant` so the signed `tid` is trusted.
349
+ </Accordion>
350
+
351
+ </Accordions>
352
+
353
+ ## Learn more
354
+
355
+ - [Authentication](/docs/elements/gate/auth) — `gate.auth` and `fx.auth`
356
+ - [Authorization](/docs/elements/gate/authorization) — scopes after tenant-role union
357
+ - [RLS](/docs/elements/gate/rls) — `policy.tenant` and the SQL stamp
358
+ - [Store](/docs/elements/store) — SQL / KV / files facets
359
+ - [HTTP](/docs/elements/flow/http) — gated routes that read `fx.tenant`
360
+
361
+ ## Next
362
+
363
+ <Cards>
364
+ <Card
365
+ title="RLS"
366
+ description="policy.tenant and the SQL identity stamp."
367
+ href="/docs/elements/gate/rls"
368
+ />
369
+ <Card
370
+ title="Vault Element"
371
+ description="Secrets and protected configuration."
372
+ href="/docs/elements/vault"
373
+ />
374
+ <Card title="Gate Overview" description="Return to Gate overview." href="/docs/elements/gate" />
375
+ </Cards>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Elements"
3
- description: "The eight closed semantic primitives of the OKEngine backend model."
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
  ---
@@ -8,8 +8,8 @@ source: "docs/spec/unified-theory.md"
8
8
  Forty backend concerns collapse into eight semantic primitives. An element earns its place only with **irreducible physics**.
9
9
 
10
10
  <Callout title="Closed primitive set">
11
- There is no ninth element. New infrastructure creates a protocol driver or plugin, preserving a
12
- small mental model.
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
13
  </Callout>
14
14
 
15
15
  ```text
@@ -19,37 +19,47 @@ Drivers connect the model to infrastructure.
19
19
  Providers and Recipes choose where that infrastructure runs.
20
20
  ```
21
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
+
22
32
  ## The Eight Primitives
23
33
 
24
34
  <Cards>
25
35
  <Card
26
36
  title="Flow"
27
- description="Behavior — on(Trigger) → Effects via fx."
37
+ description="Behavior — on(Trigger) → Effects via fx. Unified endpoints, jobs, consumers, and durable sagas."
28
38
  href="/docs/elements/flow"
29
39
  />
30
40
  <Card
31
41
  title="Signal"
32
- description="Data in motion — delivery physics as a property (once, broadcast, live)."
42
+ description="Data in motion — once, broadcast, and live with mandatory delivery physics."
33
43
  href="/docs/elements/signal"
34
44
  />
35
45
  <Card
36
46
  title="Store"
37
- description="Data at rest — SQL, KV, files with image transforms, and search."
47
+ description="Data at rest — SQL, KV, files with image transforms, and search behind one handle."
38
48
  href="/docs/elements/store"
39
49
  />
40
50
  <Card
41
51
  title="Clock"
42
- description="Time — schedules, intervals, durable sleeps, and time travel."
52
+ description="Time — schedules, intervals, durable sleep, and deterministic time travel."
43
53
  href="/docs/elements/clock"
44
54
  />
45
55
  <Card
46
56
  title="Gate"
47
- description="Permission to act — auth, tenancy, ABAC, and rate limits at the trigger."
57
+ description="Permission to act — auth, tenancy, ABAC/RBAC, and rate limits at the trigger."
48
58
  href="/docs/elements/gate"
49
59
  />
50
60
  <Card
51
61
  title="Vault"
52
- description="Protected knowledge — fail-loud secret contracts and redacted values."
62
+ description="Protected knowledge — fail-loud secret contracts, dynamic config, and redacted values."
53
63
  href="/docs/elements/vault"
54
64
  />
55
65
  <Card
@@ -59,7 +69,7 @@ Providers and Recipes choose where that infrastructure runs.
59
69
  />
60
70
  <Card
61
71
  title="AI"
62
- description="Reaching machine intelligence — models, prompts, agents, and RAG."
72
+ description="Reaching machine intelligence — models, prompts, agents, and MCP tool boundaries."
63
73
  href="/docs/elements/ai"
64
74
  />
65
75
  </Cards>