okengine 0.18.4 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (512) hide show
  1. package/AGENTS.md +18 -10
  2. package/README.md +2 -2
  3. package/package.json +51 -50
  4. package/site/content/docs/ai/index.mdx +25 -6
  5. package/site/content/docs/ai/llms-txt.mdx +1 -1
  6. package/site/content/docs/ai/meta.json +1 -1
  7. package/site/content/docs/ai/skills.mdx +4 -1
  8. package/site/content/docs/ai/try-it.mdx +58 -0
  9. package/site/content/docs/client/auth.mdx +208 -0
  10. package/site/content/docs/client/calling.mdx +451 -0
  11. package/site/content/docs/client/index.mdx +209 -0
  12. package/site/content/docs/client/live.mdx +234 -0
  13. package/site/content/docs/client/meta.json +5 -0
  14. package/site/content/docs/client/react.mdx +249 -0
  15. package/site/content/docs/elements/ai/agents.mdx +232 -0
  16. package/site/content/docs/elements/ai/index.mdx +341 -0
  17. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  18. package/site/content/docs/elements/ai/meta.json +5 -0
  19. package/site/content/docs/elements/ai/models.mdx +283 -0
  20. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  21. package/site/content/docs/elements/channel/email.mdx +266 -0
  22. package/site/content/docs/elements/channel/index.mdx +344 -0
  23. package/site/content/docs/elements/channel/meta.json +5 -0
  24. package/site/content/docs/elements/channel/push.mdx +218 -0
  25. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  26. package/site/content/docs/elements/channel/sms.mdx +264 -0
  27. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  28. package/site/content/docs/elements/clock/index.mdx +300 -0
  29. package/site/content/docs/elements/clock/meta.json +5 -0
  30. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  31. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  32. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  33. package/site/content/docs/elements/flow/http.mdx +1080 -0
  34. package/site/content/docs/elements/flow/index.mdx +618 -0
  35. package/site/content/docs/elements/flow/meta.json +5 -0
  36. package/site/content/docs/elements/flow/routing.mdx +559 -0
  37. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  38. package/site/content/docs/elements/gate/auth.mdx +371 -0
  39. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  40. package/site/content/docs/elements/gate/index.mdx +418 -0
  41. package/site/content/docs/elements/gate/meta.json +5 -0
  42. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  43. package/site/content/docs/elements/gate/rls.mdx +303 -0
  44. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  45. package/site/content/docs/elements/index.mdx +52 -11
  46. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  47. package/site/content/docs/elements/signal/index.mdx +352 -0
  48. package/site/content/docs/elements/signal/live.mdx +590 -0
  49. package/site/content/docs/elements/signal/meta.json +5 -0
  50. package/site/content/docs/elements/signal/once.mdx +596 -0
  51. package/site/content/docs/elements/store/files.mdx +659 -0
  52. package/site/content/docs/elements/store/index.mdx +310 -0
  53. package/site/content/docs/elements/store/kv.mdx +629 -0
  54. package/site/content/docs/elements/store/meta.json +5 -0
  55. package/site/content/docs/elements/store/search.mdx +946 -0
  56. package/site/content/docs/elements/store/sql.mdx +937 -0
  57. package/site/content/docs/elements/vault/config.mdx +256 -0
  58. package/site/content/docs/elements/vault/index.mdx +356 -0
  59. package/site/content/docs/elements/vault/meta.json +5 -0
  60. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  61. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  62. package/site/content/docs/index.mdx +78 -30
  63. package/site/content/docs/meta.json +11 -8
  64. package/site/content/docs/plugins/cors.mdx +2 -1
  65. package/site/content/docs/plugins/csrf.mdx +4 -1
  66. package/site/content/docs/plugins/headers.mdx +2 -1
  67. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  68. package/site/content/docs/plugins/magic-link.mdx +6 -0
  69. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  70. package/site/content/docs/plugins/oauth.mdx +1 -1
  71. package/site/content/docs/plugins/otp.mdx +12 -1
  72. package/site/content/docs/plugins/passkey.mdx +39 -15
  73. package/site/content/docs/plugins/two-factor.mdx +91 -34
  74. package/site/content/docs/plugins/username.mdx +1 -1
  75. package/site/content/docs/recipes/caddy.mdx +3 -3
  76. package/site/content/docs/recipes/index.mdx +18 -28
  77. package/site/content/docs/recipes/mailpit.mdx +1 -1
  78. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  79. package/site/content/docs/recipes/meta.json +1 -4
  80. package/site/content/docs/recipes/nginx.mdx +2 -2
  81. package/site/content/docs/recipes/openrouter.mdx +283 -0
  82. package/site/content/docs/recipes/pgdog.mdx +3 -3
  83. package/site/content/docs/recipes/postgres.mdx +1 -2
  84. package/site/content/docs/recipes/rustfs.mdx +2 -2
  85. package/site/content/docs/recipes/traefik.mdx +3 -3
  86. package/site/content/docs/reference/cli.mdx +231 -0
  87. package/site/content/docs/reference/configuration.mdx +30 -10
  88. package/site/content/docs/reference/environment-variables.mdx +93 -20
  89. package/site/content/docs/reference/errors.mdx +132 -29
  90. package/site/content/docs/reference/fx.mdx +137 -73
  91. package/site/content/docs/reference/index.mdx +13 -21
  92. package/site/content/docs/reference/meta.json +4 -5
  93. package/site/content/docs/reference/okid.mdx +42 -17
  94. package/site/content/docs/reference/plugins.mdx +4 -3
  95. package/site/content/docs/reference/security.mdx +197 -0
  96. package/site/content/docs/understand/meta.json +5 -0
  97. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  98. package/site/content/docs/understand/the-model.mdx +32 -0
  99. package/site/content/docs/understand/the-problem.mdx +74 -0
  100. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  101. package/src/auth/api-keys.ts +2 -1
  102. package/src/auth/bindings.ts +64 -16
  103. package/src/auth/gate-auth.test.ts +6 -1
  104. package/src/auth/identity.ts +152 -5
  105. package/src/auth/index.ts +29 -0
  106. package/src/auth/invites.ts +2 -1
  107. package/src/auth/method-context.ts +41 -0
  108. package/src/auth/oauth-as/crypto.ts +2 -1
  109. package/src/auth/oauth-as/stores.ts +2 -1
  110. package/src/auth/operator.ts +2 -1
  111. package/src/auth/sessions-jwt.test.ts +77 -0
  112. package/src/auth/sessions.ts +20 -4
  113. package/src/auth/tenants.ts +3 -2
  114. package/src/auth/two-factor-challenge.test.ts +61 -0
  115. package/src/auth/two-factor-challenge.ts +284 -0
  116. package/src/auth/verification.ts +5 -0
  117. package/src/bench/REPORT.md +49 -0
  118. package/src/bench/g03-signal-once.bench.ts +1 -1
  119. package/src/bench/g10-observability-contention.bench.ts +1 -1
  120. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  121. package/src/bench/load-app.ts +2 -10
  122. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  123. package/src/cli/ai-setup/apply.ts +294 -52
  124. package/src/cli/ai-setup/catalog.ts +238 -1342
  125. package/src/cli/ai-setup/index.ts +14 -99
  126. package/src/cli/ai-setup/prompts.ts +60 -443
  127. package/src/cli/ask-seed.test.ts +96 -0
  128. package/src/cli/ask-seed.ts +82 -0
  129. package/src/cli/ask-vault-gaps.test.ts +84 -0
  130. package/src/cli/ask-vault-gaps.ts +146 -0
  131. package/src/cli/build.ts +2 -2
  132. package/src/cli/client-add.test.ts +26 -1
  133. package/src/cli/client-add.ts +106 -27
  134. package/src/cli/competitor-mention-removal.test.ts +1 -1
  135. package/src/cli/db-seed.ts +2 -0
  136. package/src/cli/db.ts +150 -11
  137. package/src/cli/dev.ts +119 -211
  138. package/src/cli/docker-clean.ts +2 -2
  139. package/src/cli/docker-cli.test.ts +1 -1
  140. package/src/cli/doctor-diff.ts +4 -2
  141. package/src/cli/doctor-pii.test.ts +1 -1
  142. package/src/cli/doctor.ts +14 -1
  143. package/src/cli/hero-meta.test.ts +4 -2
  144. package/src/cli/load-config.images.test.ts +8 -10
  145. package/src/cli/load-config.ts +1 -1
  146. package/src/cli/registry.ts +22 -10
  147. package/src/cli/replay.ts +3 -1
  148. package/src/cli/start.ts +1 -1
  149. package/src/cli/tui/keys.ts +2 -3
  150. package/src/client/auth/cookies.ts +74 -0
  151. package/src/client/auth/create-auth-client.ts +636 -0
  152. package/src/client/auth/denials.ts +99 -0
  153. package/src/client/auth/session.ts +283 -0
  154. package/src/client/auth.test.ts +251 -0
  155. package/src/client/auth.ts +39 -114
  156. package/src/client/create-with-session.ts +245 -0
  157. package/src/client/create.ts +51 -5
  158. package/src/client/index.ts +11 -1
  159. package/src/client/live.ts +11 -79
  160. package/src/client/notes-contract.test.ts +5 -10
  161. package/src/client/sse.ts +137 -0
  162. package/src/client/stream.ts +147 -0
  163. package/src/client/transport.test.ts +32 -0
  164. package/src/client/transport.ts +123 -26
  165. package/src/client/types.ts +118 -14
  166. package/src/client-react/index.ts +185 -24
  167. package/src/client-react/use-live-query.ts +13 -3
  168. package/src/compiler/aot.test.ts +7 -4
  169. package/src/compiler/effects-embed.test.ts +56 -0
  170. package/src/compiler/effects-fetch.test.ts +43 -0
  171. package/src/compiler/effects-infer.ts +58 -2
  172. package/src/compiler/extract.test.ts +258 -44
  173. package/src/compiler/extract.ts +566 -48
  174. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  175. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  176. package/src/compiler/fixtures/skyport.expected.json +4 -4
  177. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  178. package/src/compiler/response.ts +2 -2
  179. package/src/compiler/search-writer-isolation.test.ts +40 -0
  180. package/src/config/index.ts +11 -0
  181. package/src/console/server/app.ts +17 -23
  182. package/src/console/server/bind.ts +4 -0
  183. package/src/console/server/console.test.ts +2 -2
  184. package/src/console/server/flows-invoke.test.ts +50 -34
  185. package/src/console/server/flows.ts +436 -255
  186. package/src/console/server/runs-ingest.test.ts +6 -3
  187. package/src/console/server/serve.ts +1 -1
  188. package/src/console/server/signals.test.ts +1 -5
  189. package/src/console/server/signals.ts +8 -6
  190. package/src/console/server/state.ts +6 -1
  191. package/src/console/server/store.ts +1 -1
  192. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  193. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  194. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  195. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  196. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  197. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  198. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  199. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  200. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  201. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  202. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  203. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  204. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  205. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  206. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  207. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  208. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  209. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  210. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  211. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  212. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  213. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  214. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  215. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  216. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  217. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  218. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  219. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  220. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  221. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  222. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  223. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  224. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  225. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  226. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  227. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  228. package/src/console/ui-next/dist/index.html +6 -13
  229. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  230. package/src/console/ui-next/src/client.ts +7 -2
  231. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  232. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  233. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  235. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  236. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  237. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  238. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  239. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  240. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  241. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  242. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  243. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  244. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  245. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  246. package/src/docker/ai-model-status.test.ts +1 -12
  247. package/src/docker/ai-model-status.ts +10 -38
  248. package/src/docker/compose-up.test.ts +100 -0
  249. package/src/docker/compose-up.ts +292 -0
  250. package/src/docker/compose.ts +4 -14
  251. package/src/docker/derive.ts +9 -34
  252. package/src/docker/docker.test.ts +16 -261
  253. package/src/docker/images-config.test.ts +13 -25
  254. package/src/docker/index.ts +1 -24
  255. package/src/docker/recipes/index.ts +0 -23
  256. package/src/docker/recipes/pgdog.ts +6 -4
  257. package/src/docker/stack-id.test.ts +2 -2
  258. package/src/docker/stack-id.ts +0 -1
  259. package/src/docker/types.ts +2 -2
  260. package/src/drivers/ai-anthropic.ts +10 -0
  261. package/src/drivers/ai-openai-compatible.ts +34 -7
  262. package/src/drivers/ai-providers.test.ts +0 -107
  263. package/src/drivers/ai-stream.test.ts +0 -34
  264. package/src/drivers/ai-types.ts +17 -8
  265. package/src/drivers/channel-fcm.ts +6 -1
  266. package/src/drivers/channel-msegat.ts +6 -1
  267. package/src/drivers/channel-resend.ts +5 -1
  268. package/src/drivers/channel-smtp.ts +5 -1
  269. package/src/drivers/channel-sndr.ts +10 -1
  270. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  271. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  272. package/src/drivers/channel-taqnyat.ts +6 -1
  273. package/src/drivers/channel-types.ts +10 -0
  274. package/src/drivers/channel-unifonic.ts +6 -1
  275. package/src/drivers/channel-wa-cloud.ts +6 -1
  276. package/src/drivers/channel-webpush.ts +6 -1
  277. package/src/drivers/external.ts +33 -0
  278. package/src/drivers/index.ts +0 -10
  279. package/src/drivers/meilisearch.ts +6 -0
  280. package/src/drivers/oauth-types.ts +4 -0
  281. package/src/drivers/postgres.test.ts +74 -3
  282. package/src/drivers/postgres.ts +175 -6
  283. package/src/drivers/signal-types.ts +5 -5
  284. package/src/drivers/types.ts +7 -0
  285. package/src/drivers/vault-types.ts +5 -0
  286. package/src/elements/ai/declare.ts +17 -4
  287. package/src/elements/ai/eval.ts +1 -1
  288. package/src/elements/ai/mcp-http.ts +1 -1
  289. package/src/elements/ai/pii.ts +1 -1
  290. package/src/elements/ai/providers.test.ts +289 -0
  291. package/src/elements/ai/providers.ts +169 -0
  292. package/src/elements/ai/runtime.ts +68 -5
  293. package/src/elements/ai/schema.ts +2 -2
  294. package/src/elements/ai.test.ts +7 -7
  295. package/src/elements/ai.ts +17 -1
  296. package/src/elements/channel/runtime.ts +105 -12
  297. package/src/elements/clock/cron-fields.test.ts +144 -0
  298. package/src/elements/clock/cron-fields.ts +185 -0
  299. package/src/elements/clock/declare.ts +247 -3
  300. package/src/elements/clock.ts +21 -1
  301. package/src/elements/index.ts +15 -0
  302. package/src/elements/signal/chaos-child.ts +1 -2
  303. package/src/elements/signal/declare.ts +65 -37
  304. package/src/elements/signal/delivery-modes.test.ts +11 -31
  305. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  306. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  307. package/src/elements/signal/key-ordering.test.ts +6 -26
  308. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  309. package/src/elements/signal/optional-emit.test.ts +6 -9
  310. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  311. package/src/elements/signal/orphan-messages.test.ts +4 -15
  312. package/src/elements/signal/reconcile.test.ts +2 -2
  313. package/src/elements/signal/runtime.ts +1 -1
  314. package/src/elements/signal/schema-emit.test.ts +4 -8
  315. package/src/elements/signal.test.ts +24 -49
  316. package/src/elements/signal.ts +9 -2
  317. package/src/elements/store/domain-ddl.test.ts +1 -1
  318. package/src/elements/store/live-http.test.ts +9 -4
  319. package/src/elements/store/prepare-row.test.ts +123 -0
  320. package/src/elements/store/resource.ts +43 -12
  321. package/src/elements/store/schema-decl.ts +117 -0
  322. package/src/elements/store/search-backfill.ts +205 -0
  323. package/src/elements/store/search-bind.ts +66 -0
  324. package/src/elements/store/search-bm25.ts +78 -0
  325. package/src/elements/store/search-ddl.ts +156 -0
  326. package/src/elements/store/search-embed-flow.ts +141 -0
  327. package/src/elements/store/search-errors.ts +34 -0
  328. package/src/elements/store/search-fusion.ts +112 -0
  329. package/src/elements/store/search-lsh.ts +179 -0
  330. package/src/elements/store/search-runtime.ts +300 -0
  331. package/src/elements/store/search.test.ts +144 -0
  332. package/src/elements/store/sql-session.test.ts +1 -0
  333. package/src/elements/store/sql-session.ts +83 -3
  334. package/src/elements/store/table.ts +23 -2
  335. package/src/elements/store/upsert-app.test.ts +1 -3
  336. package/src/elements/store.ts +50 -0
  337. package/src/full.ts +4 -2
  338. package/src/http.ts +4 -1
  339. package/src/i18n/catalogs/ar.ts +14 -6
  340. package/src/i18n/catalogs/en.ts +14 -6
  341. package/src/index.ts +6 -1
  342. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  343. package/src/kernel/adopt-routes.ts +9 -1
  344. package/src/kernel/app-auth.ts +5 -0
  345. package/src/kernel/app.ts +102 -9
  346. package/src/kernel/auto-cache.test.ts +6 -12
  347. package/src/kernel/auto-registry.test.ts +3 -3
  348. package/src/kernel/boot-bind/ai.test.ts +22 -19
  349. package/src/kernel/boot-bind/ai.ts +5 -43
  350. package/src/kernel/boot-bind/clock.ts +23 -5
  351. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  352. package/src/kernel/boot.test.ts +11 -6
  353. package/src/kernel/boot.ts +66 -16
  354. package/src/kernel/boundary-contract.ts +93 -0
  355. package/src/kernel/budget.test.ts +1 -1
  356. package/src/kernel/call.ts +89 -0
  357. package/src/kernel/capability.ts +6 -0
  358. package/src/kernel/client-descriptor.ts +123 -0
  359. package/src/kernel/clock-timezone.test.ts +80 -0
  360. package/src/kernel/correlation.test.ts +1 -1
  361. package/src/kernel/dry-run.ts +11 -8
  362. package/src/kernel/effects-stamping.test.ts +42 -9
  363. package/src/kernel/effects.test.ts +4 -2
  364. package/src/kernel/effects.ts +51 -9
  365. package/src/kernel/errors-channel.ts +17 -0
  366. package/src/kernel/errors-live-resume.ts +3 -2
  367. package/src/kernel/errors-tenant.ts +7 -4
  368. package/src/kernel/errors.registry-helpers.ts +96 -0
  369. package/src/kernel/errors.registry.test.ts +139 -25
  370. package/src/kernel/errors.ts +102 -23
  371. package/src/kernel/external-effects.test.ts +196 -0
  372. package/src/kernel/flow.test.ts +13 -4
  373. package/src/kernel/flow.ts +69 -71
  374. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  375. package/src/kernel/fx-dead-letters.test.ts +3 -3
  376. package/src/kernel/fx-fetch.ts +55 -0
  377. package/src/kernel/fx-live-stream.ts +2 -2
  378. package/src/kernel/fx-live.test.ts +8 -8
  379. package/src/kernel/fx.test.ts +17 -11
  380. package/src/kernel/fx.ts +180 -57
  381. package/src/kernel/horizontal-child.ts +1 -1
  382. package/src/kernel/http-query.test.ts +3 -6
  383. package/src/kernel/index.ts +13 -3
  384. package/src/kernel/instance-id.ts +1 -1
  385. package/src/kernel/instances.test.ts +40 -0
  386. package/src/kernel/instances.ts +47 -9
  387. package/src/kernel/live-http.test.ts +6 -7
  388. package/src/kernel/live-http.ts +6 -2
  389. package/src/kernel/live-resume.test.ts +1 -1
  390. package/src/kernel/mcp-tool.test.ts +3 -3
  391. package/src/kernel/on.ts +98 -4
  392. package/src/kernel/pipeline.test.ts +12 -15
  393. package/src/kernel/plugin-elements.test.ts +1 -1
  394. package/src/kernel/stamp-http.test.ts +3 -3
  395. package/src/kernel/triggers.ts +210 -95
  396. package/src/kernel-entry.ts +0 -1
  397. package/src/manifest/diff.ts +11 -1
  398. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  399. package/src/manifest/types.ts +46 -2
  400. package/src/mcp/docs-index.ts +3 -3
  401. package/src/mcp/docs-mcp.test.ts +2 -2
  402. package/src/mcp/docs-tools.ts +1 -1
  403. package/src/okid.test.ts +56 -0
  404. package/src/okid.ts +55 -11
  405. package/src/plugins/anonymous.ts +8 -4
  406. package/src/plugins/auth/shared.ts +27 -3
  407. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  408. package/src/plugins/auth-methods.security.test.ts +561 -23
  409. package/src/plugins/config-source.ts +1 -1
  410. package/src/plugins/csrf.test.ts +65 -0
  411. package/src/plugins/index.ts +2 -0
  412. package/src/plugins/magic-link.ts +36 -16
  413. package/src/plugins/oauth/shared.ts +3 -1
  414. package/src/plugins/oauth.ts +22 -14
  415. package/src/plugins/otp.ts +37 -21
  416. package/src/plugins/passkey-webauthn.ts +9 -6
  417. package/src/plugins/passkey.ts +98 -26
  418. package/src/plugins/pre-account-hijack.test.ts +223 -0
  419. package/src/plugins/two-factor.ts +466 -37
  420. package/src/plugins/username.ts +19 -7
  421. package/src/release/build-lib.ts +1 -0
  422. package/src/release/limits.ts +2 -2
  423. package/src/release/measure.ts +1 -1
  424. package/src/runs/collect.test.ts +0 -2
  425. package/src/runtime/json-code-block.test.ts +250 -20
  426. package/src/runtime/json-code-block.ts +1261 -41
  427. package/src/term.test.ts +1 -1
  428. package/src/test/create-test-app.test.ts +12 -12
  429. package/src/test/live-signals.test.ts +6 -6
  430. package/src/test/provisions.integration.test.ts +10 -14
  431. package/src/test/reset-element-registries.ts +1 -1
  432. package/src/test/tenant-isolation.test.ts +12 -6
  433. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  434. package/site/content/docs/deployment/docker.mdx +0 -227
  435. package/site/content/docs/deployment/index.mdx +0 -83
  436. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  437. package/site/content/docs/deployment/meta.json +0 -5
  438. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  439. package/site/content/docs/elements/ai.mdx +0 -385
  440. package/site/content/docs/elements/channel.mdx +0 -346
  441. package/site/content/docs/elements/clock.mdx +0 -244
  442. package/site/content/docs/elements/flow.mdx +0 -420
  443. package/site/content/docs/elements/gate.mdx +0 -436
  444. package/site/content/docs/elements/signal.mdx +0 -380
  445. package/site/content/docs/elements/store.mdx +0 -1099
  446. package/site/content/docs/elements/vault.mdx +0 -405
  447. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  448. package/site/content/docs/get-started/index.mdx +0 -43
  449. package/site/content/docs/get-started/installation.mdx +0 -220
  450. package/site/content/docs/get-started/introduction.mdx +0 -132
  451. package/site/content/docs/get-started/meta.json +0 -13
  452. package/site/content/docs/get-started/project-structure.mdx +0 -925
  453. package/site/content/docs/get-started/testing.mdx +0 -328
  454. package/site/content/docs/get-started/why.mdx +0 -162
  455. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  456. package/site/content/docs/recipes/ollama.mdx +0 -142
  457. package/site/content/docs/recipes/sglang.mdx +0 -105
  458. package/site/content/docs/recipes/vllm.mdx +0 -106
  459. package/site/content/docs/reference/cli.md +0 -232
  460. package/site/content/docs/reference/client.mdx +0 -469
  461. package/site/content/docs/reference/security.md +0 -74
  462. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  463. package/src/cli/ai-setup/recommend.test.ts +0 -225
  464. package/src/cli/ai-setup/recommend.ts +0 -225
  465. package/src/cli/dev-controls.test.ts +0 -122
  466. package/src/cli/dev-controls.ts +0 -164
  467. package/src/cli/tui/DevLive.tsx +0 -126
  468. package/src/console/ui-next/dist/assets/access-page-De7Lc2JC.js +0 -4
  469. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  470. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  471. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  472. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  473. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  474. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  475. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  476. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  477. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  478. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  479. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  480. package/src/console/ui-next/dist/assets/flows-page-RGy7VEA_.js +0 -1
  481. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  482. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  483. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  484. package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
  485. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  486. package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.js +0 -4
  487. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  488. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  489. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  490. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  491. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  492. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  493. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  494. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  495. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  496. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  497. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  498. package/src/console/ui-next/dist/assets/units-page-4rHOePuE.js +0 -1
  499. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  500. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  501. package/src/console/ui-next/dist/assets/vault-page-DISPgxLM.js +0 -2
  502. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  503. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  504. package/src/docker/ollama-pull.ts +0 -232
  505. package/src/docker/recipes/llama-cpp.ts +0 -298
  506. package/src/docker/recipes/ollama.ts +0 -44
  507. package/src/docker/recipes/sglang.ts +0 -55
  508. package/src/docker/recipes/vllm.ts +0 -44
  509. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  510. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  511. package/src/drivers/ai-ollama.ts +0 -389
  512. package/src/drivers/ollama.ts +0 -14
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OKE1014 — kept off the Store-only `oke()` graph.
2
+ * OKE1210 — kept off the Store-only `oke()` graph.
3
3
  *
