0.15

Every published okengine release, newest first.

all series ยท 0.16 ยท 0.14

v0.15.2

๐Ÿ› Fixed

  • oxfmt ignores generated emit (oke-client.d.ts, schema.drizzle.ts, flows/generated.ts) so oke dev no longer fails Format on CI.

v0.15.1

๐Ÿ› Fixed

  • Compiler 200-flow extract budget test no longer dies on Bun's 5s default timeout on GitHub Actions. CI still asserts under 4s after warmup.

v0.15.0

โœจ Added

Console โ€” Store

  • One Gate picker on SQL, browse, and grid edit. Policy sheet Code tab shows store.schema.policy plus pgPolicy. Policy grid marks declared vs live. Schema cards show Manifest RLS.
  • Resource header shows an RLS chip before PII for SQL tables (on/off from live relrowsecurity, same shield language as the tree). Enabled tables with policies show **N RLS**.
  • Owner policy templates open a Column select of the table fields (preselect creator_email / owner_email when present) with PK / FK marks, and rewrite USING / WITH CHECK. Create stays blocked until a column is picked.
  • Two-finger click (right-click) a Store row opens the row sheet. Empty grid opens Create policy / index / function / trigger or Insert.
  • Row sheet Edit / Save patches editable columns (policy roles, USING, WITH CHECK, command, and table / KV cells).
  • Create policy: form X closes the sheet; templates X only closes the templates dock (the shared X no longer sits on templates).
  • Create policy SQL / Code dock has the same drag handle as Query / explorer splits so the preview can be resized.

Runtime

  • store.schema.policy.gate/owner/scope and store.schema.rls(). oke db push installs oke.* helpers before drizzle-kit.
  • File-tree HTTP routes: http.get() plus nameless flow({ do }) stamp path and unit.export from flows/<unit>/. oke() drains generated.ts into $routes. Unresolved path is OKE1010; duplicate method+path is OKE1011; unnamed HTTP is OKE1012.
  • Tree generate fails when two files declare the same method + path (list.ts + route.ts both http.get() โ†’ GET /notes). Different methods on one path stay allowed. Boot still refuses leftovers (OKE1011).

๐Ÿ’ฅ Breaking Changes

Console โ€” Store

  • SQL / browse / edit payloads are { asGate, asUserId }. Local-only asUserId on the SQL picker is gone โ€” the server stamps the full bag.

Console โ€” Units & Call API

  • Policy-only invoke no longer mints userId: "gate:${name}". oke.user() is empty unless a seeded user is picked. Invoke may return rls.

Runtime

  • Linear / edge match order is static, then :param, then * โ€” same as Trie and RegExp. A first-registered /notes/:slug no longer eats /notes/archive.
  • User-plane fx.store applies RLS on postgres / pglite. Apps that created Console policies and relied on the app role ignoring them now filter.
  • Public contract is oke.gate() / oke.user() / oke.has_scope(). Docs and templates no longer teach current_setting or current_user.
  • Special TO roles stay unquoted (public, current_user). Manifest Table gains rls + policies.
  • HTTP trigger .gate.public is gone. Mark a route open with .public(), sibling of .live(). gate.public stays the element sentinel.

โ™ป๏ธ Changed

Dev, Keel & create-oke

  • Keel and create-oke templates pin the same drizzle rc5 pair as the framework (orm@1.0.0-rc.5-169397b, kit@1.0.0-rc.5-ab785fc).
  • create-oke Notes (standard / advanced) use the file tree. app.ts is import "@/flows/generated" plus oke({ name }) โ€” .adopt(routes) is optional. Keel core.ts splits by element; the barrel stays @/core. oke ai setup prefers src/core/ai.ts when that file exists.
  • oke dev Ready board uses aligned name / port columns, and each bound surface (Backend, Console, MCP, Docs MCP) is its own box with the URL and a one-line purpose.

Runtime

  • Drizzle pin: drizzle-orm@1.0.0-rc.5-169397b (npm rc5) and drizzle-kit@1.0.0-rc.5-ab785fc (kit rc5). There is no 1.0.0-rc.5 on the registry.
  • User-plane HTTP fx.store stamps Gate identity per statement on postgres / pglite. Cron / CDC / signal stay table-owner.
  • oke() auto-drains store.kv / store.index, clock(), and gate.policy / .scope / .rate the same way as store.sql / vault.secret. Import the declaring module before oke() โ€” no hand-built stores / clocks / gate.policies arrays.

Docs

  • New Get Started page: Project structure โ€” folders are the URL, reserved leaves, main prefix exception, QUERY vs leaves, [...slug] client key "*", and http.resource in a tree.
  • Introduction, Basic Usage, Client, CLI, and element pages point at Project structure so http.get("/โ€ฆ") + flow("unit.action") is no longer taught as the only identity.
  • Project structure: _ files are importable but not routes; match order is static โ†’ :param โ†’ *; generate-time method+path collision.
  • Bumped site dependencies: fumadocs to 16.14.5 / MDX 15.3.0, Next to 16.3.1, plus patch/minor updates for @base-ui/react, lucide, postcss, and @types/node.

