0.8

Every published okengine release, newest first.

all series · 0.9 · 0.7

v0.8.0

✨ Added

  • Postgres Clock CronStore (drivers.clock: "postgres") — multi-host leader election via the same FOR UPDATE SKIP LOCKED + lazy lease reclaim pattern as Signal once delivery. Table oke_crons holds schedule rows with locked_by / lease_expires_at. Chaos-proven across OS processes against a real Postgres (OKE_TEST_POSTGRES_URL). file remains for local / single-host shared volumes.
  • defineSeed({ essential, dev, prod }) + oke db seed — explicit seed runs (never at boot). essential every env; dev on local/docker; prod on prod only. Docker/prod print the DB target and require typing the env name (--force skips). create-oke standard + advanced ship real src/seed/ (welcome note + sample notes).
  • fx.store(db).upsert(table, matchOn, values, options?) — insert when no match; existing rows untouched unless { onExisting: "update" }.
  • Store docs **Seeding** section (categories, upsert, confirm, migration boundary) and CLI reference for oke db seed.
  • <StoreSeeding /> teaching figure — env→block lighting + upsert outcomes under Store docs Seeding.
  • Phone-number OTP delivery via Taqnyat Verify — fx.sendOtp / fx.verifyOtp on Channel; when drivers.channel.sms is taqnyat, phoneNumber() uses Taqnyat's provider-managed Verify API (no self-generated code). Non-Taqnyat SMS drivers fail loudly; no SMS driver keeps the local hashed path + exposeDevOtp.
  • taqnyat-mail Channel email driver (additive) — magic-link and every channel.email template can deliver through Taqnyat Mail (TAQNYAT_MAIL_TOKEN + TAQNYAT_CAMPAIGN); SMTP/Mailpit stays the docker default.
  • Opt-in Taqnyat live test suite — real sendOtp (success code 5) and real Taqnyat Mail magic-link sends, double-gated behind the global per-medium flags OKE_SMS_LIVE=1 / OKE_EMAIL_LIVE=1 **plus** the real credentials; credential presence alone never sends. Skips are always visible.
  • Postgres durable journal (drivers.journal: "postgres") — durable-flow runs persist in oke_journal_runs with locked_by / lease_expires_at, reusing the Signal/Clock FOR UPDATE SKIP LOCKED + lazy lease reclaim pattern. memory (default) and file stay for local / single-host.
  • Boot-time orphan discovery — a booted app scans the shared journal for running / due sleeping runs without a live lease and resumes them, no caller-supplied runId; the scheduler tick also claims due sleeps and sweeps expired-lease orphans from the shared store.
  • Run-level lease coordination — every start / resume / wake acquires the run lease first (renewed on each journal persist, released on park / complete / fail), so two instances never execute the same run under a live lease; an in-process in-flight guard stops overlapping sessions (orphan scan vs. scheduler tick) inside one instance.
  • Durable-journal chaos proofs across OS processes — SIGKILL mid-run with survivor takeover (completed fx.step never re-runs) and a two-process race on one due sleep (exactly one executes), gated on OKE_TEST_POSTGRES_URL.

♻️ Changed

  • Booted apps bind drivers.journal from config instead of a hardcoded in-memory store. postgres without DATABASE_URL / OKE_STORE_SQL_URL fails loud at boot; the postgres journal pulls the store.sql docker image like clock does.
  • Template / create-oke: standard + advanced gain drivers.journalmemory for local/test, postgres for docker/prod.
  • JournalStore gains an optional lease surface — JournalLeaseStore (acquireLease / releaseLease / claimDueSleep / listOrphans), hasJournalLease, JournalLeaseBusy, and JOURNAL_DEFAULT_LEASE_MS (30s) are exported; memory and file stores implement it too.
  • Flow / Clock docs: durable crash-recovery claims are now scoped to a shared journal — postgres resumes after restarts and across instances; the memory journal remains same-process only. At-least-once for in-flight steps and the client-retry boundary are documented.
  • Template / create-oke docker+prod clock default: filepostgres now that the real CronStore exists (file still valid for local/single-host).
  • sently 1.0.0 → 1.2.0 — Taqnyat OTP helpers (sendOtp / verifyOtp) unchanged in shape; 1.1/1.2 add vendor extras + the opt-in live-suite pattern mirrored by OKE's new live tests.
  • Split JournalSuspend / isJournalSuspend into journal-suspend.ts so the kernel edge profile (retry filter) no longer pulls Node journal persistence into the browser bundle (~15.01 kB → ~13.4 kB gzip).
  • fx.store(sqlDecl) typed as SqlStoreHandle (facet overloads) so .upsert / .insert / .select typecheck; SQL decls without a store runtime throw instead of a stub missing those methods.
  • Store Seeding docs: full env matrix, simple vs complex file forms, upsert outcome table, CLI flags, seed-vs-migrate Callout.
  • Store docs: short **Multiple environments** note under SQL schema sync — local push vs staging/prod versioned drizzle/ + migrate catch-up.
  • oke db adversarial test: multi-file generate + re-migrate skips applied migrations; simulated env lag applies only the pending file (drizzle-kit __drizzle_migrations history through the CLI wrapper).

🐛 Fixed

  • Durable three-layer gap closed: with a shared journal, restarts no longer lose every durable run, crashed runs resume via the boot orphan scan, and the same run can no longer execute on two instances concurrently under a live lease.
  • fx.store(db).upsert through real oke()createTestAppapp.fetch() (regression test); SQL StoreDecl without a store runtime no longer silently returns a stub that made .upsert look like “not a function”.