4
4
  * Signal drivers throw this when a Last-Event-ID is missing from the tape.
5
5
  * Loaded via computed `import.meta.require` from {@link lookupOkeError}.
@@ -9,7 +9,8 @@ import type { OkeErrorDefinition } from "./errors.ts";
9
9
 
10
10
  /** Last-Event-ID is missing from the retained live tape. */
11
11
  export const LIVE_RESUME_GAP: OkeErrorDefinition = {
12
- code: 1014,
12
+ code: 1210,
13
+ domain: "signal",
13
14
  cause: 'Cursor "{afterId}" missing on "{signal}".',
14
15
  fix: "Reconnect without Last-Event-ID.",
15
16
  };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OKE10151017 — kept off the Store-only `oke()` graph.
2
+ * OKE18101830 — kept off the Store-only `oke()` graph.
3
3
  *
4
4
  * Tenant KV/vault and membership failures. Loaded via computed
5
5
  * `import.meta.require` from {@link throwOke} / {@link lookupOkeError}.
@@ -9,21 +9,24 @@ import type { OkeErrorDefinition } from "./errors.ts";
9
9
 
10
10
  /** Tenant-scoped op ran with no resolved `fx.tenant.id`. */
11
11
  export const TENANT_REQUIRED: OkeErrorDefinition = {
12
- code: 1015,
12
+ code: 1810,
13
+ domain: "mcp_tenancy",
13
14
  cause: "This operation needs a tenant, but none is resolved for this request.",
14
15
  fix: "Call fx.auth.switchTenant(id), send a signed tid claim, or pass the tenant header.",
15
16
  };