Console โ€” Store

  • Store tree toolbar shows SQL, KV, Files, and Index icons to show or hide each facet. The eye menu and per-band Hide control are gone.
  • Query Run is play + label only. โŒ˜ Enter stays on the tooltip and the run menu.
  • Owner / Gate templates and the policy Code dock use oke.user() / oke.gate() / oke.has_scope().
  • Store Query results fade in once per completed run (180ms EASE_OUT, translateY 4px; reduced-motion opacity 120ms).

Console โ€” Flows & traces

  • Overview Traces Advanced filters now reveal/collapse with the existing AgentDisclosure clip-path (220ms open / 140ms close, EASE_OUT).

Dev, Keel & create-oke

  • oke db seed is a separate command (intro / confirm / outro). oke dev does not ask to seed โ€” not every project has a seed. The live controls add s to run that command as a child (oke db seed --force), not inside the oke dev process.
  • Keel (and store resource tests) generate Zod from tables via drizzle-orm/zod. The separate drizzle-zod package is gone.
  • Keel and create-oke templates are oke({ name }) โ€” stores, secrets, gates, clocks, and channel templates auto-register from @/core.

๐Ÿ› Fixed

Console โ€” Chrome

  • Key caps on primary buttons use the button ink so chords stay readable.

Console โ€” Store

  • Query console replaces a leftover default SELECT when that table is not in the live store, and seeds a random live table (not always the first).
  • KV browse value fills leftover grid width (same as SQL comment).
  • Files PDF preview was a blank iframe โ€” CSP frame-src 'self' blocked the blob URL. frame-src / img-src / media-src now allow blob:.
  • Resource header no longer repeats a singleton ref (kv:reminders ยท kv:reminders โ†’ kv:reminders). SQL still shows sql:db ยท sql:tasks.

Console โ€” Units & Call API

  • Extract expands z.object and drizzle-orm/zod (createSelectSchema / insert / update, tableZod().select) into Manifest JSON Schema so Call API Fields and the contract Request / Response lists populate instead of "Schema not expanded in Manifest."
  • Mutation receipts (clock.run-now, store edit, vault write, replay, channel send-test, โ€ฆ) return at as ISO-8601 UTC instead of epoch ms (1787305011525 โ†’ 2026-08-21T09:36:51.525Z).
  • Call API no longer seeds a JSON body on GET / HEAD / DELETE. Path tokens (:id) stay in Path params; leftover GET fields are Query params. GET /tasks/:id is path-only โ€” the duplicate Body id is gone.

Runtime

  • $routes from generated.ts accepts cron / signal / call-only flows โ€” AppRouteMap no longer requires method/path on every leaf.
  • Pathless http.get() types resolve HttpPathPending in the trigger namespace (verbatim type import).
  • PGlite RLS stamp is split statements (SET LOCAL ROLE oke_app, set_config) โ€” a multi-command batch is rejected by PGlite's prepared query path. Concurrent identities on the shared connection are serialized.
  • Postgres RLS stamps reserve() one Bun.SQL slot, then BEGIN / SET LOCAL on that slot. begin() plus parent unsafe() was deadlocking PgDog (checkout timeout). Store, journal, clock, and instances share one pool of 8; PgDog pool_size is 20.
  • oke.* helpers install again: toPostgresParams no longer rewrites jsonb ? into $1 when there are no bound values, and oke.has_scope uses jsonb_exists.
  • Creating schema oke no longer steals domain tables: search_path is public, oke, and leftover oke.<table> rows move to public.
  • fx.store(db).select().where() / .orderBy() compile Drizzle eq / and / or / like / asc again against the pinned drizzle-orm@1.0.0-rc.5-169397b โ€” that snapshot stores StringChunk.value as a string, not string[].

Dev, Keel & create-oke

  • Keel KV (drafts, reminders, view-prefs, webhooks) is { durable: true } and seed writes all four, so Console Store browse is not empty after Redis recreates. Seed logs keys N for kv.set.
  • recurring.spawn (and GitHub / Slack / form intake) call tasks.create by name so the Manifest stamps effects.calls โ€” aliased fx.call(createTask) was inferred as createTask and threw OKE1007 every hour.
  • oke db push treats drizzle-kit rename_or_create as create and retries, so a first-time Keel schema no longer fails missing_hints. Destructive confirm_data_loss still stops.
  • oke db push only manages schema public (schemaFilter), so it does not try to drop oke / oke_console.

Docs

  • Homepage starter snippet reads flows/main/route.ts after the tree split removed main/index.ts.