v0.12.0
✨ Added
Console — Chrome
motion(Motion for React) reserved for near-future ui-next animations; import viamotion/react.
Console — Observability
fx.askstamps driver-reported input / output tokens onto WideEvent, Parquet, and Console run rows. Observability AI rail shows window totals when present — never a 0-token placeholder.- Console **Runs SQL** (
POST /console/runs/query, Observability SQL tab) — read-only DuckDB over.oke/runs. Statement guard rejects DDL/DML/external access; isolated session setsenable_external_access=false; 5s timeout; 1000-row cap. Files driver skips re-copy when partition keys are unchanged. PII mask is column-key only (RunsQueryPiiProjectionGap). - Fleet registry (
oke_instances) — each process heartbeats every 5s (30s TTL) on the existing 1s scheduler.GET /console/instancesjoins Clock and Journal leases by the unified bootinstanceId. Observability showsN alive(unbound is empty, not 0). - Console **Observability** (
/observability) — health strip (Vault seal/KEK, Store drift, Clock overdue/lease, Signal queue lag, window P95 / error rate), top errors from the persisted runs buffer (opens Trace detail), and a Bklit composed chart (request volume, error count, dual-axis P95). AI cost stays empty untilfx.askwrites run telemetry. Instances chip readsGET /console/instances(alive ⇔ TTL). oke devlive Traces bridge: host-app WideEvents POST to ConsolePOST /console/runs/ingest(secret-gated). Console appends into its own runs store → existingfeedRun/projectRunPII mask forGET /console/runsand/console/live. Prod stays opt-in (oke({ runs })); the bridge env is set only byoke dev.- ui-next trace detail Sheet (shadcn, side=left): row click keeps graph highlight and opens a real breakdown — summary counts from EffectKind + logs, proportional waterfall bars from EffectEntry timestamps/durations (EDGE_STROKE colors), expandable event list, and REQUEST with Manifest method/path plus Shiki-highlighted
WideEvent.input. No RESPONSE section (WideEvent has no output field today).GET /console/runs/ live projection now include maskedinput. - Console **Kbd** key caps on the command palette, sidebar tooltips, Query run/save, Store grid find/undo/redo, and shortcut sheets.
⌘1…⌘5hop Overview / Flows / Store / Monitoring / Vault;⌘,opens Settings;⌘Elogs out. Caps show ⌘ on Mac and Ctrl on Windows. - Console explorer pages (Overview, Flows, Store, Observability, Vault) share a start-panel collapse / expand control on the inspector header.
Console — Store
- Call API **PII** matches Store Query: handler responses mask classified fields by default. Toggle includes audited cleartext (
revealPii). - Console Files is a folder browser, not a key table. Slash-separated keys become folders with breadcrumbs, list/grid views, and an inspector that previews text and images. Operators can upload (including drag-and-drop), download, and delete. Browse returns
sizeBytes;POST /console/store/objectreads one object;POST /console/store/editputspatch.body(utf8/base64). - Console Files uploads mint a URL-safe object key (
safeFileObjectKeyfromokengine/store) and keep the original name plus MIME / size in.oke/catalog.json. When the Manifest has afile_objectsSQL table, Console upserts that row too. Non-ASCII keys on/editare rewritten; the old key is deleted.fx.store(files).putis unchanged. - Console Store explorer facet bands (SQL / KV / Files / Index) have a show/hide control on each band and an eye menu in the search bar. Hidden bands leave the tree; restore them from the menu. The pick persists in localStorage. Selecting a resource in a hidden facet shows that band again.
- Console Store table rows show live RLS: emerald
ShieldEnergywhen enabled, mutedShieldOffwhen disabled (pg_class.relrowsecurity). - Console Store catalog create sheets expose **Advanced** Postgres knobs: Indexes (
CONCURRENTLY,INCLUDE,NULLS NOT DISTINCT,WITH), Functions (SECURITY DEFINER,STRICT,PARALLEL,LEAKPROOF,SET search_path,COST/ROWS), Triggers (CONSTRAINT,UPDATE OF, transition tables,TRUNCATE, function args), and Extensions (SCHEMA,VERSION,CASCADE—pg_catalogrefused). - Console Store **Create policy** Advanced pairs RLS with Gate **policy** and **scope** (
gate.public,gate.policy,gate.scope) — not the Access Module:Action / role catalog. Read / Write / Both stays the default. Picks stay on Gate —TO publicstays on the SQL. - Console Store **SQL** and **KV** facet bands open a query console (code icon on the band). SQL runs DML and DDL through
POST /console/store/sql(allowWriteon writes, includingCREATE/GRANT/EXPLAIN ANALYZE). The workbench has query tabs, session history, a Manifest schema rail (tables + columns), run current / selection (⌘Enter), run all (⌘⇧Enter, sequential, stops on the first error), EXPLAIN / EXPLAIN ANALYZE, gutter play marks, Prettify, a No LIMIT hint, elapsed time, and table / JSON / raw results with CSV copy. A multi-statement script opens a result tab per statement. The SQL editor completes Manifest tables, columns, and keywords as you type (context-aware after FROM / SELECT / WHERE, plus CREATE / ALTER / DROP / EXPLAIN); KV completeslist/get/set/delete/ttland namespaces. Schema collapses to a right-edge strip; results collapse to the status bar (Run expands them again). KV namespaces expand to inferred value fields (same rail as SQL columns). Double-click a tab to rename; Save keeps named queries in localStorage (History → Saved). Tabs persist across sessions. KVset(key, value, ttl?)writes throughPOST /console/store/edit(same script Pending Changes emits).deleteandttlmatch thefx.storehandle (ttlMs); word and call forms work for every command.oke_consolestays refused for raw SQL. - Console SQL query console toolbar can **include PII**. Default stays masked; turning PII on sends
revealPii: trueonPOST /console/store/sqland re-runs the last read (writes stay untouched). Results meta showsPII maskedorPII visible. - Console KV query console has the same **Prettify** control as SQL. It rewrites
list/get/set/delete/ttlto call form and indentssetJSON. - Console SQL query console can **view data as a Gate** — three cards (Operator, Public, As). Operator bypasses RLS. Public and As set
oke.gateon postgres / pglite. As picks a user (via their matching policy) or a Manifest policy gate. Policies readcurrent_setting('oke.gate', true). Memory SQL accepts the pick but does not apply session GUCs. - Console Store SQL band **Schema** opens a visualizer of Manifest tables, columns, and relations — declared
.references()plus inferred*_idcolumns (search, auto layout, copy as SQL, smart Colorize, PK / FK / unique icons, cardinality icons for many-to-one / one-to-one / many-to-many / self; click a related table to dim the rest). - Console Store SQL table browse can **insert a row** from the grid toolbar (Insert data). Empty fields stay NULL;
iddefaults to a UUID. OmitidonPOST /console/store/editto INSERT (patch.idrequired). - Console Store **Indexes** catalog can **Create index** — the same form-and-preview sheet as RLS Policies (templates, table / columns / method, plus a free highlighted SQL editor), then
CREATE INDEXthroughPOST /console/store/sql(allowWrite). Refuses anything that is notCREATE INDEX. - Console Store **Functions** catalog can **New function** — the same form-and-preview sheet as RLS Policies / Triggers (templates, name / args / returns / language, plus a free highlighted SQL editor), then
CREATE FUNCTIONthroughPOST /console/store/sql(allowWrite). Refuses anything that is notCREATE FUNCTION. - Console Store SQL folders add **Triggers** under each SQL store. Browse uses live
pg_triggerwhen the engine has it; otherwise an empty list. **New trigger** uses the same form-and-preview sheet as RLS Policies (templates, table / timing / events, plus a free highlighted SQL editor), then runsCREATE TRIGGERthroughPOST /console/store/sql(allowWrite). - Console Store tree adds **Expand all / Collapse all** next to search, on each facet band (scoped to that facet's folders), and on each store folder. Facet bands start open; store folders and SQL Tables start collapsed. Selecting a resource re-opens its facet, not the folder. Search still expands matching folders.
- Console Store can list the **
oke_consoleauth schema** beside app SQL (oke_operators, sessions, roles, API keys, identities) whenOKE_CONSOLE_AUTH_STORE=1. Hidden by default. Browse is read-only; credential hashes stay masked until audited reveal. Edit / delete / raw SQL are refused so operator-plane rows never joinpublic. - Console Store SQL folders add **Indexes**, **Functions**, and **Extensions** under each SQL store (app
dbandoke_console). Browse uses livepg_*when the engine has it; otherwise Manifest primary-key / unique indexes. Extensions list built-in contrib packs with an enable / disable toggle (CREATE/DROP EXTENSION). A Library sheet searches and adds external packs (TimescaleDB, PostGIS, pg_cron, DuckDB, plv8, FDWs, …) by name, alias, or category. Memory keeps the catalog in-process. The SQL editor does not complete these as tables. - Console Store SQL folders add **RLS Policies** (
__policies). Browse listspg_policies. Create policy reviewsCREATE POLICY(and optionalENABLE ROW LEVEL SECURITY) before it runs. **Templates** opens a flush rail beside the form (SELECT / INSERT / UPDATE / DELETE / ALL, owner,oke.gate, joins, restrictive extra check).oke_consolestays read-only. - Console Store Extensions can **upgrade** to the newest packaged version (
ALTER EXTENSION … UPDATE). The name chip shows the current version and an Upgrade action (pgvector0.8.0→0.8.6). Names link to the project page or Postgres docs. - Console Store replica-lag chip follows the newest touching run from the live runs buffer (same
/console/livemerge as Traces) and uses the Traces duration cool→hot palette (emerald → yellow → rose). Falls back to the store-list snapshot when the buffer has no lag. - Console Store **PII chip** toggles masking for every classified column on the current browse page. Off (amber) sends audited
revealPii: trueonQUERY /console/store/query; on (sky) remasks. Switching tables remasks. - Console Store browse **Import / Export** in the grid toolbar. Export downloads the current page (or checked rows) as CSV or JSON. Import parses CSV/TSV/JSON, matches rows by
id/keyalready on the page, and stages writable cells as uncommitted changes (PII[redacted]values are skipped). Does not insert new rows — there is still no/console/store/addendpoint. - Console Store JSON cells (KV
value, Indexmeta, and JSON strings) show a trailing **Open as table** icon. It opens a sheet with a flattened field table plus a full-height JSON editor. On writable KV/SQL cells, table fields and JSON source both edit in place and stage the reconstructed object as an uncommitted change. - Console Store KV browse adds **TTL** and **size** columns. TTL is remaining time from the driver (
PTTLon redis; intended TTL on memory) and is editable in the grid (30m,1h, or empty to clear). Size is the UTF-8 JSON byte length of the value, and updates as you stage edits. **Add key** upserts viaPOST /console/store/edit(no/console/store/addendpoint). Value-only edits now preserve remaining TTL instead of wiping it. - **Console ui-next Store page (v1)** — read-first browse at
/store: facet tree, schema, masked SQL row browser with audited reveal, KV/files/index browsers with honest “not PII-classified / no SQL-grade masking” copy, and reverse readers/writers linking to Units/Flows (no edit/delete/SQL console). - **Console ui-next Store page (v2)** — browse is now a virtualized data grid (TanStack Table + Virtual, Base UI chrome) with column sort, find-in-page (honest “increase Limit to search more rows” copy), and safe mutations:
- Edit (SQL/KV) runs dry-run preview → typed
EDIT+ reason in production; PII-masked cells require audited reveal before edit and the client strips any[redacted]placeholder from the patch. - Delete (all four facets) requires typed
DELETE+ reason in production. - Server
applyEditrejects a patch value equal to[redacted]on a classified PII column so the mask can never overwrite real data. - No SQL Insert UI (no
/console/store/addendpoint); KV “add” is edit/set. - No server-side column WHERE filters yet — v1 find/sort are client-side on the fetched page only.
- Console Store SQL band **Performance** view — slow queries, cache hit rate, and live lock blocking from
pg_stat_statements/pg_locks(QUERY /console/store/sql/statsand/locks). StructuredPgStatStatementsNotPreloaded/Unsupported/NotCreatedinstead of a generic 500. Index Advisor is opt-in: Enable whenpg_available_extensionslistsindex_advisor, otherwise a CTA to pinoke-postgres-advisor:18-alpine. Suggest copiesCREATE INDEXDDL and does not create indexes. - Local
postgres/pgvectorrecipes preloadpg_stat_statementsat postmaster start. Timescale keepstimescaledbfirst (timescaledb,pg_stat_statements).supabase/postgresand Yugabyte commands are unchanged. Opt-inoke-postgres-advisor:18-alpineemitsDockerfile.postgres-advisor(hypopg + index_advisor). Defaultpostgres:18-alpineis unchanged. - ui-next seed now fills all four Store facets with real data (previously schema-only): SQL
bookings5 rows /shipments3 rows (with a PIIemailcolumn), KVholds4 keys, Filesuploads3 objects (one non-ASCII key for warnings), Indexdocs4 vectors. Seeded viaseedUiNextStoreDatain both the Vite dev plugin and the Playwright fixture. fx.store(index).list(limit?)returns stored documents (id + meta, no embeddings) on every index driver. Console Index browse uses it so an empty search lists the catalog.- Store query performance: preload vs
CREATE EXTENSIONvs unsupported on Postgres / Timescale / Supabase Docker / Neon / Supabase / Yugabyte / Cockroach pages. Index Advisor opt-in image documented on the Postgres recipe. - Store KV **Performance** (
QUERY /console/store/kv/stats) — Redis-wireINFO/COMMANDSTATS/SLOWLOG/LATENCYon the KV band.memoryreturnsKvStatsUnsupported. INFO is instance-wide (StoreKvStatsServerWideGap). SLOWLOG args collapse until reveal (StoreKvStatsSlowlogArgsGap). NoMONITOR, no invented hot-keys.
Console — Vault
- Console Vault **Add** (
+) creates a secret or config from the operator plane as well as fromvault.secret/vault.configin source. Metadata lands in.oke/vault-contracts.json; the value uses the same write path as Set. A review dialog (name + fingerprint) pauses before the write — same as set / rotate. Rows show aconsolechip until the name is declared in the Manifest. - Console Vault is a security instrument, not a filter-and-empty-state. Deep search (
is:unset,is:blast,from:.env.local,reader:,fp:) ANDs over name, fingerprint, readers, and winner. Posture chips and a scan board surface unset, blast, shared, dormant, and overdue contracts. Resolution is a lock-path. Security (verify chain, rotate master, fingerprint export, CLI copy) lives in one sheet. Values stay write-only. - Console **Vault** page (
/vault): fingerprints-only list + backend status, set / rotate via typed confirm, and master rotation throughPOST /console/vault/rotate-master(one batch,remaininghonest,ROTATE_MASTER+ reason). Any operator in the same process may continue; overlapping batches returnVaultRotateBusy. Generated master key is shown once and never logged. Audit verify isGET /console/vault/audit/verify(ok,brokenAt,reason,row). Backup stays on the CLI. The Console never accepts a master key in the HTTP body.
Console — Flows & traces
- Boot wires
drivers.runs(filesindev/prodat.oke/runs,memoryintest).oke replayand host recording share that root. create-oke templates install@duckdb/node-api.runs.keepdeletes old Parquet partitions (7dindev,30dinprod). ConsolelistRunsunions live ingest with disk so Traces survive a Console restart. - ui-next Flows split-view is bidirectionally interactive: clicking a flow node filters the Traces list (
flow = Xadvanced clause), clicking a signal node filters to runs whose flow emits or consumes that signal, and clicking the canvas clears the filter (removable chip in the filter row). - ui-next Trace detail sheet supports sticky effect focus — click a waterfall bar, overview segment, or event row to pin emphasis (click again to release).
- ui-next Replay is now visible: a Motion playhead sweeps the waterfall while bars grow as it crosses them, the hero duration counts up in sync, and the Flow graph pulses along the causal chain. All motion respects reduced-motion settings.
- ui-next Traces pane parity: contextual
formatDuration(μs / ms / s), status row tint + trigger icons (HTTP / Signal / Clock), persistent selected accent, hover Replay + Copy run ID, and All/Errors + duration-threshold filters over the scoped runs list.POST /console/traces/replaynow re-invokes throughrunReplay(same path asoke replay --request-id), not a log-only stub. - ui-next trace detail Sheet surfaces the **Gate** element: summary chip from
run.gates, plus a Gates section with Manifest kind/description (e.g.member· policy · Signed-in member onsupport.triage). - ui-next Request section is a protocol frame: method-colored rail, Body with Fields/Raw toggle (typed key·value rows + per-field copy), byte size, and line-numbered Raw JSON.
- WideEvent / Console runs project optional **
output** (flow return value), PII-masked likeinput. ui-next trace sheet shows an Output protocol frame; seeded skyport runs include realistic outputs (failures omit them). - ui-next Traces duration filter uses shadcn Base UI
Selectwith cool→hot colored dots on each threshold (Any / >10ms…>5s), matching row duration tones. - ui-next Traces **Advanced** filtering: progressive-disclosure dimension query (
flow = X AND cache = miss AND duration > 1s) with presets, chips, and expression editor — same language as Runs (§9.11), client-side on the scoped list. - ui-next eight-element HugeIcons vocabulary (
ELEMENT_ICONS) aligned with site Lucide; Traces trigger icons and Flow graph nodes share Flow / Signal / Store / Clock / Gate / Vault / Channel / AI glyphs. bun run dev:console-next:seeded(OKE_CONSOLE_NEXT_SEEDED=1) boots the same Console kernel + skyport Manifest + seeded WideEvent chain as the Playwright ui-next fixture, so opening http://127.0.0.1:6537 shows a real Flows graph and Traces (click → highlight). Terminal prints URL, claim code, and a one-line seed summary.
Console — Units & Call API
dev:console-next:seedUnits tree is a full work-management HTTP surface: CRUD on tasks, comments, projects, documents, attachments, spaces, tags, goals, members, views, and forms, plus custom routes (archive, assign, complete, follow, QUERY search, PUT drafts, HEAD health). Call API binds every HTTP flow.- ui-next Units ↔ Flows connector:
/flows?flow=<id>seeds the graph/Traces filter and fitView; Units contract header has **Open in graph**. Recent activity strip shows real buffered call count / error rate for the selected flow (honest empty when the Console runs buffer has nothing in-window). Units subscribes touseRuns+/console/livelike Flows. - ui-next Units **Platform failure modes**: derived only from this flow's Gates
- request schema with HTTP-encoding truth (
Unauthorized401 ·Forbidden403 ·RateLimited429 ·ValidationError422) — not OKE#### codes and not Call API chrome's default-400 quirk. Declared Flow errors stay a separate tier. - Console
POST /console/flows/invokeexecutes the target flow on a bound host via invoke-as (assumed identity scopes) — no more stubecho/inv_*responses. Fail-closed when the host adapter is unbound. OptionalpathParams; response includesstatus/failure/runIdwhen the host provides them. KernelexecuteacceptstrustedInvokefor console-trusted principal injection outsideenv: "test". - ui-next **Units** page (
/units): Manifest flows grouped by unit, contract panel (request/response schema rows, typed errors, gates, effects), and session-authenticated Call API wired to real invoke-as.
Console — Auth & shell
- Console claim **Generate** mints a first-operator password that meets Console policy (12+ upper, lower, number, special) and copies it to the clipboard.
oke console claim-codeprints the first-admin claim mirrored to.oke/claim-code(mode 0600) on Console boot while setup is open; cleared after a successful claim. Same code still prints once to the boot log.bun run dev:console-nextboots an ephemeral Console kernel on :6533 beside Vite and prints the claim code in the same terminal (also mirrored to.oke/claim-code). Usesbunx --bun viteso the Console graph runs under Bun (not Node).- ui-next operator login when setup is closed: Email + Password (TanStack Form + Zod + shadcn Field) posts to real
POST /console/session/login, storesoke_console_aton success, and surfacesAuthFailed/AuthRateLimitederrors. Same ConsoleChrome shell as claim. Gate extended intest:console:setup-ui-next. - ui-next authenticated shell (Phase 3): TanStack Router (
/pre-auth,/overview·/flows·/storeguarded shell). Claim and login success navigate to/overview. Sidebar-07 layout collapsed by default, OKE logo header, Overview/Flows/Store nav with honest Empty placeholders. Unauthenticated shell visits redirect to/. Gate:test:console:setup-ui-next. - Parallel Console SPA scaffold at
src/console/ui-next/(React + Vite + shadcn/Base UI + TanStack Form/Query + HugeIcons) with a real first-admin claim page wired to/console/setup/statusand/console/setup/claim. Existingsrc/console/ui/is unchanged; cutover is not yet. Gate:bun run test:console:setup-ui-next. - ui-next shell chrome: OKE wordmark + light/dark/system theme toggle (official shadcn Vite ThemeProvider,
oke-console-themestorage, no next-themes). - Console sidebar **Fast** opens a ⌘K command palette (navigate, theme, settings, logout). **Settings** is a dialog with operator identity and the theme toggle. **Logout** posts
/console/session/logoutand returns to sign-in.
Runtime
http.resource(path, ops)chains.gate(...)and.live()likehttp.get. Gates apply to every verb; live marks list and get.gate.all(...members)reuses a gate chain..gate(write)flattens the handle (and plain arrays) left to right. The compiler expands.gate(write)and.gate(...WRITE)ontoflow.gates..gate.publicis the unauthenticated sentinel — same as.gate(gate.public), without importinggate.- Handwritten HTTP lists prefer the Stripe envelope (
outis the item array,fx.json.withQuery(rows, input)). Extra keys auto-eq except pathid.fx.json.with(page)stays for an already-built pager. Any other declaredoutis still valid. - Official managed vault providers now include Azure Key Vault, GCP Secret Manager, Doppler, and 1Password Connect alongside AWS Secrets Manager. Set
drivers.vaultto"managed"andOKE_VAULT_PROVIDERto the id. Cloud SDKs stay optional peers; Doppler and 1Password usefetch. http.query()— RFC 10008 safe, idempotent HTTP trigger that still carries a JSON body.Content-Type: application/jsonis required (missing → 400InvalidQuery; other types → 415UnsupportedMediaType). Invalid JSON is 400 with no sniffing. QUERY responses and 405s that allow QUERY advertiseAccept-Query: "application/json". CORS default methods include QUERY; CSRF treats QUERY as safe (like GET). The client always sends a JSON body on QUERY ({}when only path params remain).- Browser
GET(Acceptpreferstext/html) paints the JSON envelope in traces chrome — flush h-10 strips, hairline /60, status + handler latency - cache (hit / miss / none), a right-rail Routes tree (static GET links; POST and
:paramlisted), line numbers, copy, Pretty / Raw (compact stays on the same page).curl,Accept: application/json,?format=json, and/_/·/_oke/stay JSON. - Console operator reads
store/query,gates/simulate,gates/powers,access/effective, andchannels/previewnow bind QUERY.store/previewstays POST (audited dry-run).
Dev, Keel & create-oke
- create-oke
standard/advancedship a Vite 8web/SPA. Vite ownsindex.htmland proxies/notes·/health·/_oketo the app.bun run webafteroke dev. - Keel lists speak PostgREST v16 read grammar:
col=eq|neq|gt|gte|lt|lte|like|ilike|in|is|match|imatch,not.,like(any).{…}, nestedor=/and=/not.and,order=col.desc.nullslast,select=id,alias:col.store.resourcenow acceptsnot.,is.not_null, quotedin.(), and nestedor/andgroups. bun run dev:keel:resettears down the keel Compose stack (oke docker clean --yes) and deletes.oke/,.env.local, and generated Docker extras so the nextdev:keelis a first boot.defineSeed({ name, description })labels this app's seed (template or example).oke devasksSeed keel (Featured Harbor GA story + volume + vault stubs)?and.oke/state.jsonstores that id — a different name re-prompts. Not a global seeded flag.examples/keelis a work-management OKE app (not a create-oke template) foroke devagainst Compose — Postgres, PgDog, Redis, RustFS, Mailpit, Meilisearch, and llama.cpp. Featured Harbor GA task chain, stub GitHub/Slack ingest,bun run dev:keel, thenoke db seed.- Keel pins
images.pgdogso Compose puts PgDog in front of Postgres.DATABASE_URLis the pooler (:6432);OKE_STORE_SQL_URLstays the direct host. create-okeasks **Add a reverse proxy…?** (Caddy / Traefik / nginx / No) and persistsproxyin~/.oke/create-defaults.json. Flags:--proxy <id>/--no-proxy.- nginx image recipe (
nginx:1.27-alpine) — generatednginx.confreverse proxy on :80; companion docs under Recipes → nginx. playwright.ui-next.config.tsalways records trace + screenshot + video; afterbun run test:console:setup-ui-next,bun run test:console:setup-ui-next:reportopens the HTML timeline report.oke-imagesskill (.agents/skills/oke-images/) — probe registries and bump Compose pins in catalog, recipes, templates, Keel, and docs without inventing tags.
Docs
- Docs site machine surfaces for agents: spec-compliant
/llms.txt(absolute links, curated sections, Optional rest),/llms.json,/llms-full.txtwith teaching-figure fallbacks,/llms/agents(the AGENTS.md contract),/robots.txt(allow-all including named AI crawlers), and/sitemap.xml. Per-page markdown is/llms.mdx/docs/⟨slug⟩;/content.mdand.mdstill resolve. HTML docs pages advertiserel="alternate"type="text/markdown".
💥 Breaking Changes
- Global password policy defaults are now minLength **8** with uppercase, lowercase, number, and special character required (
DEFAULT_PASSWORD_POLICY.requireSpecial). Previous defaults were minLength 12 with letter + number only. Override viagate.auth.passwordPolicy/createOperator({ passwordPolicy }). The special-character option is namedrequireSpecial(failure reasonrequireSpecial); do not userequireSymbolon password policies. - Stack env is project
.env.localonly. Vault resolution is driver →process.env→.env.local→ (optional)dev-fallback.oke dockermerges stack keys into.env.local; composeenv_fileis../.env.local.COMPOSE_ENV_RELis.env.local. The.env.dockerfile and resolution source are gone. - Console routes are now
/overview(graph + Traces),/flows(explorer),/store, and/vault. Unknown paths (including/units) are 404 — no legacy rewrite. Dev scripts aredev:console/:seed/:fresh(the-nextsuffix is gone).
♻️ Changed
Console — Chrome
- Explorer folder rows (
db, Tables, unit folders) use the sametext-xsas leaf rows — the group token had no size and read larger. - Signal uses Hugeicons
InternetAntenna03everywhere (Units bands, live flags, traces, graph) — was the slashedRadio01. - Console tab chrome uses the O mark favicon, title **okengine Console**, and an operator description meta (was a generic icon and "oke Console"). Module routes prefix the page name (
Overview · okengine Console). - Console data tables drop the muted header fill and use the same hairline / hover as explorers: Store browse, query results, files list, JSON inspect, and Vault fingerprints. Store browse restyles the row checkbox at the table, not the shared control.
- Console sidebar: the graph/traces page is **Overview** (
/overview); the Manifest catalog is **Flows** (/flows)./unitsredirects to/flows. Sign-in lands on Overview. Legacy?next=/unitsrewrites to/flows. The Flows explorer search placeholder is **Search flows…** (was units). - Schema type badges use one hue per type (string teal, integer blue); rose stays on risk pills.
- Console sheets share one flat language: full-bleed fields (no boxed inputs), text toggles instead of chips, and a flush Cancel | action footer. Create policy, index, function, trigger, insert, KV add, edit, confirm, pending changes, and the extension library all use it.
- Console theme toggle is strip tokens (ink when active, icon-only when idle) — no sliding pill, no muted chip. Same control in Settings.
- ui-next theme tokens match SACP web zinc (tuned dark card/muted + chart/sidebar).
Console — Observability
- Observability SQL Run is a stretch strip token; the PII gap note is hairline text. KPI labels use tracking 0.08em and
/60hairlines. Error rows open the local Trace sheet instead of navigating to Overview. Leftovermonitoring-*slots areobservability-*. - Console explorers share the Overview traces language: flush rows, bare tinted icons, tabular counts, and a full-height selection rail. Flows, Store, Vault, and Observability lists plus detail headers drop boxed wells. Advanced on Flows is an icon control like Traces.
- Console inspector identity (Vault / Store / Units) matches the Observability Query / Metrics header: one h-8 strip. Title, kind, and env / copy sit on one centered baseline; risk, PII, Set, and Rotate stay full-height strip tokens. Vault posture and Units activity use the same stretch bar.
- Console explorer tokens encode traces chrome: stretch toolbars,
EXPLORER_STRIP_*bars, flat icon buttons (no bordered wells). Search, filters, Query, Call, Vault, and Monitoring strips use those tokens — selected ink only. - Console Monitoring Metrics / SQL tabs and the Query header are flush strips (no pill tabs, no blur header). Sidebar module icons are flush in the rail — hover fill, no chip. The brand cell and explorer search / identity / command headers share h-10 — between the old 32px strip and a full 48px rail square.
- Console sidebar order is Overview / Flows / Store / Monitoring / Vault. Monitoring uses the chart-analysis mark.
- Console Monitoring is now **Observability**. Canonical route is
/observability;/monitoringkeeps a search-preserving redirect (bookmarks and?next=). Sidebar, command palette, and digit4point at the new path.
Console — Store
- Store KV uses Hugeicons
Braceson the band (same{ }mark as site Store docs). Leaves use a job glyph — drafts, reminders, view prefs, webhooks — instead of the same key on every row. - Store Index / KV leaves skip the folder wrap when a store has one child with the same name (
comments→comments). Files already did this for a single bucket. - Console Store Query PII uses the view / view-off glyph. Gate keeps the shield so the two toolbar controls no longer share an icon. The query command strip matches Call API: full-height, square tokens (Gate / PII / Schema / Run). Gate As picker drops the User/Policy tray and rounded rows for flush list chrome.
- Console Gate picker (Store Query and Call API) is a flush strip: Operator / Public / As keep the access diagrams; Operator and Public show a one-line hint; As still opens the user/policy list.
- Console Query results toolbar matches the command strip: h-8 flush tokens, hairline /60, no boxed icon wells.
- Console index browse Search / topK lives on the grid toolbar (one strip — no second search row). Sidebar nav idle icons sit at 40% ink; the active module is a solid accent chip.
fx.store(index).driverIdis the configured driver before first I/O (was a gated function, so seed treated Meilisearch as memory and wrote one vector blob). Keeldevpinsmeilisearch. Index browse promotes title / identifier columns.- Console Index browse is a search box, not a vector probe. Type a phrase to rank documents by id and stored meta (Meilisearch uses full-text
q). Paste1, 0, 0to run an ANN probe. Opening the index lists documents immediately. - Console Overview graph is a radial hub, not a spaghetti of every flow × effect. OKE sits at the center; the eight elements orbit it; each element's kinds sit on a middle ring (Store SQL/KV/Files/Index, Gate policy/scope/rate/flag, Channel email/SMS/WA/Push, and the rest); units sit on the outer ring with live heat from Traces. Hover a unit to light the elements it touches. Click a unit or flow for a 1-hop neighborhood; click an element disc to fan its resources. Map breadcrumb returns to the hub. Opening Overview runs the orchestra: random notes from the traces ledger land as new rows and light that request's path on the hub (paused while a run or neighborhood is open).
- Console Files treats the **bucket** as the inspectable unit. A singleton
store.files(name, { buckets: [name] })is one tree leaf (noattachments → attachments). The list payload may includedriverId(memory/fs/s3) so the tree and header can show where bytes live. Click a file to open a right-side sheet (same chrome as SQL / KV row detail) so the folder list stays full width. The sheet previews images, PDF, video, audio, and text (pretty JSON, CSV table). The toolbar is path + find + view + upload + delete + refresh. - Console Files upload shows the original name (Unicode OK) and a generated ASCII key. The browser lists and searches by original name. Existing non-ASCII objects keep the
non_ascii_keywarning until they are re-uploaded. - Console Store **Create policy** is easier to scan: table and behavior share a row,
FORis a compact command strip, Gate / Rows are chaptered, and the SQL preview stays pinned above Create.USINGandWITH CHECKappear only for the commands Postgres accepts. - Console Store **Create index**, **New function**, and **New trigger** match that layout: compact template chips, paired fields, chaptered Options, and a pinned editable SQL dock above Create. Choice rows (Language, Method, Timing, FOR) keep the label on the same line as the chips so they do not read as empty field headers.
- Console Store SQL catalog folders use
sql:db/indexes(andfunctions/triggers/extensions/policies) instead of the__indexesreserved prefix. Query still accepts the old__names. - Console Store **Extension library** Install reviews required extensions and the
CREATE EXTENSIONSQL (requires first) before enabling a pack. - Console Store **Extension library** is a marketplace sheet: featured Timescale / Cron / PostGIS cards, search + category select, and an installed badge — not a flat list.
- ui-next Store browse adopts a single toolbar + row-detail Sheet layout (SACP-style chrome): Refresh, find-in-results, sort indicator, Writers/Readers popover, tenant, page size, and row count on one row; column headers carry PK/type glyphs from the Manifest; double-click a row for Fields/JSON detail with the existing audited Reveal, edit, and typed-confirm Delete. No Insert / Export / pagination arrows — those have no real backend endpoints. Seed bookings gain an Arabic
noteso mixed RTL/LTR cells render without breaking column alignment. - ui-next Store resource pane is now an edge-to-edge explorer workbench: compact identity chrome (status chips on the right, PII copy on the chip tooltip), a command strip with growing find, a spreadsheet grid (PK / PII / numeric headers, cell focus ring, compact audited reveal), and an IDE-style status bar. Instructional banners are gone.
- ui-next Store grid is now the beUI editable Table: inline cell edit (commit on blur/Enter), row-handle delete (typed confirm, no Insert), selection, sort, resize, and reorder. PII-masked cells still use audited Reveal; JSON/RTL/numeric cells keep their formatters. Find, undo/redo, column visibility, and the status bar stay on the command strip.
- ui-next Store grid stages edits locally: dirty cells fill brown with tan text; a selected range is navy with a 2px primary outline on the head cell. Changes opens a Pending Changes sheet (Visual diffs + SQL, Clear All / Commit All, ⌘S). Click selects a cell, click again or type to edit, drag to multi-select (paste/type fills). The row-detail Sheet is gone from browse — edits stay in the grid until Commit All.
- Console Store Query / KV performance headers use the shared identity strip: one baseline for title, ref, and actions. The Index Advisor pin note lives in the limitation banner, not the h-10 chrome.
- Console Store Schema find is the explorer search field (flush, no magnifying-glass overlay). Table count stays tabular and unclipped.
- Console Store SQL / KV Query identity uses the shared header strip: one baseline for title, ref, and statement hint. Store / tenant pickers are flush tokens, not pills.
Console — Vault
- Console Vault list rows are two lines: description + risk on the first, env name and readers on the second. Healthy rows drop the trailing set/config word. Band hints live on the section title.
- Console Vault detail is one path: identity, a next-action banner with the verb (Set / Rotate) when something is wrong, a posture strip (from / read / readers / blast), then the lock path as a first-hit-wins spine. Pick a layer to copy its fill command in the row. Fingerprints and readers stay flush lists. Shared and in-flight runs sit on the posture strip / blast banner — no Advanced dump. One Set or Rotate on the page, not two.
- Console Vault set / rotate drop the typed
SET/ROTATEphrase. Pick a reason chip (scheduled,leak,provider, …) or **other** and type a note. Submit opens a review dialog (name, fingerprint, reason) — Cancel aborts; Confirm is the write. Add uses the same dialog. Rotate-master still typesROTATE_MASTER. - The
envvault driver lock-path matches vault/managed: driver →process.env→.env.local→ (optional)dev-fallback. Console writes still persist to.env.local. - Console Vault lock-path paints the winning layer emerald (same hit tone as the docs figure). Winner / last-read / readers / blast briefing rows carry icons. The first lock-path step is always
driver; its chip showsbuilt-in,managed · aws, orsimulate(env driver) on the same line. - Console Vault lock-path
simulate/ driver-kind chip uses emerald ink on the won wash (not muted-foreground) so contrast holds in dark mode. - Console Vault list bands (Secrets / Config) collapse like Store and Units. Row wells use posture color and icon (overdue clock, blast alert, config source) instead of one gray key.
- Console Vault lists declared contracts only — undeclared
process.envkeys no longer appear as secrets. Seeded keel vault is five secrets plus four public config values (origin, API, docs, workspace) with winners across driver / process.env / .env.local. Overdue chips sayoverdue; hover explains the rotate window (Last read older than rotate 90d — never-read counts). Secrets that must not rotate declarerotate: "never"(omit is the same); Console showsno rotate.
Console — Flows & traces
- Overview orchestra (random minted traces) runs only in
dev:console:seed. Liveoke devTraces stay operation-based — Clock, HTTP, Call API — not cloned ledger notes. - Console lookback and facet tokens are flat text (15m / 1h / 24h / 7d, Vault posture, Flows filters) — no muted segment well. Selected lookback fills the strip (
bg-muted/70). Filter tokens hover-fill the strip (Traces All / Errors / duration, Call dock, schema toolbar, sheet tabs). - Console overview Store spoke shows only SQL / KV / Cache / Files / Index. Named KV namespaces (
drafts,reminders,view-prefs,webhooks) fan when Store is focused. - Console Traces list row no longer shows Replay — that action lives on the trace detail sheet.
- Console Traces list row shows cache status before duration: flash for hit, slashed flash for miss, muted unavailable for not applicable (
run.cache). The detail sheet repeats the same mark next to the trigger kind. - Console Traces filters drop the pill well: All / Errors are flat text toggles and duration is a borderless select. Advanced visualizes applied clauses (
trigger = signal) instead of a raw query dump; presets toggle those clauses.SelectTriggernow acceptsflat. - ui-next Traces filter chrome: title, Advanced (icon + count), and live status share one header; All/Errors + duration sit on a single non-wrapping row with the duration select filling leftover width — no more wrap that stranded Advanced on a second line.
- ui-next Flow graph visual craft: per-kind HugeIcons + accents (Flow/Store/Signal/AI), color-coded bezier edges for reads/writes/emits/calls,
@dagrejs/dagreLR layout, selection glow + desaturated dim, tighter unit-group bounds, and a pannable MiniMap. oke devrequest lines append the WideEvent / run id after the timestamp so a ConsoleGET /console/vaultline can be pasted into Traces oroke replay --request-id.- Console Trace / Flows Gates heading matches Waterfall: title and count sit together on the strip, not justify-between.
Console — Units & Call API
- Console Units tree lists HTTP flows by method: GET, POST, QUERY, PATCH/PUT, DELETE (then name). Was alphabetical, so
deletesat aboveget. - Call API Response status uses the same traces cache glyph as the Traces list (
CacheGlyph: sky flash / amber flash-off / muted unavailable) beside200, then duration. Reveal-PII invokes skip auto-cache and do not invent a hit. - Console sidebar hops restore the last Flows / Units / Store / Vault URL (selected trace, flow, resource, contract) instead of wiping the module back to its empty landing.
- Seeded Console Call API runs against the same Store as browse.
issues.listreturns rows,issues.createinserts,attachments.deletereturns the deleted object. A leftover:idpath token isNotFound, not a fake 200. Path fields prefill keel seed ids. - Seeded Console list Call API takes query + pagination:
q,teamKey,limit,offset,cursor,orderBy,order. The response includesitems,count,total,limit,offset, andnextCursor. - Console Call API Response has an expand control that opens the full JSON in a wide sheet (copy included) so long list payloads are readable.
- Console Call API body fields sit on a container grid that drops from five columns to one as the dock narrows.
- Console Traces toolbar uses the same explorer search as Units / Store / Vault (
Search traces…) instead of a title. The query matches flow, unit, trigger, cache, error, and run id. - Units explorer bands and folders start collapsed (search still expands matches).
- Console Units inspector is a vertical workbench: contract briefing above, Call API docked below (always visible). Request/Response sit side by side; identity, Fields/Raw, Reset, and Call live on the dock toolbar — no more scrolling past a long contract to invoke.
- Console Flows contract no longer lists derived Platform failure modes (401/403/422/429 from gates + schema). Declared Flow errors stay. Gates remain in their own section.
- Console Flows, Units, Store, and Vault share one explorer language: 28/72 split, h-8 search toolbar, tinted band headers, sky selection rail, sticky identity header, and the same Empty pane. Vault search and posture chips live in the left explorer (not a page-wide bar).
- ui-next Units tree: trigger bands (HTTP, Signal, …) are bordered, clearly separated sections with chevron + tinted kind-icon headers; unit folders also show chevrons and nest flows under a guide line — both levels collapse/expand (auto-reopen when the selection is inside). Trigger glyphs are now distinct per kind (API / radio / calendar / timer / store / function) with matching icon wells in Traces.
- ui-next Units Call API is trigger-aware: HTTP keeps method/path + body; call-only keeps
flow.inwith a bypasses-caller note and Manifest callers fromeffects.calls; cron/every prefer lease-gated/console/clock/run-nowwhen a Manifest clock soft-joins, otherwise honest empty-input invoke fallback; signal keeps handler invoke with copy that it does not test bus delivery physics. fx.askstampsRunTelemetry.promptVersionand adds cost only when the driver suppliesusage.costgreater than zero. Token counts persist on the ask journal.oke devattaches the host AI runtime so Call API asks reachGET /console/ai. Child-process HTTP asks still have a separate journal (no ingest bridge).- Console Call API Response (and Body / Path params chapters) use the shared explorer strip: 0.08em heading, ink status, flush JSON rail — no padded well or status chip.
- Console Call API expanded Response sheet header is the same strip: stretch copy / close, hairline before close, no absolute icon-sm well or pr-12 dodge.
Console — Auth & shell
- Sign-in prefills
dev@oke.devonly on standalonedev:console/:seed.oke devand production leave email and password empty. - Console Sign in / Create admin expanding-arrow tile uses primary ink, not sky.
- Console Sign in / first-admin claim is a docked lock: wordmark sits on the plate, calibration ticks on the corners, two-column instrument fields, page-ink tile on the key. The submit key sits below the plate, not inside it.
- Console claim / sign-in lock column is
max-w-md(wasmax-w-sm) so the first-admin plate has room for the password meter and generate control. - Setup / sign-in is a gate, not an inspector: OKE wordmark in open air, LED eyebrow + display title, underline ledger fields, ink key. The page foot stays traces (brand, theme tokens, version) — no boxed tray, no pill theme well.
- Console claim / sign-in drops the nested muted tray. The form is a lock ledger (uppercase labels, underline fields, display title); setup state stays an LED eyebrow, not a strip chip.
- Console Sign in / Create admin is a sharp expanding-arrow key (primary bar inverted per theme, sky tile, near-black dotted trail) — beUI motion, Console rail color, no lime pill.
dev:console-next/:seedboot a fixed operator (dev@oke.dev/Okengine123!) so restarts skip claim; login form prefills in Vite serve.dev:console-next:fresh/:fresh:seedkeep first-admin claim open. Renameddev:console-next:seeded→:seed.- Console first-operator claim keeps a stricter minLength **12** with the same character classes (
CONSOLE_PASSWORD_POLICY), shared by the claim flow, ui-next meter/Zod, and setup docs. - ui-next password strength bar uses a red → amber → lime → emerald ladder (theme primary washed out mid-progress in dark mode).
- ui-next authenticated sidebar stays always icon-collapsed on desktop (no expand / rail / header trigger); mobile sheet trigger unchanged.
- Console sidebar footer drops the operator avatar. Icon actions are Fast (command palette), Settings, and Logout.
- ui-next authenticated shell drops the inset top header (page title breadcrumb); content uses the full inset area.
- Console is the ui-next SPA.
oke dev/oke startservesrc/console/ui-next/dist/. Initial-load budget is 700 kB gzip (no legacypanel-*split). - Access, Manifest Diff, Plugins, and standalone Runs are not in this Console yet — named backlog, not silently dropped. Backend projections remain.
oke devNotices and 4xx/5xx request follow-ups use the Claim house block: a colored◇ Notice/◇ 401chip on its own row, then the body — yellow for warnings, red for 5xx. No dim↳line.
Runtime
- The
filesruns driver no longer uses a deleted tmpdir: default root is.oke/runs,all()reads every Parquet file (not just this process's catalog), and the memory driver opens DuckDB only whenquery()runs. fx.json.withaccepts a{ data, meta }page (fx.json.with(page)) as well as the two-arg form. Flowoutstays the item array — do not put the page object onout.- List
meta.next/meta.prevare the next request ({ cursor }), not flags. The typed client walks withpage.next()orfor await (const page of api.notes.list({ limit: 20 }))— no.pages(), noif (mode), nohasNext.meta.next/meta.prevare typed{ cursor }bags for TanStackpageParam. Offset and keyset tokens share?cursor=.hasNext/nextCursor/hasNextPage/ClientCall.pagesare gone (unreleased).
Dev, Keel & create-oke
- Keel Files is one
keelbucket (wasattachments). Seed lays out workspace folders — attachments, documents, avatars, projects, exports, forms — so Console browse matches the app. - Keel and Console seed now declare four
store.indexfacets — tasks, documents, comments, and projects — and fill each from featured + volume rows (was tasks only). - Keel
oke db seed(dev) initializes the built-in vault and writes the keel stubs plus minted stack URLs (Postgres / Redis / S3 / Meilisearch / Mailpit / AI) so/vaultlooks like production..env.localkeepsOKE_VAULT_MASTER_KEYandPORT— other apps still leave Vault empty. examples/keelnow picks Signal delivery per job: comments, projects, forms, and goals emitonce+broadcast+live(notify / search / late-subscriber feed). Tasks addtask-changedbroadcast;task-assignedisliveoptional.- Keel Compose now starts llama.cpp so all eight elements are live.
drivers.aiisopenai-compatiblein dev/prod (mockin test); the hero showsopenai-compatible · granite3.3:2binstead of—. examples/keeland Console ui-next seed are work management (spaces, goals, projects, sections, tasks, forms, views) with first-classproject_manager/developerroles — not a Linear issue tracker. Featured walkable id isENG-12. Seed volume is ~500 tasks across SQL, KV, files, and index.- Keel scheduled flows drop the repeated unit from the name:
drafts.expire,overdue.watch,recurring.spawn,goals.rollup,digest.daily(wasdrafts.expire-drafts, …). - Keel list responses put the item array in
dataand pagination inmeta(Stripe envelope).outisz.array(Item), not{ items, count }. create-oke Notesnotes.listuses the same envelope. Store / Flow docs teach it as the preferred handwritten list, not a requirement. examples/keelflowin/outschemas now come fromdrizzle-zod(createSelectSchema/ insert / update on generated tables) instead of hand-copiedz.objectcolumn lists.- S3 files (
RustFS/ MinIO) create the configured bucket on first open whenS3_ENDPOINTis set, sooke db seedand uploads no longer fail withThe specified bucket does not exist. examples/keeloke db seednow writes the same lived-in Linear story as Console ui-next seed — featured ENG-184 chain plus ~500 generated issues, comments, labels, drafts, attachments, and search index documents.- ui-next seeded mode (
dev:console-next:seed) is a Linear-shaped **keel** workspace: github.ingest → issues.create → notify.onIssue,CycleClosedfailure, liveissues.list, cycle rollover, Triage Intelligence, and draft TTL — all eight elements plus CDC, ~14 SQL tables (teams through customer_requests), KV drafts, file attachments, and issue search. Eight featured rows + 72 ops (~80 traces). Store browse defaults to 500 rows so the 500+issuesbacklog (plus comments, labels, drafts, attachments) fills the grid.sql:dbalso lists the app Gate auth +oke schema generatesystem tables (oke_identities, sessions, roles, crons, vault stubs) — distinct from the Consoleoke_consoleoperator folder. - Default Compose image pins: RustFS
1.0.0-rc.2, Mailpitv1.30.7, PgDogv0.1.53, Meilisearchv1.53, llama.cppserver-b10450, Ollama0.32.13, vLLMv0.27.1, SGLangv0.5.17-runtime, Traefikv3.7, nginx1.31-alpine. Floating tags (postgres:18-alpine,redis:8-alpine,caddy:2-alpine) stay.
Docs
/llms.txtis a curated llmstxt.org index instead of the raw Fumadocs nav dump. Onboard AI copies/llms.txtplus/llms/agentson the current origin. The documented Vault curl no longer 404s.- Landing CollapseDiagram shows the zoo and okengine rings side by side on one shared step (no tab switch).
- AI docs:
fx.askresolves capability pinsname@versionagainst the declared prompt; a mismatched pin isai: unknown prompt.
🔥 Removed
store.resource({ unit })— unit comes fromflow("notes.list")and.adopt({ notes }), not a resource option.- Legacy
src/console/ui/Console SPA (15panel-*chunks, Vite:6534). - Console Traces duration-threshold select (Any / >10ms…>5s). Status (All / Errors) and Advanced (
duration > 100ms) remain.
🐛 Fixed
Console — Chrome
- Console shortcut caps use ⌘ on Mac and Ctrl on Windows. Detection reads Client Hints / userAgent, not only
navigator.platform. - Sidebar Logout hover is destructive ink + wash. Tooltip and palette show
⌘E/Ctrl+E. - Console icon-rail selection is readable: idle icons sit at 30% ink, the active chip uses a stronger
--sidebar-accent, and hover no longer clears the selected fill. - Console Flow and Store schema MiniMaps were blank: graph nodes only set
style.width/style.height, and xyflow MiniMap skips user nodes without top-levelwidth/height.
Console — Observability
- Console
GET /console/runsno longer nests each list response back into the runs store (console.runs.listoutput elided on record; prior list polls filtered from the projection). Live/poll fallbacks were doubling payload size every tick and OOMing the ui-next kernel (~GB RSS).
Console — Store
- Console index browse keeps focus while typing. Search no longer sits inside a tooltip trigger, the grid stays mounted across keystrokes, and the query waits 280ms of quiet.
- Console Store browse no longer shows classified emails in cleartext.
ownerEmail/owner_email(and the same JS/SQL spelling split) mask as[redacted]unless the operator enables Include PII. - Store Query editors paint SQL and KV with their own token colors (keywords / commands, strings, keys, numbers, comments) instead of a single gray overlay. KV is no longer highlighted as bash.
- Console Store KV browse on a dedicated namespace (
store.kv("drafts")) lists root keys (ENG-184) instead of looking fordrafts:*. Extract stampsnamespacesso Overview Store resources include KV. - Console Units Call no longer paints a thrown host error as
200+response: null. A 500 envelope orOkeError(including OKE1006 undeclared secret) shows as a failure. Extract now bindsvault.configsofx.vault.get(publicAppUrl)declaresPUBLIC_APP_URL, and list flows can return the seeded rows Store SQL already shows. - Console Units Call **Invoke as** uses the same Operator / Public / As Gate cards as Store Query. Operator bypasses the flow's gate chain; Public is anonymous; As picks a user or policy.
- Console Store schema graph infers camelCase FKs (
teamId,issueId,parentId) the same as*_id, so keel tables draw relation edges instead of a single unlinked column. - Console SQL query editor applies Shiki token colors with inline theme ink (
github-light/github-dark) soSELECT/FROMare not a flat grey overlay. - Console Units Call identity picker uses the same card menu as Store Query Gate (name, email, scopes) instead of a plain select.
oke devConsole Call API and Store SQL now use the live host app (compose Postgres / Redis), not the empty Manifest memory sandbox. Invoke-as no longer returnsInvokeDenied: host invoke not configured.- Console SQL query console **Gate** menu no longer crashes on open (
MenuGroupContext— label now sits insideDropdownMenuGroup). - Console Store RLS policy rows are editable in the grid (
ALTER POLICYfor roles / USING / WITH CHECK). Creating a policy with RLS on now flips the table shield to emerald. - Console Store explorer shows the RLS shield only on SQL tables (
pg_class.relrowsecurity). KV, files, and index children no longer get a muted "RLS disabled" badge. - Console Store SQL console no longer fails default
SELECT * … LIMIT 50;on the memory driver — trailing semicolons are stripped before parse. - Console Store Pending Changes **KV tab** shows
set(key, value, ttl?)instead of a fake SQLUPDATE. Visual diff is unchanged. SQL tables still get the SQL tab. - Console Store KV namespaces now have unique effect refs (
kv:draftsvskv:triage-snooze). Selecting one no longer highlights both, and browse lists only that namespace's keys. - ui-next Store cell edit no longer draws a focus ring; pending brown fill covers the whole cell. Escape or clicking empty space clears the cell range.
- Console
storeEdit/storeDeleteSQL DML throughsql.rawnow usesexec(the memory driver has no generic UPDATE/DELETE onquery), so ui-next Commit All actually writes rows instead of returningInternalError. - Console Manifest StoreRuntime now derives SQL
classifymaps fromtables.*.columnsPII/sensitive tags (andtable.columnkeys onstore.classifications), so browse masking matches listpiiColumnswithout a hand-registered classify map. Store query/edit/delete/sql paths also bind the panel-lazy runtime (previously only list did). - Console Store browse of a Meilisearch index no longer fails with InternalError after the index already exists. Open is idempotent (GET then create;
index_already_exists/ HTTP 409 is success). Browse errors show the driver message, not a bare code.
Console — Vault
- Console Vault **Set** on Simulated env no longer returns
VaultNotFound. The panel boots with gaps so the first write can land in.env.local. - Console Vault lock-path no longer shows
simulateunderoke devwhendrivers.vault.devis"vault". The Console was not givenoke.config, so it fell back to the env driver.oke devnow passes the loaded config;serveConsoleloadsoke.config.tsfrom cwd when it is omitted.
Console — Flows & traces
- Tier-1 cache hits record the real
computed:…lookup on the effect ledger. Trace Waterfall shows that cache read instead of "No effects recorded". Miss runs still show the store reads that actually ran. - Console Trace request / response body fills leftover sheet height. Raw JSON is no longer capped at 14rem with empty space below. The sheet is
max-w-2xl(wasmax-w-xl) so the payload has more room. - Console Traces / Runs no longer 500 after a failed login sits next to a successful run. All-null
error_codeParquet batches were JSON;Unauthorizedwas VARCHAR — DuckDB refused the union. - Console Overview no longer paints Cache as a fifth Store type. Store kinds are
sql·kv·files·index. Cache is a KV namespace (and HTTP read cache), not a facet. - Console Overview element discs are name-only: no
N livecaption and no live-heat pulse. Center edge handles stay invisible. Hubs are 56px and show the two-letter lattice symbol (Fl·Sg·St·Ck·Gt·Vt·Ch·Ai). Hover still names the element. - Console Traces Advanced clause and preset labels use stronger ink so they stay readable on the dark pane (no muted-on-muted greys).
- Console Traces list always shows relative time in the right column. Failed runs keep the rail / dot; hover still carries the error code.
- Console Flows graph keeps node cards (ships) above effect ribbons. Parent-group edges no longer inherit a child z-index that paints lines over store / signal / AI targets.
/flowsrenders the graph + Traces page and/unitsrenders the explorer — the path names now match the pages.- HTTP API-key Bearer now authenticates through
onAuth. WideEventprincipalis the key id anddimensions.api_keyis stamped. Session JWTs stayclaims.subwith no key dimension. Forged / revoked / expired keys are 401.
Console — Units & Call API
- Call API Fields / Raw no longer draws a second hairline under the dock toolbar (the toggle sat in its own strip).
fx.asknow converts Zod / shorthandoutto JSON Schema (validate +response_format). Mock fills that shape instead of{ ok, echo }, so Call APIdocuments.summarizereturns a summary instead of generic Unavailable. Docker openai-compatible fails loud withoutOKE_AI_URL. Concurrent/console/aino longer 500s on a duplicate DuckDBrunsview.- Call API Response no longer flashes cleartext then remasks, or drops the 200 chip on a PII toggle. Hide PII remasks in place; reveal refetches. The JSON viewer never paints a stale highlight.
- Call API **PII** now opens the host store session with cleartext when Include PII is on, and skips auto-cache so a prior masked list is not reused. Classified columns the handler reads (
ownerEmail) were already[redacted]at the driver. bun run dev:keel:resetwrites a fresh.env.localfrom.env.example(PUBLIC_APP_URL and the other vault / app defaults). The nextdev:keelregenerates stack passwords. Keel now passes KV / index stores, vault configs, and clocks intooke()so Call API and KV Query resolve after a wipe.- Overview Store spoke always shows **Cache** (engine
fx.cache— not a Call API / trace) and fans declared KV namespaces (drafts,triage-snooze,webhooks) so keel does not hide them behind a Store click. - Call API **PII** now renders on the toolbar. The panel imported
runs-piifrom a path Vite could not resolve, so:6533kept the last bundle without the control. - Tables with a
namecolumn (teams, labels, cycles, …) no longer fail Call API with OKE1001sql:db. The kernel now readstableNameso the capability matches extractedsql:<table>. - Console Traces now lists Call API invokes (
issues.listand other host flows). The in-process attach used byoke devposts WideEvents to the same ingest bridge as the app child, so they sit next to clock ticks likedrafts.expire. - Console Units Call Response shows the handler output JSON on success. Invoke-as also unwraps
fx.jsonand HTTP{ data }envelopes whenexecuteleftoutputempty. - Console Units Call path-param fields show the route token as a placeholder (
:id) and stamp the path on the Path params chapter. - Traces no longer show
0μsfor a handler that finished in the same millisecond. Duration usesperformance.now()when the app clock did not tick. Call API shows that handler time (same clock as Traces) and labels the browser round-trip asrtt.
Console — Auth & shell
- Command palette search mark is
size-3.5, same as explorer row icons — it no longer fills the 40px strip. oke devkeeps the first-admin claim code on the live board (paste URL +oke console claim-code). The code is TTY-only — never returned fromGET /console/setup/status. After surfaces bind, the TTY reprints one Ready board (elements, Docker, claim, notices, Backend / Console / MCP) so mid-boot db-push lines and health ticks cannot tear the claim box. Thebun --hotchild no longer clears the screen on schema reload. The pane drops after the first operator.- Console setup chrome footer no longer draws hairline rules against the theme toggle. Brand sits left, theme center, version right.
- Console Sign in after an expired session returns to the module you were on (
/store,/units,/flowsplus search) instead of always opening Flows.?next=only accepts those three paths. - First-admin claim/login no longer 500 with
ReadableStream has already been usedwhen a staleoke_console_atcookie (or Bearer) is present — public-flowonRequestskips re-wrapping a body already consumed byparseValidate. - Console fields stay transparent when the browser autofills.
htmluses Tailwindscheme-light/scheme-dark; autofill ink follows--foregroundwith no UA wash. - First-admin claim no longer flashes Sign in before Overview. Setup closes the instant the operator exists; the gate keeps the Created plate and uses the new session instead of swapping to login.
Runtime
fx.askwith a versioned prompt handle (document-summary@1) resolves the bare prompt id. Call APIdocuments.summarizeno longer returns Unavailableai: unknown prompt.- After
oke keel reset, Console Call API no longer mocksfx.askwhenOKE_AI_URLis set. Traces also showfail(code, { message })on the run (Unavailable was a code with no reason). - Clock
everyjobs no longer re-enter on the 1s scheduler tick. The slot (lastRunAt) is claimed before the handler, stacked ticks are skipped, and a named clock covers its interval so keel does not register bothwatch-overdueand15m. - OKE1005 no longer fires when a flow asks a prompt by name and the Manifest stamped
effects.asksasname@version(compiler pin).documents.summarize→document-summarymatchesdocument-summary@1. Distinct pins still deny. - Console Gates list no longer 500s on apps that use
gate.public. Reconstructing the Manifest usedgate.policy("public"), which is reserved. - Boot mints one
instanceId(inst-<uuid>) for Clock, Journal, and the fleet registry. They no longer mint independently with different prefixes. - Read-only flows cache automatically from inferred or ledgered
reads— nocache: "30s"and nofx.cache. The first GET is a miss; the next identical GET is a hit.cache: falseopts out; a duration string adds a TTL. Writes invalidate matching keys. GET /_oke/client.jsonwraps the runtime route map as{ routes }sooke devcan regenerateoke-client.d.ts. ChromeGET /json/versionprobes are silent on Backend as well as MCP.- Clock traces like
drafts.expireno longer fail with a bareOkeErrorand no message.fx.store(kv).delete(key)now extractskv:<namespace>(notkv:key),ttlMsis a read, and thrownOkeErrors record asOKE1002plus the cause. store.schema.tablewith anamecolumn no longer throwsUnable to resolve table name from valueon insert, select, or Drizzle emit.- Wrong-method hits on a registered path return **405** with
Allowlisting bound methods (was a generic 404). CORS preflight still answers first. Raw Console ingest 405s now includeAllow: POST. - Password policy special-character rule is canonical as
requireSpecialon bothDEFAULT_PASSWORD_POLICYandCONSOLE_PASSWORD_POLICY, with regression tests that a password missing only a special is rejected and that ui-next’s 5 checklist criteria match server validation. - Kernel edge and Store-only
oke()no longer statically import PostgRESTlistPage, i18n catalogs,http.resource, or auto-cache. Those load through computedimport.meta.requirewhen the feature actually runs, so unused graphs stay under budget.
Dev, Keel & create-oke
- Keel
oke db seedno longer fails vault boot on emptyOKE_CONSOLE_SECRET/MEILI_MASTER_KEY/OPENAI_API_KEY. Those contracts (and the other stack configs) now havedevfallbacks so the app can boot before seed writes the store. ComposeOKE_STORE_INDEX_KEYstill maps toMEILI_MASTER_KEY. oke db seedno longer crashes tallying Meilisearchupsert(undefined is not an object (evaluating 'result.status')). Index upserts return void; only SQL{ status }is counted.- Keel reset no longer pins
OKE_AI_URL=http://127.0.0.1:8080/v1.oke devwrites the published llama.cpp port (:23xxx). oke dev/bun run dev:keelhot-reloads Console UI from source. Vite attaches on an okengine checkout soui-nextedits no longer needbun run build.oke devunder Compose no longer refuses keel CRUD with OKE1008.bindCrudstampssql:<table>on each verb; extract expands the same. Authors do not declareeffectsat the call site.- A fresh
oke devhero now shows the effective driver map (signal Redis, clock Postgres, files S3, channel SMTP) even whenoke.config.tsonly pins overrides.dev:keel:resetSIGTERMs leftover listeners on:6530/:6533/:6535. Chrome inspector probes on MCP (GET /,/json/version) no longer paint as 404s. - Keel
oke db seedno longer inserts sections before projects (sections_project_idFK). Essential seed is spaces / members / tags; sections land with projects in the volume step. oke devno longer crashes when an app bindshttp.query(RFC 10008). Bun.serve nativeroutesreject QUERY; those verbs stay on the fetch fallback. An invalid route table retries fetch-only — Bun's HTML-bundling example is not printed.bun run dev:keelno longer dies with OKE1008 oncycles.list. Extract expandsbindNamedTableCrudinto unit-prefixed CRUD flows so effects are inferred, not hand-declared.create-oke**reuse previous settings** no longer re-asks locales / PgDog / proxy — saved answers from~/.oke/create-defaults.jsonapply directly (CLI flags still override).- ui-next
tsconfigno longer typechecks the Vite Console kernel plugin (SPA stays DOM-only); roottsconfigcoversvite.config.ts+ the kernel plugin. - Typecheck for
tests/console/setup-ui-next.spec.tsvia a DOM-scopedtests/console/tsconfig.ui-next.json(root stays ESNext-only for kernel/server tests). bun run buildno longer warns that Console chunks exceed 500 kB. Highlighting loads five grammars through the JS engine (no Oniguruma WASM / unused C++ bundle), and Overview / Flows / Store / Vault are lazy route chunks.oke devno longer writes a label-only Composeappservice when Traefik is pinned. That stub had no image or build, sodocker compose upfailed withservice "app" has neither an image nor a build context. Laptopoke devstays infra-only; Traefik labels still apply whenoke dockerincludesapp.oke devno longer attaches Console Vite HMR to the create-okefile:stage (~/.oke/create-oke/okengine). That copy hasui-nextsource but is not the monorepo, so the browser requested/src/features/flows/flows-page.tsxand failed. Scaffolded apps serveui-next/distlike a published install. Vite attach stays on for the okengine checkout (workspacesin package.json).- create-oke templates and the local okengine stage list
@duckdb/node-apiintrustedDependenciesso Bun runs its native postinstall. Console run history falls back to in-process events when DuckDB is missing instead of crashing the kernel. oke db pushmissing_hintsnow prints the unresolved statements instead of only the status line.
Docs
- Docs Signal and AI figures no longer ask Motion to interpolate
oklch/labtheme tokens (stroke/fillstay attributes; Motion animates opacity and position only). - Docs
GET /sw.jsis no longer a 404. A leftover service worker on localhost:3000 was still asking for the script; the site now serves an unregistering worker and drops the registration.
🔒 Security
Console — Store
- Console Store hides
oke_console(operators, sessions, credential hashes) unlessOKE_CONSOLE_AUTH_STORE=1. Query is refused when the flag is off. - Console security gate **5c**: default
QUERY /console/store/queryon a table with PII-classified columns never returns unmasked values;POST /console/store/revealreturns cleartext and leaves an auditedconsole.store.revealRuns log (operatorId, ref, child, id, column) — same suite class as gate **5b** host-ingest masking. - Console security gate **5e**: default
POST /console/store/sqlmasks classified columns;revealPii: truereturns cleartext and writes an auditedconsole.store.sql.reveallog (operatorId, ref). POST /console/store/sqlasGatemust bepublicor a declared policy Gate (rate gates refused). The pick is audited asconsole.store.sql.asGate(operatorId, ref, gate).- Store SQL performance query text is a named limitation
StoreSqlStatsQueryTextGap— engine-native fingerprints, not Store browse masking. Livepg_stat_activity.queryis collapsed untilrevealPii: true, which writesconsole.store.sql.stats.reveal. Documented in security.md §10.4. - Store KV SLOWLOG args (keys and values) stay collapsed until
revealPii: true, which writesconsole.store.kv.stats.reveal(operator, ref). Named limitationStoreKvStatsSlowlogArgsGap.
Console — Flows & traces
- Host → Console runs ingest never returns WideEvent bodies; operator reads stay on the masked
projectRunpath (adversarial PII gate covered).
Console — Units & Call API
- Console invoke-as adversarial coverage: assumed identity A never executes with identity B's scopes; host gates enforce the assumed principal.
Console — Auth & shell
- Console login
?next=is allow-listed to/overview,/flows,/store,/vault, and/observability(plus their search)./monitoringrewrites to/observability. Other values (including/units) are dropped so an expired session cannot be an open redirect.
Runtime
- Host HTTP API-key authentication stamps
principalas the bare key id (anddimensions.api_key) so Access per-key matching is real when a request is key-authenticated.