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
@@ -12,7 +12,7 @@ import { join } from "node:path";
12
12
  export interface DocsPage {
13
13
  /** URL slug under `/docs` (`""` for the index page). */
14
14
  readonly slug: string;
15
- /** Content-relative path (e.g. `get-started/introduction.mdx`). */
15
+ /** Content-relative path (e.g. `understand/the-problem.mdx`). */
16
16
  readonly path: string;
17
17
  /** Frontmatter title. */
18
18
  readonly title: string;
@@ -39,7 +39,7 @@ export interface DocsIndex {
39
39
  /**
40
40
  * Look up a page by slug or content path.
41
41
  *
42
- * @param id - Slug (`get-started/introduction`) or path (`…/introduction.mdx`)
42
+ * @param id - Slug (`understand/the-problem`) or path (`…/the-problem.mdx`)
43
43
  */
44
44
  readonly get: (id: string) => DocsPage | null;
45
45
  /**
@@ -203,7 +203,7 @@ export async function loadDocsIndex(
203
203
  }
204
204
 
205
205
  /**
206
- * @param relativePath - e.g. `get-started/introduction.mdx`
206
+ * @param relativePath - e.g. `understand/the-problem.mdx`
207
207
  */
208
208
  function pathToSlug(relativePath: string): string {
209
209
  const noExt = relativePath.replace(/\.mdx?$/i, "");
@@ -112,7 +112,7 @@ describe("docs MCP tools", () => {
112
112
 
113
113
  test("oke.docs.get returns body byte-identical to on-disk source", async () => {
114
114
  const mcp = await createDocsMcpServer({ contentDir: CONTENT });
115
- const slug = "get-started/introduction";
115
+ const slug = "understand/the-problem";
116
116
  const res = await mcpPost(mcp.fetch, {
117
117
  jsonrpc: "2.0",
118
118
  id: 2,
@@ -133,7 +133,7 @@ describe("docs MCP tools", () => {
133
133
  const content = envelope.content as { body: string; slug: string };
134
134
  expect(content.slug).toBe(slug);
135
135
 
136
- const raw = await Bun.file(join(CONTENT, "get-started", "introduction.mdx")).text();
136
+ const raw = await Bun.file(join(CONTENT, "understand", "the-problem.mdx")).text();
137
137
  expect(content.body).toBe(stripYamlFrontmatter(raw));
138
138
  });
139
139
 
@@ -52,7 +52,7 @@ export const DOCS_MCP_TOOLS: readonly DocsToolDescriptor[] = [
52
52
  properties: {
53
53
  slug: {
54
54
  type: "string",
55
- description: "Page slug (e.g. get-started/introduction) or path (…/introduction.mdx)",
55
+ description: "Page slug (e.g. understand/the-problem) or path (…/the-problem.mdx)",
56
56
  },
57
57
  },
58
58
  required: ["slug"],
package/src/okid.test.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  OKID_DEFAULT_LENGTH,
9
9
  OKID_LOOKALIKE_CHARS,
10
10
  OKID_MAX_LENGTH,
11
+ OKID_MAX_PREFIX_LENGTH,
11
12
  OKID_MIN_LENGTH,
12
13
  OKID_SORTABLE_ALPHABET,
13
14
  OKID_SORTABLE_MIN_LENGTH,
@@ -304,6 +305,61 @@ describe("okid sortable mode", () => {
304
305
  });
305
306
  });
306
307
 
308
+ describe("okid semantic prefix", () => {
309
+ test("prepends the label and keeps body length", () => {
310
+ const id = okid({ prefix: "usr_" });
311
+ expect(id.startsWith("usr_")).toBe(true);
312
+ expect(id.length).toBe(4 + OKID_DEFAULT_LENGTH);
313
+ expect(id.slice(4).length).toBe(OKID_DEFAULT_LENGTH);
314
+ });
315
+
316
+ test("honors length as the body size, not the total", () => {
317
+ const id = okid({ prefix: "evt_", length: 16 });
318
+ expect(id.startsWith("evt_")).toBe(true);
319
+ expect(id.length).toBe(4 + 16);
320
+ });
321
+
322
+ test("combines with sortable: prefix + timestamp + random", () => {
323
+ const realNow = Date.now;
324
+ Date.now = () => 1_700_000_000_000;
325
+ try {
326
+ const a = okid({ prefix: "evt_", sortable: true, length: 16 });
327
+ const b = okid({ prefix: "evt_", sortable: true, length: 16 });
328
+ expect(a.startsWith("evt_")).toBe(true);
329
+ expect(a.length).toBe(4 + 16);
330
+ expect(a.slice(4, 12)).toBe(b.slice(4, 12));
331
+ expect(a.slice(12)).not.toBe(b.slice(12));
332
+ } finally {
333
+ Date.now = realNow;
334
+ }
335
+ });
336
+
337
+ test("empty / omitted prefix is a no-op", () => {
338
+ expect(okid({ prefix: "" }).length).toBe(OKID_DEFAULT_LENGTH);
339
+ expect(okid({}).length).toBe(OKID_DEFAULT_LENGTH);
340
+ });
341
+
342
+ test("rejects characters outside OKID_ALPHABET", () => {
343
+ expect(() => okid({ prefix: "usr:" })).toThrow(RangeError);
344
+ expect(() => okid({ prefix: "usr " })).toThrow(RangeError);
345
+ expect(() => okid({ prefix: "usr." })).toThrow(RangeError);
346
+ });
347
+
348
+ test("rejects oversized prefixes", () => {
349
+ expect(() => okid({ prefix: "a".repeat(OKID_MAX_PREFIX_LENGTH + 1) })).toThrow(RangeError);
350
+ expect(okid({ prefix: "a".repeat(OKID_MAX_PREFIX_LENGTH) }).length).toBe(
351
+ OKID_MAX_PREFIX_LENGTH + OKID_DEFAULT_LENGTH,
352
+ );
353
+ });
354
+
355
+ test("full id stays URL-safe", () => {
356
+ for (let i = 0; i < 200; i++) {
357
+ const id = okid({ prefix: "inst-" });
358
+ expect(encodeURIComponent(id)).toBe(id);
359
+ }
360
+ });
361
+ });
362
+
307
363
  describe("okid entropy math", () => {
308
364
  const bitsPerChar = Math.log2;
309
365
 
package/src/okid.ts CHANGED
@@ -16,8 +16,11 @@
16
16
  * 48-bit epoch-millisecond timestamp encoded in exactly 8 chars, leaving
17
17
  * `length − 8` random chars (78 bits at the default length). Lexicographic
18
18
  * order equals time order across milliseconds; ids minted within the same
19
- * millisecond tie on the prefix and carry no intra-ms ordering. Clock skew
19
+ * millisecond tie on the timestamp and carry no intra-ms ordering. Clock skew
20
20
  * distorts ordering but can never cause duplicates (the tail stays random).
21
+ * - **Semantic prefix** — `okid({ prefix: "usr_" })` prepends a fixed label
22
+ * from the OKID alphabet. `length` is always the generated body (random or
23
+ * sortable); the returned string is `prefix + body`.
21
24
  * - **Alphabet control** — group toggles (`numbers`, `lowercase`,
22
25
  * `uppercase`, `symbols`) and `lookAlikes` shrink the alphabet for
23
26
  * human-transcribed codes. Non-power-of-two alphabets use rejection
@@ -38,7 +41,8 @@
38
41
  *
39
42
  * const userId = okid(); // 21 chars, 126 bits
40
43
  * const requestId = okid(16); // explicit length
41
- * const eventKey = okid({ sortable: true }); // time-prefixed
44
+ * const eventKey = okid({ sortable: true }); // time-prefixed body
45
+ * const typedId = okid({ prefix: "usr_" }); // usr_ + 21-char body
42
46
  * const inviteCode = okid({
43
47
  * lookAlikes: false,
44
48
  * uppercase: false,
@@ -89,14 +93,27 @@ export const OKID_MAX_LENGTH = 128;
89
93
  /** Sortable ids need ≥ 16: 8 timestamp chars alone would leave no randomness. */
90
94
  export const OKID_SORTABLE_MIN_LENGTH = 16;
91
95
 
96
+ /** Longest permitted semantic {@link OkidOptions.prefix}. */
97
+ export const OKID_MAX_PREFIX_LENGTH = 32;
98
+
92
99
  /** Options for {@link okid}. All alphabet toggles default to included. */
93
100
  export interface OkidOptions {
94
- /** Total id length (default {@link OKID_DEFAULT_LENGTH}). */
101
+ /**
102
+ * Generated body length (default {@link OKID_DEFAULT_LENGTH}). Does not
103
+ * include {@link prefix} — the returned string is `prefix + body`.
104
+ */
95
105
  readonly length?: number;
96
106
  /**
97
- * Prefix a 48-bit epoch-ms timestamp (exactly 8 chars) so lexicographic
98
- * order tracks creation time across milliseconds. Alphabet toggles are
99
- * ignored under this mode see {@link OKID_SORTABLE_ALPHABET}.
107
+ * Fixed semantic label prepended to the body (e.g. `"usr_"`, `"evt_"`).
108
+ * Characters must belong to {@link OKID_ALPHABET}; max
109
+ * {@link OKID_MAX_PREFIX_LENGTH}. Empty / omitted means no label.
110
+ */
111
+ readonly prefix?: string;
112
+ /**
113
+ * Prefix the body with a 48-bit epoch-ms timestamp (exactly 8 chars) so
114
+ * lexicographic order tracks creation time across milliseconds. Alphabet
115
+ * toggles are ignored under this mode — see {@link OKID_SORTABLE_ALPHABET}.
116
+ * Combines with {@link prefix}: `prefix + timestamp + random`.
100
117
  */
101
118
  readonly sortable?: boolean;
102
119
  /** Include `a-z` (default true). */
@@ -204,6 +221,26 @@ function assertLength(length: number, min: number, label: string): void {
204
221
  }
205
222
  }
206
223
 
224
+ /**
225
+ * Assert a semantic prefix is within bounds and stays on the URL-safe alphabet.
226
+ *
227
+ * @param prefix - Caller-supplied label
228
+ */
229
+ function assertPrefix(prefix: string): void {
230
+ if (prefix.length > OKID_MAX_PREFIX_LENGTH) {
231
+ throw new RangeError(
232
+ `okid: prefix length ${prefix.length} exceeds max ${OKID_MAX_PREFIX_LENGTH}`,
233
+ );
234
+ }
235
+ for (const char of prefix) {
236
+ if (!OKID_ALPHABET.includes(char)) {
237
+ throw new RangeError(
238
+ `okid: prefix contains invalid character ${JSON.stringify(char)} — use characters from OKID_ALPHABET`,
239
+ );
240
+ }
241
+ }
242
+ }
243
+
207
244
  /**
208
245
  * Generate an OKE-native id.
209
246
  *
@@ -211,9 +248,10 @@ function assertLength(length: number, min: number, label: string): void {
211
248
  * the hot path and skips all option resolution beyond validation.
212
249
  *
213
250
  * @param options - Length in chars, or {@link OkidOptions}
214
- * @returns A URL-safe id of exactly the requested length
251
+ * @returns A URL-safe id: the generated body, optionally preceded by
252
+ * {@link OkidOptions.prefix}
215
253
  * @throws RangeError on invalid input (non-integer, out-of-range length,
216
- * empty alphabet)
254
+ * invalid prefix, empty alphabet)
217
255
  */
218
256
  export function okid(options: number | OkidOptions = OKID_DEFAULT_LENGTH): string {
219
257
  if (typeof options === "number") {
@@ -223,6 +261,7 @@ export function okid(options: number | OkidOptions = OKID_DEFAULT_LENGTH): strin
223
261
 
224
262
  const {
225
263
  length = OKID_DEFAULT_LENGTH,
264
+ prefix = "",
226
265
  sortable = false,
227
266
  lowercase = true,
228
267
  uppercase = true,
@@ -231,15 +270,20 @@ export function okid(options: number | OkidOptions = OKID_DEFAULT_LENGTH): strin
231
270
  lookAlikes = true,
232
271
  } = options;
233
272
 
273
+ if (prefix) assertPrefix(prefix);
274
+
275
+ let body: string;
234
276
  if (sortable) {
235
277
  assertLength(length, OKID_SORTABLE_MIN_LENGTH, "length");
236
278
  // Time ordering requires lexicographic encoding, which requires the full
237
279
  // codepoint-ordered alphabet — partial subsets cannot preserve both the
238
280
  // caller's charset choice AND cross-ms ordering, so toggles are ignored.
239
281
  const alphabet = resolveAlphabet(true, true, true, true, true);
240
- return encodeTimestamp(Date.now()) + encode(alphabet, length - 8);
282
+ body = encodeTimestamp(Date.now()) + encode(alphabet, length - 8);
283
+ } else {
284
+ assertLength(length, OKID_MIN_LENGTH, "length");
285
+ body = encode(resolveAlphabet(numbers, lowercase, uppercase, symbols, lookAlikes), length);
241
286
  }
242
287
 
243
- assertLength(length, OKID_MIN_LENGTH, "length");
244
- return encode(resolveAlphabet(numbers, lowercase, uppercase, symbols, lookAlikes), length);
288
+ return prefix ? prefix + body : body;
245
289
  }
@@ -16,6 +16,7 @@ import {
16
16
  resolveSharedIdentities,
17
17
  type AuthMethodOptions,
18
18
  } from "./auth/shared.ts";
19
+ import { okid } from "../okid.ts";
19
20
 
20
21
  /** Options for {@link anonymous}. */
21
22
  export interface AnonymousPluginOptions extends AuthMethodOptions {
@@ -34,17 +35,20 @@ export function anonymous(opts: AnonymousPluginOptions = {}): PluginDef {
34
35
  const runtime = createMethodRuntime(opts);
35
36
  const identities = resolveSharedIdentities(opts);
36
37
 
37
- const signIn = flow("auth.signInAnonymous", {
38
- plane: "user",
38
+ const signInContract = {
39
39
  out: SessionTokensOut,
40
40
  errors: { AuthFailed, AuthRateLimited },
41
+ };
42
+
43
+ const signIn = flow("auth.signInAnonymous", {
44
+ plane: "user",
41
45
  do: async () => {
42
46
  let userId: string;
43
47
  try {
44
48
  userId = (
45
49
  await linkOrProvision(identities, {
46
50
  provider: "anonymous",
47
- providerAccountId: crypto.randomUUID(),
51
+ providerAccountId: okid(),
48
52
  now: runtime.now,
49
53
  })
50
54
  ).user.id;
@@ -70,5 +74,5 @@ export function anonymous(opts: AnonymousPluginOptions = {}): PluginDef {
70
74
 
71
75
  return plugin("anonymous", { version: "0.0.1", config: { method: "anonymous" } })
72
76
  .needs("auth")
73
- .binding(bindPublicAuth("/sign-in/anonymous", signIn, "signIn"));
77
+ .binding(bindPublicAuth("/sign-in/anonymous", signIn, "signIn", signInContract));
74
78
  }
@@ -9,6 +9,7 @@ import { getActiveGateAuthContext } from "../../auth/method-context.ts";
9
9
  import { createSessionStore, type SessionCrypto, type SessionStore } from "../../auth/sessions.ts";
10
10
  import { gate } from "../../elements/gate.ts";
11
11
  import type { GateDecl } from "../../elements/gate/declare.ts";
12
+ import type { BoundaryContract } from "../../kernel/boundary-contract.ts";
12
13
  import { fail } from "../../kernel/errors.ts";
13
14
  import { flow, type AnyFlowDef } from "../../kernel/flow.ts";
14
15
  import type { Binding } from "../../kernel/on.ts";
@@ -21,6 +22,9 @@ export const AuthFailed = z.object({
21
22
  reasons: z.array(z.string()).optional(),
22
23
  });
23
24
  export const AuthRateLimited = z.object({ reason: z.string() });
25
+ export const Forbidden = z.object({
26
+ reason: z.string().optional(),
27
+ });
24
28
 
25
29
  export const SessionTokensOut = z.object({
26
30
  accessToken: z.string(),
@@ -29,6 +33,18 @@ export const SessionTokensOut = z.object({
29
33
  userId: z.string().optional(),
30
34
  });
31
35
 
36
+ /** Sign-in may return tokens or a locked 2FA challenge. */
37
+ export const SignInOut = z.union([
38
+ SessionTokensOut,
39
+ z.object({
40
+ twoFactorRequired: z.literal(true),
41
+ challengeId: z.string(),
42
+ method: z.enum(["totp", "email_otp"]),
43
+ userId: z.string(),
44
+ devOtp: z.string().optional(),
45
+ }),
46
+ ]);
47
+
32
48
  /** Common options for auth method plugins (session issue). */
33
49
  export interface AuthMethodOptions {
34
50
  /** HMAC secret; falls back to `OKE_AUTH_SECRET`, then a dev default. */
@@ -120,9 +136,11 @@ export function bindPublicAuth(
120
136
  path: string,
121
137
  flowDef: AnyFlowDef,
122
138
  kind: keyof typeof AUTH_RATE_PRESETS = "otp",
139
+ contract?: BoundaryContract,
123
140
  ): Binding {
124
141
  const gates = authPublicGates(kind);
125
- let trigger = http.post(`/auth${path}`);
142
+ let trigger =
143
+ contract !== undefined ? http.post(`/auth${path}`, contract) : http.post(`/auth${path}`);
126
144
  for (const g of gates) trigger = trigger.gate(g);
127
145
  return bindAuthHttp(trigger, flowDef);
128
146
  }
@@ -133,8 +151,14 @@ export function bindPublicAuth(
133
151
  * @param path - Path under `/auth`
134
152
  * @param flowDef - Flow
135
153
  */
136
- export function bindSessionAuth(path: string, flowDef: AnyFlowDef): Binding {
137
- return bindAuthHttp(http.post(`/auth${path}`).gate(AUTH_SESSION_GATE), flowDef);
154
+ export function bindSessionAuth(
155
+ path: string,
156
+ flowDef: AnyFlowDef,
157
+ contract?: BoundaryContract,
158
+ ): Binding {
159
+ const trigger =
160
+ contract !== undefined ? http.post(`/auth${path}`, contract) : http.post(`/auth${path}`);
161
+ return bindAuthHttp(trigger.gate(AUTH_SESSION_GATE), flowDef);
138
162
  }
139
163
 
140
164
  export { AUTH_SESSION_GATE, fail, flow, http, z };
@@ -18,7 +18,7 @@ import { otp } from "./otp.ts";
18
18
  import { magicLink } from "./magic-link.ts";
19
19
 
20
20
  const SECRET = "test-secret-at-least-16";
21
- const MAILPIT_IMAGE = "axllent/mailpit:v1.30.7";
21
+ const MAILPIT_IMAGE = "axllent/mailpit:v1.31.1";
22
22
 
23
23
  afterEach(() => {
24
24
  resetBindings();