16
17
 
17
18
  /** Client-supplied tenant id is not a real membership. */
18
19
  export const TENANT_NOT_MEMBER: OkeErrorDefinition = {
19
- code: 1016,
20
+ code: 1820,
21
+ domain: "mcp_tenancy",
20
22
  cause: 'The caller is not a member of tenant "{tenant}".',
21
23
  fix: "Pick a tenant from fx.auth.listTenants() or add the user as a member.",
22
24
  };
23
25
 
24
26
  /** Tenant role mapped an invented or operator-plane scope. */
25
27
  export const TENANT_UNKNOWN_SCOPE: OkeErrorDefinition = {
26
- code: 1017,
28
+ code: 1830,
29
+ domain: "mcp_tenancy",
27
30
  cause: 'Tenant role scope "{scope}" is not a declared application scope.',
28
31
  fix: "Use a name from this app's Manifest catalog (never console:*).",
29
32
  };
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Registry gate helpers — uniqueness, domain-range correctness, lazy discovery.
3
+ * Used only by `errors.registry.test.ts` (not a public runtime API).
4
+ */
5
+
6
+ import { readdir } from "node:fs/promises";
7
+ import { join } from "node:path";
8
+ import { OKE_ERROR_RANGES, type OkeErrorDefinition, type OkeErrorDomain } from "./errors.ts";
9
+
10
+ const LAZY_FILE_RE = /^errors-.+\.ts$/;
11
+
12
+ /** True when `value` looks like a full {@link OkeErrorDefinition}. */
13
+ export function isOkeErrorDefinition(value: unknown): value is OkeErrorDefinition {
14
+ if (value === null || typeof value !== "object") return false;
15
+ const v = value as Record<string, unknown>;
16
+ return (
17
+ typeof v.code === "number" &&
18
+ Number.isInteger(v.code) &&
19
+ typeof v.domain === "string" &&
20
+ typeof v.cause === "string" &&
21
+ typeof v.fix === "string"
22
+ );
23
+ }
24
+
25
+ /** Collect every `OkeErrorDefinition` export from a module namespace. */
26
+ export function collectDefsFromModule(mod: Record<string, unknown>): readonly OkeErrorDefinition[] {
27
+ const out: OkeErrorDefinition[] = [];
28
+ for (const value of Object.values(mod)) {
29
+ if (isOkeErrorDefinition(value)) out.push(value);
30
+ }
31
+ return out;
32
+ }
33
+
34
+ /**
35
+ * Discover lazy error chunks: every `errors-*.ts` file in `dir`
36
+ * (excludes `errors.ts` itself via the hyphen requirement).
37
+ *
38
+ * @param dir - Absolute directory to scan (typically `import.meta.dir`)
39
+ */
40
+ export async function discoverLazyErrorDefs(dir: string): Promise<{
41
+ readonly files: readonly string[];
42
+ readonly defs: readonly OkeErrorDefinition[];
43
+ }> {
44
+ const names = (await readdir(dir)).filter((name) => LAZY_FILE_RE.test(name)).sort();
45
+ const defs: OkeErrorDefinition[] = [];
46
+ for (const name of names) {
47
+ const mod = (await import(join(dir, name))) as Record<string, unknown>;
48
+ defs.push(...collectDefsFromModule(mod));
49
+ }
50
+ return { files: names, defs };
51
+ }
52
+
53
+ /** Return duplicate numeric codes, or an empty array if all unique. */
54
+ export function findDuplicateCodes(defs: readonly OkeErrorDefinition[]): readonly number[] {
55
+ const seen = new Set<number>();
56
+ const dupes: number[] = [];
57
+ for (const def of defs) {
58
+ if (seen.has(def.code)) dupes.push(def.code);
59
+ else seen.add(def.code);
60
+ }
61
+ return dupes;
62
+ }
63
+
64
+ /** Return defs whose code falls outside `OKE_ERROR_RANGES[domain]`. */
65
+ export function findOutOfRangeDefs(
66
+ defs: readonly OkeErrorDefinition[],
67
+ ): readonly OkeErrorDefinition[] {
68
+ const bad: OkeErrorDefinition[] = [];
69
+ for (const def of defs) {
70
+ const range = OKE_ERROR_RANGES[def.domain as OkeErrorDomain];
71
+ if (!range) {
72
+ bad.push(def);
73
+ continue;
74
+ }
75
+ const [lo, hi] = range;
76
+ if (def.code < lo || def.code > hi) bad.push(def);
77
+ }
78
+ return bad;
79
+ }
80
+
81
+ /** Throw if any code is duplicated. */
82
+ export function assertUniqueCodes(defs: readonly OkeErrorDefinition[]): void {
83
+ const dupes = findDuplicateCodes(defs);
84
+ if (dupes.length > 0) {
85
+ throw new Error(`Duplicate OKE error codes: ${dupes.join(", ")}`);
86
+ }
87
+ }
88
+
89
+ /** Throw if any code is outside its declared domain range. */
90
+ export function assertCodesInDomainRanges(defs: readonly OkeErrorDefinition[]): void {
91
+ const bad = findOutOfRangeDefs(defs);
92
+ if (bad.length > 0) {
93
+ const detail = bad.map((d) => `OKE${d.code} domain=${d.domain}`).join("; ");
94
+ throw new Error(`OKE error codes outside domain range: ${detail}`);
95
+ }
96
+ }
@@ -1,48 +1,147 @@
1
1
  /**
2
- * Error-code registry gate — unique codes, cause/fix/docsUrl shape (§21).
2
+ * Error-code registry gate — unique codes, domain ranges, lazy discovery (§21).
3
3
  *
4
4
  * Docs pages (docs/e/{code}.md) are deferred to a dedicated docs prompt;
5
5
  * this gate enforces registry invariants only.
6
6
  */
