okengine 0.18.5 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (510) hide show
  1. package/AGENTS.md +18 -10
  2. package/README.md +2 -2
  3. package/package.json +51 -50
  4. package/site/content/docs/ai/llms-txt.mdx +1 -1
  5. package/site/content/docs/ai/meta.json +1 -1
  6. package/site/content/docs/ai/skills.mdx +4 -1
  7. package/site/content/docs/ai/try-it.mdx +58 -0
  8. package/site/content/docs/client/auth.mdx +208 -0
  9. package/site/content/docs/client/calling.mdx +451 -0
  10. package/site/content/docs/client/index.mdx +209 -0
  11. package/site/content/docs/client/live.mdx +234 -0
  12. package/site/content/docs/client/meta.json +5 -0
  13. package/site/content/docs/client/react.mdx +249 -0
  14. package/site/content/docs/elements/ai/agents.mdx +232 -0
  15. package/site/content/docs/elements/ai/index.mdx +341 -0
  16. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  17. package/site/content/docs/elements/ai/meta.json +5 -0
  18. package/site/content/docs/elements/ai/models.mdx +283 -0
  19. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  20. package/site/content/docs/elements/channel/email.mdx +266 -0
  21. package/site/content/docs/elements/channel/index.mdx +344 -0
  22. package/site/content/docs/elements/channel/meta.json +5 -0
  23. package/site/content/docs/elements/channel/push.mdx +218 -0
  24. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  25. package/site/content/docs/elements/channel/sms.mdx +264 -0
  26. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  27. package/site/content/docs/elements/clock/index.mdx +300 -0
  28. package/site/content/docs/elements/clock/meta.json +5 -0
  29. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  30. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  31. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  32. package/site/content/docs/elements/flow/http.mdx +1080 -0
  33. package/site/content/docs/elements/flow/index.mdx +618 -0
  34. package/site/content/docs/elements/flow/meta.json +5 -0
  35. package/site/content/docs/elements/flow/routing.mdx +559 -0
  36. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  37. package/site/content/docs/elements/gate/auth.mdx +371 -0
  38. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  39. package/site/content/docs/elements/gate/index.mdx +418 -0
  40. package/site/content/docs/elements/gate/meta.json +5 -0
  41. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  42. package/site/content/docs/elements/gate/rls.mdx +303 -0
  43. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  44. package/site/content/docs/elements/index.mdx +20 -10
  45. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  46. package/site/content/docs/elements/signal/index.mdx +352 -0
  47. package/site/content/docs/elements/signal/live.mdx +590 -0
  48. package/site/content/docs/elements/signal/meta.json +5 -0
  49. package/site/content/docs/elements/signal/once.mdx +596 -0
  50. package/site/content/docs/elements/store/files.mdx +659 -0
  51. package/site/content/docs/elements/store/index.mdx +310 -0
  52. package/site/content/docs/elements/store/kv.mdx +629 -0
  53. package/site/content/docs/elements/store/meta.json +5 -0
  54. package/site/content/docs/elements/store/search.mdx +946 -0
  55. package/site/content/docs/elements/store/sql.mdx +937 -0
  56. package/site/content/docs/elements/vault/config.mdx +256 -0
  57. package/site/content/docs/elements/vault/index.mdx +356 -0
  58. package/site/content/docs/elements/vault/meta.json +5 -0
  59. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  60. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  61. package/site/content/docs/index.mdx +63 -36
  62. package/site/content/docs/meta.json +8 -7
  63. package/site/content/docs/plugins/cors.mdx +2 -1
  64. package/site/content/docs/plugins/csrf.mdx +4 -1
  65. package/site/content/docs/plugins/headers.mdx +2 -1
  66. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  67. package/site/content/docs/plugins/magic-link.mdx +6 -0
  68. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  69. package/site/content/docs/plugins/oauth.mdx +1 -1
  70. package/site/content/docs/plugins/otp.mdx +12 -1
  71. package/site/content/docs/plugins/passkey.mdx +39 -15
  72. package/site/content/docs/plugins/two-factor.mdx +91 -34
  73. package/site/content/docs/plugins/username.mdx +1 -1
  74. package/site/content/docs/recipes/caddy.mdx +3 -3
  75. package/site/content/docs/recipes/index.mdx +18 -28
  76. package/site/content/docs/recipes/mailpit.mdx +1 -1
  77. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  78. package/site/content/docs/recipes/meta.json +1 -4
  79. package/site/content/docs/recipes/nginx.mdx +2 -2
  80. package/site/content/docs/recipes/openrouter.mdx +283 -0
  81. package/site/content/docs/recipes/pgdog.mdx +3 -3
  82. package/site/content/docs/recipes/postgres.mdx +1 -2
  83. package/site/content/docs/recipes/rustfs.mdx +2 -2
  84. package/site/content/docs/recipes/traefik.mdx +3 -3
  85. package/site/content/docs/reference/cli.mdx +231 -0
  86. package/site/content/docs/reference/configuration.mdx +30 -10
  87. package/site/content/docs/reference/environment-variables.mdx +93 -20
  88. package/site/content/docs/reference/errors.mdx +132 -29
  89. package/site/content/docs/reference/fx.mdx +137 -73
  90. package/site/content/docs/reference/index.mdx +13 -21
  91. package/site/content/docs/reference/meta.json +4 -5
  92. package/site/content/docs/reference/okid.mdx +42 -17
  93. package/site/content/docs/reference/plugins.mdx +4 -3
  94. package/site/content/docs/reference/security.mdx +197 -0
  95. package/site/content/docs/understand/meta.json +5 -0
  96. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  97. package/site/content/docs/understand/the-model.mdx +32 -0
  98. package/site/content/docs/understand/the-problem.mdx +74 -0
  99. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  100. package/src/auth/api-keys.ts +2 -1
  101. package/src/auth/bindings.ts +64 -16
  102. package/src/auth/gate-auth.test.ts +6 -1
  103. package/src/auth/identity.ts +152 -5
  104. package/src/auth/index.ts +29 -0
  105. package/src/auth/invites.ts +2 -1
  106. package/src/auth/method-context.ts +41 -0
  107. package/src/auth/oauth-as/crypto.ts +2 -1
  108. package/src/auth/oauth-as/stores.ts +2 -1
  109. package/src/auth/operator.ts +2 -1
  110. package/src/auth/sessions-jwt.test.ts +77 -0
  111. package/src/auth/sessions.ts +20 -4
  112. package/src/auth/tenants.ts +3 -2
  113. package/src/auth/two-factor-challenge.test.ts +61 -0
  114. package/src/auth/two-factor-challenge.ts +284 -0
  115. package/src/auth/verification.ts +5 -0
  116. package/src/bench/REPORT.md +49 -0
  117. package/src/bench/g03-signal-once.bench.ts +1 -1
  118. package/src/bench/g10-observability-contention.bench.ts +1 -1
  119. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  120. package/src/bench/load-app.ts +2 -10
  121. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  122. package/src/cli/ai-setup/apply.ts +294 -52
  123. package/src/cli/ai-setup/catalog.ts +238 -1342
  124. package/src/cli/ai-setup/index.ts +14 -99
  125. package/src/cli/ai-setup/prompts.ts +60 -443
  126. package/src/cli/ask-seed.test.ts +96 -0
  127. package/src/cli/ask-seed.ts +82 -0
  128. package/src/cli/ask-vault-gaps.test.ts +84 -0
  129. package/src/cli/ask-vault-gaps.ts +146 -0
  130. package/src/cli/build.ts +2 -2
  131. package/src/cli/client-add.test.ts +26 -1
  132. package/src/cli/client-add.ts +106 -27
  133. package/src/cli/db-seed.ts +2 -0
  134. package/src/cli/db.ts +150 -11
  135. package/src/cli/dev.ts +119 -211
  136. package/src/cli/docker-clean.ts +2 -2
  137. package/src/cli/docker-cli.test.ts +1 -1
  138. package/src/cli/doctor-diff.ts +4 -2
  139. package/src/cli/doctor-pii.test.ts +1 -1
  140. package/src/cli/doctor.ts +14 -1
  141. package/src/cli/hero-meta.test.ts +4 -2
  142. package/src/cli/load-config.images.test.ts +8 -10
  143. package/src/cli/load-config.ts +1 -1
  144. package/src/cli/registry.ts +22 -10
  145. package/src/cli/replay.ts +3 -1
  146. package/src/cli/start.ts +1 -1
  147. package/src/cli/tui/keys.ts +2 -3
  148. package/src/client/auth/cookies.ts +74 -0
  149. package/src/client/auth/create-auth-client.ts +636 -0
  150. package/src/client/auth/denials.ts +99 -0
  151. package/src/client/auth/session.ts +283 -0
  152. package/src/client/auth.test.ts +251 -0
  153. package/src/client/auth.ts +39 -114
  154. package/src/client/create-with-session.ts +245 -0
  155. package/src/client/create.ts +51 -5
  156. package/src/client/index.ts +11 -1
  157. package/src/client/live.ts +11 -79
  158. package/src/client/notes-contract.test.ts +5 -10
  159. package/src/client/sse.ts +137 -0
  160. package/src/client/stream.ts +147 -0
  161. package/src/client/transport.test.ts +32 -0
  162. package/src/client/transport.ts +123 -26
  163. package/src/client/types.ts +118 -14
  164. package/src/client-react/index.ts +185 -24
  165. package/src/client-react/use-live-query.ts +13 -3
  166. package/src/compiler/aot.test.ts +7 -4
  167. package/src/compiler/effects-embed.test.ts +56 -0
  168. package/src/compiler/effects-fetch.test.ts +43 -0
  169. package/src/compiler/effects-infer.ts +58 -2
  170. package/src/compiler/extract.test.ts +257 -43
  171. package/src/compiler/extract.ts +566 -48
  172. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  173. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  174. package/src/compiler/fixtures/skyport.expected.json +4 -4
  175. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  176. package/src/compiler/response.ts +2 -2
  177. package/src/compiler/search-writer-isolation.test.ts +40 -0
  178. package/src/config/index.ts +11 -0
  179. package/src/console/server/app.ts +17 -23
  180. package/src/console/server/bind.ts +4 -0
  181. package/src/console/server/console.test.ts +2 -2
  182. package/src/console/server/flows-invoke.test.ts +50 -34
  183. package/src/console/server/flows.ts +436 -255
  184. package/src/console/server/runs-ingest.test.ts +6 -3
  185. package/src/console/server/serve.ts +1 -1
  186. package/src/console/server/signals.test.ts +1 -5
  187. package/src/console/server/signals.ts +8 -6
  188. package/src/console/server/state.ts +6 -1
  189. package/src/console/server/store.ts +1 -1
  190. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  191. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  192. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  193. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  194. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  195. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  196. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  197. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  198. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  199. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  200. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  201. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  202. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  203. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  204. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  205. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  206. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  207. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  208. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  209. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  210. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  211. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  212. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  213. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  214. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  215. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  216. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  217. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  218. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  219. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  220. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  221. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  222. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  223. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  224. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  225. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  226. package/src/console/ui-next/dist/index.html +6 -13
  227. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  228. package/src/console/ui-next/src/client.ts +7 -2
  229. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  230. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  231. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  232. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  233. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  235. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  236. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  237. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  238. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  239. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  240. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  241. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  242. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  243. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  244. package/src/docker/ai-model-status.test.ts +1 -12
  245. package/src/docker/ai-model-status.ts +10 -38
  246. package/src/docker/compose-up.test.ts +100 -0
  247. package/src/docker/compose-up.ts +292 -0
  248. package/src/docker/compose.ts +4 -14
  249. package/src/docker/derive.ts +9 -34
  250. package/src/docker/docker.test.ts +16 -261
  251. package/src/docker/images-config.test.ts +13 -25
  252. package/src/docker/index.ts +1 -24
  253. package/src/docker/recipes/index.ts +0 -23
  254. package/src/docker/recipes/pgdog.ts +6 -4
  255. package/src/docker/stack-id.test.ts +2 -2
  256. package/src/docker/stack-id.ts +0 -1
  257. package/src/docker/types.ts +2 -2
  258. package/src/drivers/ai-anthropic.ts +10 -0
  259. package/src/drivers/ai-openai-compatible.ts +34 -7
  260. package/src/drivers/ai-providers.test.ts +0 -107
  261. package/src/drivers/ai-stream.test.ts +0 -34
  262. package/src/drivers/ai-types.ts +17 -8
  263. package/src/drivers/channel-fcm.ts +6 -1
  264. package/src/drivers/channel-msegat.ts +6 -1
  265. package/src/drivers/channel-resend.ts +5 -1
  266. package/src/drivers/channel-smtp.ts +5 -1
  267. package/src/drivers/channel-sndr.ts +10 -1
  268. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  269. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  270. package/src/drivers/channel-taqnyat.ts +6 -1
  271. package/src/drivers/channel-types.ts +10 -0
  272. package/src/drivers/channel-unifonic.ts +6 -1
  273. package/src/drivers/channel-wa-cloud.ts +6 -1
  274. package/src/drivers/channel-webpush.ts +6 -1
  275. package/src/drivers/external.ts +33 -0
  276. package/src/drivers/index.ts +0 -10
  277. package/src/drivers/meilisearch.ts +6 -0
  278. package/src/drivers/oauth-types.ts +4 -0
  279. package/src/drivers/postgres.test.ts +74 -3
  280. package/src/drivers/postgres.ts +175 -6
  281. package/src/drivers/signal-types.ts +5 -5
  282. package/src/drivers/types.ts +7 -0
  283. package/src/drivers/vault-types.ts +5 -0
  284. package/src/elements/ai/declare.ts +17 -4
  285. package/src/elements/ai/eval.ts +1 -1
  286. package/src/elements/ai/mcp-http.ts +1 -1
  287. package/src/elements/ai/pii.ts +1 -1
  288. package/src/elements/ai/providers.test.ts +289 -0
  289. package/src/elements/ai/providers.ts +169 -0
  290. package/src/elements/ai/runtime.ts +68 -5
  291. package/src/elements/ai/schema.ts +2 -2
  292. package/src/elements/ai.test.ts +7 -7
  293. package/src/elements/ai.ts +17 -1
  294. package/src/elements/channel/runtime.ts +105 -12
  295. package/src/elements/clock/cron-fields.test.ts +144 -0
  296. package/src/elements/clock/cron-fields.ts +185 -0
  297. package/src/elements/clock/declare.ts +247 -3
  298. package/src/elements/clock.ts +21 -1
  299. package/src/elements/index.ts +15 -0
  300. package/src/elements/signal/chaos-child.ts +1 -2
  301. package/src/elements/signal/declare.ts +65 -37
  302. package/src/elements/signal/delivery-modes.test.ts +11 -31
  303. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  304. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  305. package/src/elements/signal/key-ordering.test.ts +6 -26
  306. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  307. package/src/elements/signal/optional-emit.test.ts +6 -9
  308. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  309. package/src/elements/signal/orphan-messages.test.ts +4 -15
  310. package/src/elements/signal/reconcile.test.ts +2 -2
  311. package/src/elements/signal/runtime.ts +1 -1
  312. package/src/elements/signal/schema-emit.test.ts +4 -8
  313. package/src/elements/signal.test.ts +24 -49
  314. package/src/elements/signal.ts +9 -2
  315. package/src/elements/store/domain-ddl.test.ts +1 -1
  316. package/src/elements/store/live-http.test.ts +9 -4
  317. package/src/elements/store/prepare-row.test.ts +123 -0
  318. package/src/elements/store/resource.ts +43 -12
  319. package/src/elements/store/schema-decl.ts +117 -0
  320. package/src/elements/store/search-backfill.ts +205 -0
  321. package/src/elements/store/search-bind.ts +66 -0
  322. package/src/elements/store/search-bm25.ts +78 -0
  323. package/src/elements/store/search-ddl.ts +156 -0
  324. package/src/elements/store/search-embed-flow.ts +141 -0
  325. package/src/elements/store/search-errors.ts +34 -0
  326. package/src/elements/store/search-fusion.ts +112 -0
  327. package/src/elements/store/search-lsh.ts +179 -0
  328. package/src/elements/store/search-runtime.ts +300 -0
  329. package/src/elements/store/search.test.ts +144 -0
  330. package/src/elements/store/sql-session.test.ts +1 -0
  331. package/src/elements/store/sql-session.ts +83 -3
  332. package/src/elements/store/table.ts +23 -2
  333. package/src/elements/store/upsert-app.test.ts +1 -3
  334. package/src/elements/store.ts +50 -0
  335. package/src/full.ts +4 -2
  336. package/src/http.ts +4 -1
  337. package/src/i18n/catalogs/ar.ts +14 -6
  338. package/src/i18n/catalogs/en.ts +14 -6
  339. package/src/index.ts +6 -1
  340. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  341. package/src/kernel/adopt-routes.ts +9 -1
  342. package/src/kernel/app-auth.ts +5 -0
  343. package/src/kernel/app.ts +102 -9
  344. package/src/kernel/auto-cache.test.ts +6 -12
  345. package/src/kernel/auto-registry.test.ts +3 -3
  346. package/src/kernel/boot-bind/ai.test.ts +22 -19
  347. package/src/kernel/boot-bind/ai.ts +5 -43
  348. package/src/kernel/boot-bind/clock.ts +23 -5
  349. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  350. package/src/kernel/boot.test.ts +11 -6
  351. package/src/kernel/boot.ts +66 -16
  352. package/src/kernel/boundary-contract.ts +93 -0
  353. package/src/kernel/budget.test.ts +1 -1
  354. package/src/kernel/call.ts +89 -0
  355. package/src/kernel/capability.ts +6 -0
  356. package/src/kernel/client-descriptor.ts +123 -0
  357. package/src/kernel/clock-timezone.test.ts +80 -0
  358. package/src/kernel/correlation.test.ts +1 -1
  359. package/src/kernel/dry-run.ts +11 -8
  360. package/src/kernel/effects-stamping.test.ts +42 -9
  361. package/src/kernel/effects.test.ts +4 -2
  362. package/src/kernel/effects.ts +51 -9
  363. package/src/kernel/errors-channel.ts +17 -0
  364. package/src/kernel/errors-live-resume.ts +3 -2
  365. package/src/kernel/errors-tenant.ts +7 -4
  366. package/src/kernel/errors.registry-helpers.ts +96 -0
  367. package/src/kernel/errors.registry.test.ts +139 -25
  368. package/src/kernel/errors.ts +102 -23
  369. package/src/kernel/external-effects.test.ts +196 -0
  370. package/src/kernel/flow.test.ts +13 -4
  371. package/src/kernel/flow.ts +69 -71
  372. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  373. package/src/kernel/fx-dead-letters.test.ts +3 -3
  374. package/src/kernel/fx-fetch.ts +55 -0
  375. package/src/kernel/fx-live-stream.ts +2 -2
  376. package/src/kernel/fx-live.test.ts +8 -8
  377. package/src/kernel/fx.test.ts +17 -11
  378. package/src/kernel/fx.ts +180 -57
  379. package/src/kernel/horizontal-child.ts +1 -1
  380. package/src/kernel/http-query.test.ts +3 -6
  381. package/src/kernel/index.ts +13 -3
  382. package/src/kernel/instance-id.ts +1 -1
  383. package/src/kernel/instances.test.ts +40 -0
  384. package/src/kernel/instances.ts +47 -9
  385. package/src/kernel/live-http.test.ts +6 -7
  386. package/src/kernel/live-http.ts +6 -2
  387. package/src/kernel/live-resume.test.ts +1 -1
  388. package/src/kernel/mcp-tool.test.ts +3 -3
  389. package/src/kernel/on.ts +98 -4
  390. package/src/kernel/pipeline.test.ts +12 -15
  391. package/src/kernel/plugin-elements.test.ts +1 -1
  392. package/src/kernel/stamp-http.test.ts +3 -3
  393. package/src/kernel/triggers.ts +210 -95
  394. package/src/kernel-entry.ts +0 -1
  395. package/src/manifest/diff.ts +11 -1
  396. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  397. package/src/manifest/types.ts +46 -2
  398. package/src/mcp/docs-index.ts +3 -3
  399. package/src/mcp/docs-mcp.test.ts +2 -2
  400. package/src/mcp/docs-tools.ts +1 -1
  401. package/src/okid.test.ts +56 -0
  402. package/src/okid.ts +55 -11
  403. package/src/plugins/anonymous.ts +8 -4
  404. package/src/plugins/auth/shared.ts +27 -3
  405. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  406. package/src/plugins/auth-methods.security.test.ts +561 -23
  407. package/src/plugins/config-source.ts +1 -1
  408. package/src/plugins/csrf.test.ts +65 -0
  409. package/src/plugins/index.ts +2 -0
  410. package/src/plugins/magic-link.ts +36 -16
  411. package/src/plugins/oauth/shared.ts +3 -1
  412. package/src/plugins/oauth.ts +22 -14
  413. package/src/plugins/otp.ts +37 -21
  414. package/src/plugins/passkey-webauthn.ts +9 -6
  415. package/src/plugins/passkey.ts +98 -26
  416. package/src/plugins/pre-account-hijack.test.ts +223 -0
  417. package/src/plugins/two-factor.ts +466 -37
  418. package/src/plugins/username.ts +19 -7
  419. package/src/release/build-lib.ts +1 -0
  420. package/src/release/limits.ts +2 -2
  421. package/src/release/measure.ts +1 -1
  422. package/src/runs/collect.test.ts +0 -2
  423. package/src/runtime/json-code-block.test.ts +250 -20
  424. package/src/runtime/json-code-block.ts +1261 -41
  425. package/src/term.test.ts +1 -1
  426. package/src/test/create-test-app.test.ts +12 -12
  427. package/src/test/live-signals.test.ts +6 -6
  428. package/src/test/provisions.integration.test.ts +10 -14
  429. package/src/test/reset-element-registries.ts +1 -1
  430. package/src/test/tenant-isolation.test.ts +12 -6
  431. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  432. package/site/content/docs/deployment/docker.mdx +0 -227
  433. package/site/content/docs/deployment/index.mdx +0 -83
  434. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  435. package/site/content/docs/deployment/meta.json +0 -5
  436. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  437. package/site/content/docs/elements/ai.mdx +0 -385
  438. package/site/content/docs/elements/channel.mdx +0 -346
  439. package/site/content/docs/elements/clock.mdx +0 -244
  440. package/site/content/docs/elements/flow.mdx +0 -420
  441. package/site/content/docs/elements/gate.mdx +0 -436
  442. package/site/content/docs/elements/signal.mdx +0 -380
  443. package/site/content/docs/elements/store.mdx +0 -1099
  444. package/site/content/docs/elements/vault.mdx +0 -405
  445. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  446. package/site/content/docs/get-started/index.mdx +0 -43
  447. package/site/content/docs/get-started/installation.mdx +0 -220
  448. package/site/content/docs/get-started/introduction.mdx +0 -144
  449. package/site/content/docs/get-started/meta.json +0 -13
  450. package/site/content/docs/get-started/project-structure.mdx +0 -925
  451. package/site/content/docs/get-started/testing.mdx +0 -328
  452. package/site/content/docs/get-started/why.mdx +0 -114
  453. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  454. package/site/content/docs/recipes/ollama.mdx +0 -142
  455. package/site/content/docs/recipes/sglang.mdx +0 -105
  456. package/site/content/docs/recipes/vllm.mdx +0 -106
  457. package/site/content/docs/reference/cli.md +0 -232
  458. package/site/content/docs/reference/client.mdx +0 -469
  459. package/site/content/docs/reference/security.md +0 -74
  460. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  461. package/src/cli/ai-setup/recommend.test.ts +0 -225
  462. package/src/cli/ai-setup/recommend.ts +0 -225
  463. package/src/cli/dev-controls.test.ts +0 -122
  464. package/src/cli/dev-controls.ts +0 -164
  465. package/src/cli/tui/DevLive.tsx +0 -126
  466. package/src/console/ui-next/dist/assets/access-page-3-EFj-2G.js +0 -4
  467. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  468. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  469. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  470. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  471. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  472. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  473. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  474. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  475. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  476. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  477. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  478. package/src/console/ui-next/dist/assets/flows-page-cVFnA4HH.js +0 -1
  479. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  480. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  481. package/src/console/ui-next/dist/assets/index-CMIgUbD0.js +0 -66
  482. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  483. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  484. package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.js +0 -4
  485. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  486. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  487. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  488. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  489. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  490. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  491. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  492. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  493. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  494. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  495. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  496. package/src/console/ui-next/dist/assets/units-page-l8FeKfnP.js +0 -1
  497. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  498. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  499. package/src/console/ui-next/dist/assets/vault-page-CL-d_mLE.js +0 -2
  500. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  501. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  502. package/src/docker/ollama-pull.ts +0 -232
  503. package/src/docker/recipes/llama-cpp.ts +0 -298
  504. package/src/docker/recipes/ollama.ts +0 -44
  505. package/src/docker/recipes/sglang.ts +0 -55
  506. package/src/docker/recipes/vllm.ts +0 -44
  507. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  508. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  509. package/src/drivers/ai-ollama.ts +0 -389
  510. package/src/drivers/ollama.ts +0 -14
@@ -0,0 +1,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,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>