0.3

Every published okengine release, newest first.

all series · 0.4 · 0.2

v0.3.6

✨ Added

  • oke-ship agent skill — after every implementation, append changelog notes under ## Unreleased and sync site docs via oke-docs. Wired into AGENTS.md so sessions close work with changelog + docs.
  • libsql and pglite Store SQL drivers as optional peers. libSQL adds native F32_BLOB / vector_top_k ANN; PGlite provides opt-in PostgreSQL + pgvector parity without changing the local SQLite default.
  • Real pgvector ANN for PostgreSQL and PGlite: vector(dims) storage, HNSW with cosine operators, and similarity-ranked search through Drizzle's native vector API.
  • Optional description on element declarations — store.*, signal, channel.template, clock, gate.policy / gate.rate, field.*.describe(…), and plugin.table — extracted into the Manifest and preferred as Console titles when set (raw key fallback).
  • fx.all / fx.race — structured concurrency on plain Promises: pass thunks, first failure or settle aborts sibling branches via an ambient AbortSignal (fx.signal). No generators or monadic wrapper.
  • fx.retry(fn, { retries, delay, backoff, jitter, when? }) — exponential backoff with full jitter. Prefer inside fx.step so durable replay skips completed work.
  • flow({ retry }) — coarse whole-do retry on the same journal session (rewinds the durable cursor between attempts).

♻️ Changed

  • bun run bump promotes ## Unreleased into ## v{next} — {today} (and leaves a fresh empty Unreleased). Changelog notes for unfinished work no longer land on an already-shipped version section.
  • SQL-backed indexes share the SQL facet's existing connection. PGlite remains an explicit dialect-parity choice; measured WASM startup and warm CRUD remain meaningfully slower than native SQLite.

🐛 Fixed

  • store.index() now honors drivers.store.index at real boot and uses the same driver switch in the Console. Explicit pgvector or libsql configuration fails loudly when its SQL engine, extension, or optional peer is unavailable instead of silently using memory.

v0.3.5

♻️ Changed

  • bun run ci is the single local pre-push gate (format, lint, typecheck, integration tests, budgets, gate, site). Removed the unused ci:workflow split.
  • Tag-push CI no longer re-runs budgets (local-only); parallel jobs stay lint/fmt, typecheck, test, gate, site → publish.
  • GitHub Actions runtimes upgraded off deprecated Node 20: actions/checkout@v6, oven-sh/setup-bun@v2.2.0, actions/setup-node@v6.

v0.3.4

🐛 Fixed

  • Re-release of v0.3.3 so tag CI can publish: OpenBao bootstrap waits for Raft /sys/health active before policy writes, and the plugins export budget is rebased after the CORS / IP-allowlist hardening.

v0.3.3

✨ Added

  • ipAllowlist({ trustedProxyDepth }) — how many trusted proxies append to X-Forwarded-For (default 1). Client IP is taken that many hops from the right, matching how reverse proxies append rather than overwrite.

♻️ Changed

  • Site logo assets live under site/public/logo/ (wordmarks + letter variants); README and favicon paths follow. The docs site cycles the O / K / E favicon letters.
  • Rebased the plugins export budget after the CORS / IP-allowlist hardening (4.45 kB → 4.74 kB), and refreshed the published budgets snapshot.

🐛 Fixed

  • cors({ origin: "*", credentials: true }) now throws at construction (and again if runtime config introduces the pair) instead of reflecting the request origin — that rewrite would have granted any site credentialed access.
  • ipAllowlist no longer trusts the leftmost XFF hop (spoofable when proxies append). Wrong or non-positive trustedProxyDepth fails loud.
  • OpenBao bootstrap waits for /sys/health active (Raft leader writable) after unseal before mounts/policies — fixes flaky restart CI when single-node Raft still reports readonly storage.

v0.3.2

♻️ Changed

  • Rebased the vault-openbao export budget after a genuine size increase (608 B → 1.06 kB), and refreshed the published budgets snapshot.

🐛 Fixed

  • Docs skill forbidden-token lists no longer trip the stack-mode and removed-driver git grep gates (tokens are split the same way the gate tests avoid matching themselves).
  • Restored the missing bun run gate script so CI’s gate job runs again (staleness, removed-driver, error-registry, and upgrade codemod checks).
  • Renamed and scrubbed the removed-driver gate file so it does not match its own forbidden id under case-insensitive search.

v0.3.1

♻️ Changed

  • Docs origin cut over from okengine.vercel.app to [oke.omqkhafi.dev](https://oke.omqkhafi.dev). Error links, README, scaffold next-steps, site metadataBase, and llms.txt examples now point at the custom domain.

v0.3.0

✨ Added

  • Official plugins — first-party extensions shipped inside okengine, importable from okengine/plugins and attached with .plug(), built entirely on the public plugin API. The set: securityHeaders() (full helmet.js parity with API-first defaults — the complete secure-headers set on every response, failures included, plus a CSP builder with report-only mode), cors() (preflight OPTIONS answered at the edge even for paths bound to other methods; closed by default), csrf() (stateless fetch-metadata defense with an Origin fallback — no tokens, no cookies), compression() (native Bun.gzipSync for clients that accept gzip, with size and content-type thresholds), maintenanceMode() (one-flag 503 drain with Retry-After, allow-listed paths, and an operator bypass header), and ipAllowlist() (allow/deny rules by client IP at the edge of the pipeline). All no-op safely on non-HTTP triggers.
  • configSource() — runtime-mutable plugin configuration: code as the floor, a DB row as the source of truth, and a KV binding as the automatic read-through cache. Every official plugin accepts one in place of static options; one clock-bound sync flow (declared effects, so the fx rule holds) refreshes the in-memory box that hooks read. Flip maintenance mode, open a CORS origin, or enable HSTS from the database — no redeploy.
  • Plugin API: new .edge(fn) contribution — handlers for HTTP requests that match **no** flow (e.g. CORS preflight for a path bound to another method), run in install order before the plain 404, recorded as an edge intercept capability. The CORS plugin is built on it.
  • Kernel: HTTP flows now serialize their outcome into ctx.response **before** the onResponse pipeline stage, so the last stage sees — and may replace — the final response, as InvocationContext.response always documented. Encoder input mirrors the app layer exactly; non-HTTP triggers are unchanged.
  • Docs MCP: oke dev now boots the read-only docs MCP server next to the runtime MCP — app :6530 · Console :6533 · MCP :6535 · docs MCP :6536. No Bearer token (public documentation). Tools: oke.docs.search, oke.docs.get — agents answer "how do I … in OKE?" from the real pages instead of training-data memory. Docs content now ships inside the published package so the surface works in installed apps. Boot failure (missing content, busy port) skips the surface, never takes oke dev down.
  • Documentation overhaul — all eight element pages rewritten to one standard (quick start → contract → per-environment drivers → troubleshooting). New sections: Reference (oke.config.ts options, environment variables, error codes, the full fx API, plugin API), AI Resources (runtime + docs MCP, agent contracts and skills, llms.txt endpoints), and a categorized Plugins section (Security · Operations · Performance). CLI Reference and Security moved under Reference.

♻️ Changed

  • Vault: real OpenBao is now the docker / prod default driver (durable single-node Raft, real init/unseal, least-privilege app token). The previous age-based driver and its optional peer dependency were removed entirely. Single-point-of-failure by design: back up .oke/openbao/unseal.key to a separate safe location — losing it means losing every secret permanently, with no recovery.