7
7
 
8
- import { describe, expect, test } from "bun:test";
9
- import { OKE_ERRORS, OkeError, lookupOkeError, type OkeErrorDefinition } from "./errors.ts";
8
+ import { afterAll, describe, expect, test } from "bun:test";
9
+ import { unlink, writeFile } from "node:fs/promises";
10
+ import { join } from "node:path";
11
+ import {
12
+ OKE_ERROR_RANGES,
13
+ OKE_ERRORS,
14
+ OkeError,
15
+ lookupOkeError,
16
+ type OkeErrorDefinition,
17
+ } from "./errors.ts";
10
18
  import { LIVE_RESUME_GAP } from "./errors-live-resume.ts";
19
+ import { CHANNEL_SCHEMA } from "./errors-channel.ts";
11
20
  import { TENANT_NOT_MEMBER, TENANT_REQUIRED, TENANT_UNKNOWN_SCOPE } from "./errors-tenant.ts";
21
+ import {
22
+ assertCodesInDomainRanges,
23
+ assertUniqueCodes,
24
+ discoverLazyErrorDefs,
25
+ findDuplicateCodes,
26
+ findOutOfRangeDefs,
27
+ } from "./errors.registry-helpers.ts";
12
28
 
13
- const LAZY_DEFS: readonly OkeErrorDefinition[] = [
14
- LIVE_RESUME_GAP,
15
- TENANT_REQUIRED,
16
- TENANT_NOT_MEMBER,
17
- TENANT_UNKNOWN_SCOPE,
18
- ];
29
+ const KERNEL_DIR = import.meta.dir;
30
+ const PROBE_FILE = "errors-__probe__.ts";
31
+ const PROBE_PATH = join(KERNEL_DIR, PROBE_FILE);
19
32
 
20
33
  describe("OKE error-code registry", () => {
21
- test("every code is unique", () => {
22
- const codes = [
23
- ...Object.values(OKE_ERRORS).map((d) => d.code),
24
- ...LAZY_DEFS.map((d) => d.code),
25
- ];
26
- expect(new Set(codes).size).toBe(codes.length);
34
+ test("every code is unique across main + discovered lazy defs", async () => {
35
+ const { defs: lazy } = await discoverLazyErrorDefs(KERNEL_DIR);
36
+ const all = [...Object.values(OKE_ERRORS), ...lazy];
37
+ expect(findDuplicateCodes(all)).toEqual([]);
38
+ assertUniqueCodes(all);
27
39
  });
28
40
 
29
- test("every entry has non-empty cause and fix templates", () => {
41
+ test("every code falls within its declared domain range", async () => {
42
+ const { defs: lazy } = await discoverLazyErrorDefs(KERNEL_DIR);
43
+ const all = [...Object.values(OKE_ERRORS), ...lazy];
44
+ expect(findOutOfRangeDefs(all)).toEqual([]);
45
+ assertCodesInDomainRanges(all);
46
+ });
47
+
48
+ test("OKE_ERROR_RANGES matches the locked domain scheme", () => {
49
+ expect(OKE_ERROR_RANGES.kernel).toEqual([1000, 1099]);
50
+ expect(OKE_ERROR_RANGES.store).toEqual([1100, 1199]);
51
+ expect(OKE_ERROR_RANGES.signal).toEqual([1200, 1299]);
52
+ expect(OKE_ERROR_RANGES.clock).toEqual([1300, 1399]);
53
+ expect(OKE_ERROR_RANGES.gate).toEqual([1400, 1499]);
54
+ expect(OKE_ERROR_RANGES.vault).toEqual([1500, 1599]);
55
+ expect(OKE_ERROR_RANGES.channel).toEqual([1600, 1699]);
56
+ expect(OKE_ERROR_RANGES.ai).toEqual([1700, 1799]);
57
+ expect(OKE_ERROR_RANGES.mcp_tenancy).toEqual([1800, 1899]);
58
+ expect(OKE_ERROR_RANGES.compiler).toEqual([1900, 1999]);
59
+ });
60
+
61
+ test("lazy discovery finds live-resume, channel, and tenant modules without a hand list", async () => {
62
+ const { files, defs } = await discoverLazyErrorDefs(KERNEL_DIR);
63
+ expect(files).toContain("errors-live-resume.ts");
64
+ expect(files).toContain("errors-channel.ts");
65
+ expect(files).toContain("errors-tenant.ts");
66
+ const codes = defs.map((d) => d.code);
67
+ expect(codes).toContain(1210);
68
+ expect(codes).toContain(1605);
69
+ expect(codes).toContain(1810);
70
+ expect(codes).toContain(1820);
71
+ expect(codes).toContain(1830);
72
+ });
73
+
74
+ test("adversarial: out-of-range synthetic def fails range check", () => {
75
+ const bad: OkeErrorDefinition = {
76
+ code: 1999,
77
+ domain: "kernel",
78
+ cause: "probe",
79
+ fix: "probe",
80
+ };
81
+ expect(findOutOfRangeDefs([bad])).toEqual([bad]);
82
+ expect(() => assertCodesInDomainRanges([bad])).toThrow(/outside domain range/);
83
+ });
84
+
85
+ test("adversarial: duplicate synthetic def fails uniqueness check", () => {
86
+ const clone: OkeErrorDefinition = {
87
+ ...OKE_ERRORS.UNDECLARED_READ,
88
+ cause: "dup",
89
+ fix: "dup",
90
+ };
91
+ expect(findDuplicateCodes([OKE_ERRORS.UNDECLARED_READ, clone])).toEqual([1001]);
92
+ expect(() => assertUniqueCodes([OKE_ERRORS.UNDECLARED_READ, clone])).toThrow(/Duplicate/);
93
+ });
94
+
95
+ test("adversarial: filesystem probe is discovered and fails range/uniqueness", async () => {
96
+ await writeFile(
97
+ PROBE_PATH,
98
+ [
99
+ 'import type { OkeErrorDefinition } from "./errors.ts";',
100
+ "export const PROBE_OUT_OF_RANGE: OkeErrorDefinition = {",
101
+ " code: 1999,",
102
+ ' domain: "kernel",',
103
+ ' cause: "adversarial probe",',
104
+ ' fix: "delete this file",',
105
+ "};",
106
+ "",
107
+ ].join("\n"),
108
+ "utf8",
109
+ );
110
+ try {
111
+ const { files, defs } = await discoverLazyErrorDefs(KERNEL_DIR);
112
+ expect(files).toContain(PROBE_FILE);
113
+ const probe = defs.find((d) => d.code === 1999);
114
+ expect(probe).toBeDefined();
115
+ const all = [...Object.values(OKE_ERRORS), ...defs];
116
+ expect(findOutOfRangeDefs(all).some((d) => d.code === 1999)).toBe(true);
117
+ expect(() => assertCodesInDomainRanges(all)).toThrow(/OKE1999/);
118
+ } finally {
119
+ await unlink(PROBE_PATH).catch(() => undefined);
120
+ }
121
+ });
122
+
123
+ afterAll(async () => {
124
+ await unlink(PROBE_PATH).catch(() => undefined);
125
+ });
126
+
127
+ test("every entry has non-empty cause and fix templates", async () => {
128
+ const { defs: lazy } = await discoverLazyErrorDefs(KERNEL_DIR);
30
129
  for (const [key, def] of Object.entries(OKE_ERRORS)) {
31
130
  expect(def.cause.trim().length, `${key}.cause`).toBeGreaterThan(0);
32
131
  expect(def.fix.trim().length, `${key}.fix`).toBeGreaterThan(0);
33
132
  expect(Number.isInteger(def.code), `${key}.code`).toBe(true);
34
133
  expect(def.code, `${key}.code`).toBeGreaterThan(0);
134
+ expect(def.domain, `${key}.domain`).toBeTruthy();
35
135
  }
36
- expect(LIVE_RESUME_GAP.cause.trim().length).toBeGreaterThan(0);
37
- expect(LIVE_RESUME_GAP.fix.trim().length).toBeGreaterThan(0);
38
- for (const def of LAZY_DEFS) {
136
+ for (const def of lazy) {
39
137
  expect(def.cause.trim().length, `${def.code}.cause`).toBeGreaterThan(0);
40
138
  expect(def.fix.trim().length, `${def.code}.fix`).toBeGreaterThan(0);
41
139
  }
42
140
  });
43
141
 
44
- test("OkeError docsUrl matches docs origin /e/{code}", () => {
45
- for (const def of [...Object.values(OKE_ERRORS), ...LAZY_DEFS] as OkeErrorDefinition[]) {
142
+ test("OkeError docsUrl matches docs origin /e/{code}", async () => {
143
+ const { defs: lazy } = await discoverLazyErrorDefs(KERNEL_DIR);
144
+ for (const def of [...Object.values(OKE_ERRORS), ...lazy] as OkeErrorDefinition[]) {
46
145
  const err = new OkeError(def);
47
146
  expect(err.docsUrl).toBe(`https://oke.omqkhafi.dev/e/${def.code}`);
48
147
  expect(err.message).toContain(err.docsUrl);
@@ -52,12 +151,27 @@ describe("OKE error-code registry", () => {
52
151
  });
53
152
 
54
153
  test("lookupOkeError finds the lazy LIVE_RESUME_GAP entry", () => {
55
- expect(lookupOkeError(1014)).toEqual(LIVE_RESUME_GAP);
154
+ expect(lookupOkeError(1210)).toEqual(LIVE_RESUME_GAP);
155
+ });
156
+
157
+ test("lookupOkeError finds the lazy CHANNEL_SCHEMA entry", () => {
158
+ expect(lookupOkeError(1605)).toEqual(CHANNEL_SCHEMA);
56
159
  });
57
160
 
58
161
  test("lookupOkeError finds lazy tenant entries", () => {
59
- expect(lookupOkeError(1015)).toEqual(TENANT_REQUIRED);
60
- expect(lookupOkeError(1016)).toEqual(TENANT_NOT_MEMBER);
61
- expect(lookupOkeError(1017)).toEqual(TENANT_UNKNOWN_SCOPE);
162
+ expect(lookupOkeError(1810)).toEqual(TENANT_REQUIRED);
163
+ expect(lookupOkeError(1820)).toEqual(TENANT_NOT_MEMBER);
164
+ expect(lookupOkeError(1830)).toEqual(TENANT_UNKNOWN_SCOPE);
165
+ });
166
+
167
+ test("lookupOkeError finds UNDECLARED_EMBED at 1009 (not tenant)", () => {
168
+ expect(lookupOkeError(1009)).toEqual(OKE_ERRORS.UNDECLARED_EMBED);
169
+ expect(OKE_ERRORS.UNDECLARED_EMBED.code).toBe(1009);
170
+ expect(TENANT_REQUIRED.code).toBe(1810);
171
+ });
172
+
173
+ test("NO_EFFECTS_DECLARED owns 1020 after renumber (was UNDECLARED_EMBED)", () => {
174
+ expect(OKE_ERRORS.NO_EFFECTS_DECLARED.code).toBe(1020);
175
+ expect(OKE_ERRORS.UNDECLARED_EMBED.code).toBe(1009);
62
176
  });
63
177
  });
@@ -30,13 +30,46 @@ function loadFailureMessage(): typeof import("../i18n/failure-message.ts") {
30
30
  }
31
31
  }
32
32
 
33
- /** Numeric OKE error code (permanent once published). */
33
+ /** Numeric OKE error code (stable after the domain-range renumber). */
34
34
  export type OkeErrorCode = number;
35
35
 
36
+ /**
37
+ * Error domain — each maps to a fixed numeric range in {@link OKE_ERROR_RANGES}.
38
+ * Kernel covers Flow/Trigger/Gate-posture (boot structural). Gate sessions/OAuth
39
+ * live in `gate`; MCP + tenancy share `mcp_tenancy`.
40
+ */
41
+ export type OkeErrorDomain =
42
+ | "kernel"
43
+ | "store"
44
+ | "signal"
45
+ | "clock"
46
+ | "gate"
47
+ | "vault"
48
+ | "channel"
49
+ | "ai"
50
+ | "mcp_tenancy"
51
+ | "compiler";
52
+
53
+ /** Inclusive `[lo, hi]` band for each {@link OkeErrorDomain}. */
54
+ export const OKE_ERROR_RANGES = {
55
+ kernel: [1000, 1099],
56
+ store: [1100, 1199],
57
+ signal: [1200, 1299],
58
+ clock: [1300, 1399],
59
+ gate: [1400, 1499],
60
+ vault: [1500, 1599],
61
+ channel: [1600, 1699],
62
+ ai: [1700, 1799],
63
+ mcp_tenancy: [1800, 1899],
64
+ compiler: [1900, 1999],
65
+ } as const satisfies Record<OkeErrorDomain, readonly [number, number]>;
66
+
36
67
  /** One registry entry — cause/fix may include `{name}` placeholders. */
37
68
  export interface OkeErrorDefinition {
38
- /** Permanent numeric code. */
69
+ /** Permanent numeric code (must fall in {@link OKE_ERROR_RANGES} for `domain`). */
39
70
  readonly code: OkeErrorCode;
71
+ /** Domain that owns this code's numeric range. */
72
+ readonly domain: OkeErrorDomain;
40
73
  /** One-line cause template. */
41
74
  readonly cause: string;
42
75
  /** Suggested fix template. */
@@ -112,65 +145,97 @@ export interface FailOptions {
112
145
  }
113
146
 
114
147
  /**
115
- * Permanent error registry. Codes never change meaning once published.
148
+ * Permanent error registry. Codes are stable within their domain range after
149
+ * the domain-range renumber; each entry declares `domain` for range guards.
116
150
  *
117
- * Ranges (convention):
118
- * - `1000–1099` — capability / undeclared-effect violations
119
- * - `1042` — reserved by unified-theory §21 example (orphan emit)
151
+ * Ranges:
152
+ * - `1000–1099` — Kernel (Flow / Trigger / Gate-posture)
153
+ * - `1100–1199` — Store
154
+ * - `1200–1299` — Signal
155
+ * - `1300–1399` — Clock
156
+ * - `1400–1499` — Gate (sessions / OAuth / API keys)
157
+ * - `1500–1599` — Vault
158
+ * - `1600–1699` — Channel
159
+ * - `1700–1799` — AI
160
+ * - `1800–1899` — MCP + Tenancy
161
+ * - `1900–1999` — Compiler / Manifest
120
162
  */
121
163
  export const OKE_ERRORS = {
122
164
  /** Flow reads a store resource not listed in `effects.reads`. */
123
165
  UNDECLARED_READ: {
124
166
  code: 1001,
167
+ domain: "kernel",
125
168
  cause: 'Flow "{flow}" reads "{resource}" without declaring it.',
126
169
  fix: 'Add "{resource}" to this flow\'s effects.reads.',
127
170
  },
128
171
  /** Flow writes a store resource not listed in `effects.writes`. */
129
172
  UNDECLARED_WRITE: {
130
173
  code: 1002,
174
+ domain: "kernel",
131
175
  cause: 'Flow "{flow}" writes "{resource}" without declaring it.',
132
176
  fix: 'Add "{resource}" to this flow\'s effects.writes.',
133
177
  },
134
178
  /** Flow emits a signal not listed in `effects.emits`. */
135
179
  UNDECLARED_EMIT: {
136
180
  code: 1003,
181
+ domain: "kernel",
137
182
  cause: 'Flow "{flow}" emits "{resource}" without declaring it.',
138
183
  fix: 'Add "{resource}" to this flow\'s effects.emits.',
139
184
  },
140
185
  /** Flow sends a channel template not listed in `effects.sends`. */
141
186
  UNDECLARED_SEND: {
142
187
  code: 1004,
188
+ domain: "kernel",
143
189
  cause: 'Flow "{flow}" sends "{resource}" without declaring it.',
144
190
  fix: 'Add "{resource}" to this flow\'s effects.sends.',
145
191
  },
146
192
  /** Flow asks a prompt not listed in `effects.asks`. */
147
193
  UNDECLARED_ASK: {
148
194
  code: 1005,
195
+ domain: "kernel",
149
196
  cause: 'Flow "{flow}" asks "{resource}" without declaring it.',
150
197
  fix: 'Add "{resource}" to this flow\'s effects.asks.',
151
198
  },
152
199
  /** Flow reads a secret not listed in `effects.secrets`. */
153
200
  UNDECLARED_SECRET: {
154
201
  code: 1006,
202
+ domain: "kernel",
155
203
  cause: 'Flow "{flow}" reads secret "{resource}" without declaring it.',
156
204
  fix: 'Add "{resource}" to this flow\'s effects.secrets.',
157
205
  },
158
206
  /** Flow calls another flow not listed in `effects.calls`. */
159
207
  UNDECLARED_CALL: {
160
208
  code: 1007,
209
+ domain: "kernel",
161
210
  cause: 'Flow "{flow}" calls "{resource}" without declaring it.',
162
211
  fix: 'Add "{resource}" to this flow\'s effects.calls.',
163
212
  },
213
+ /** Flow fetches a host not listed in `effects.fetches`. */
214
+ UNDECLARED_FETCH: {
215
+ code: 1008,
216
+ domain: "kernel",
217
+ cause: 'Flow "{flow}" fetches "{resource}" without declaring it.',
218
+ fix: 'Add "{resource}" to this flow\'s effects.fetches.',
219
+ },
220
+ /** Flow embeds via a model not listed in `effects.embeds`. */
221
+ UNDECLARED_EMBED: {
222
+ code: 1009,
223
+ domain: "kernel",
224
+ cause: 'Flow "{flow}" embeds with "{resource}" without declaring it.',
225
+ fix: 'Add "{resource}" to this flow\'s effects.embeds.',
226
+ },
164
227
  /**
165
228
  * Flow has no declared `effects` and no Manifest-derived effects were
166
229
  * available to stamp at boot (dev+compose / prod — never a silent open token).
167
230
  */
168
231
  NO_EFFECTS_DECLARED: {
169
- code: 1008,
232
+ code: 1020,
233
+ domain: "kernel",
170
234
  cause: 'Flow "{flow}" has no declared effects and no Manifest to derive them from.',
171
235
  fix:
172
236
  "Add explicit `effects` to this flow, or boot with a Manifest (`oke build`) / " +
173
- "`rootDir` so effects can be derived. dev+compose/prod refuse an open capability token.",
237
+ "`rootDir` so effects can be derived. If extract failed, ensure `oxc-parser` is " +
238
+ "installed (okengine dependency). dev+compose/prod refuse an open capability token.",
174
239
  },
175
240
  /**
176
241
  * A `src/flows/<unit>` folder exists on disk but no adopted flow carries
@@ -179,7 +244,8 @@ export const OKE_ERRORS = {
179
244
  * route table in a deploy-shaped environment.
180
245
  */
181
246
  ADOPT_BARREL_STALE: {
182
- code: 1009,
247
+ code: 1030,
248
+ domain: "kernel",
183
249
  cause: "src/flows/{unit} exists on disk but adopted no flows — the .adopt() barrel is stale.",
184
250
  fix: "Run `oke dev` or `oke build` to regenerate `src/flows/generated.ts`.",
185
251
  },
@@ -187,7 +253,8 @@ export const OKE_ERRORS = {
187
253
  * `http.get()` was never stamped from the file tree — refuse a silent `/`.
188
254
  */
189
255
  HTTP_PATH_UNRESOLVED: {
190
- code: 1010,
256
+ code: 1040,
257
+ domain: "kernel",
191
258
  cause: 'Flow "{flow}" bound {method} with no path — the file-tree stamp never ran.',
192
259
  fix: 'Put the file under `src/flows/<unit>/` and import `@/flows/generated`, or pass an explicit path to `http.{method}("/…")`.',
193
260
  },
@@ -195,7 +262,8 @@ export const OKE_ERRORS = {
195
262
  * Two HTTP bindings share method + path — last-add-wins is the opposite of this DX.
196
263
  */
197
264
  HTTP_ROUTE_DUPLICATE: {
198
- code: 1011,
265
+ code: 1041,
266
+ domain: "kernel",
199
267
  cause: '{method} {path} is bound twice (flow "{flow}").',
200
268
  fix: "Give each HTTP flow a unique method + path.",
201
269
  },
@@ -203,7 +271,8 @@ export const OKE_ERRORS = {
203
271
  * Adopted HTTP flow still has no name (`flow({ do })` outside a unit).
204
272
  */
205
273
  HTTP_FLOW_UNNAMED: {
206
- code: 1012,
274
+ code: 1045,
275
+ domain: "kernel",
207
276
  cause: "An HTTP flow on {method} {path} has no name.",
208
277
  fix: 'Use `flow("unit.export", {…})` or export it from a `src/flows/<unit>/` file so the tree can stamp `unit.export`.',
209
278
  },
@@ -211,7 +280,8 @@ export const OKE_ERRORS = {
211
280
  * Two live HTTP exposures of the same signal share gates + match shape.
212
281
  */
213
282
  LIVE_EXPOSURE_DUPLICATE: {
214
- code: 1013,
283
+ code: 1050,
284
+ domain: "kernel",
215
285
  cause:
216
286
  'Live signal "{signal}" is exposed twice with the same gates ({gates}) and match ({match}).',
217
287
  fix: "Use a different gate or path-param filter, or drop the extra route.",
@@ -220,7 +290,8 @@ export const OKE_ERRORS = {
220
290
  * Two MCP tool bindings share the same exposed tool name.
221
291
  */
222
292
  MCP_TOOL_DUPLICATE: {
223
- code: 1018,
293
+ code: 1060,
294
+ domain: "kernel",
224
295
  cause: 'MCP tool "{tool}" is bound twice (flow "{flow}").',
225
296
  fix: "Give each MCP tool exposure a unique tool name.",
226
297
  },
@@ -229,22 +300,24 @@ export const OKE_ERRORS = {
229
300
  * Thrown at emit when `optional` is false and nobody is subscribed.
230
301
  */
231
302
  ORPHAN_EMIT: {
232
- code: 1042,
303
+ code: 1240,
304
+ domain: "signal",
233
305
  cause: 'Flow "{flow}" emits signal "{resource}" with no subscriber.',
234
306
  fix: "Add `on({resource}, …)` or mark the signal `{ optional: true }`.",
235
307
  },
236
308
  /** Emit payload failed the signal's declared Standard Schema. */
237
309
  SIGNAL_SCHEMA: {
238
- code: 1043,
310
+ code: 1250,
311
+ domain: "signal",
239
312
  cause: '"{resource}": {detail}',
240
313
  fix: "Fix schema payload.",
241
314
  },
242
315
  /**
243
316
  * Domain table/column missing under docker/prod (migrations not applied).
244
- * Store/DDL band starts at 1100.
245
317
  */
246
318
  DOMAIN_SCHEMA_MISSING: {
247
- code: 1101,
319
+ code: 1110,
320
+ domain: "store",
248
321
  cause: "domain table not found — migrations have not been applied.",
249
322
  fix: "run `oke db migrate` against this environment.",
250
323
  },
@@ -260,7 +333,7 @@ type TenantErrorChunk = {
260
333
  };
261
334
 
262
335
  /**
263
- * Load OKE10151017. Computed stem so Bun.build cannot inline the chunk.
336
+ * Load OKE18101830. Computed stem so Bun.build cannot inline the chunk.
264
337
  */
265
338
  function loadTenantErrors(): TenantErrorChunk {
266
339
  return lazyRequire(import.meta.dir, ["errors", "tenant"].join("-"));
@@ -289,15 +362,21 @@ export function throwOke(
289
362
  * @param code - Permanent numeric code
290
363
  */
291
364
  export function lookupOkeError(code: OkeErrorCode): OkeErrorDefinition | undefined {
292
- if (code === 1014) {
365
+ if (code === 1210) {
293
366
  return lazyRequire<typeof import("./errors-live-resume.ts")>(
294
367
  import.meta.dir,
295
368
  ["errors", "live", "resume"].join("-"),
296
369
  ).LIVE_RESUME_GAP;
297
370
  }
298
- if (code === 1015) return loadTenantErrors().TENANT_REQUIRED;
299
- if (code === 1016) return loadTenantErrors().TENANT_NOT_MEMBER;
300
- if (code === 1017) return loadTenantErrors().TENANT_UNKNOWN_SCOPE;
371
+ if (code === 1605) {
372
+ return lazyRequire<typeof import("./errors-channel.ts")>(
373
+ import.meta.dir,
374
+ ["errors", "channel"].join("-"),
375
+ ).CHANNEL_SCHEMA;
376
+ }
377
+ if (code === 1810) return loadTenantErrors().TENANT_REQUIRED;
378
+ if (code === 1820) return loadTenantErrors().TENANT_NOT_MEMBER;
379
+ if (code === 1830) return loadTenantErrors().TENANT_UNKNOWN_SCOPE;
301
380
  for (const def of Object.values(OKE_ERRORS)) {
302
381
  if (def.code === code) return def;
303
382
  }