# Changelog 0.17

## v0.17.2 — 2026-08-23

### ✨ Added

#### Docs

- SoftwareApplication JSON-LD now includes `applicationCategory` (`DeveloperApplication`) and a free MIT `Offer` (`price` 0, USD).

- JSON-LD `sameAs` adds the live JSR package and X profile. Wikipedia, Wikidata, and LinkedIn are omitted — those profiles do not exist.

### ♻️ Changed

#### Docs

- Homepage heading outline is H1 → H2 → H3 (readme/stack labels, element names, exports, surfaces, start-here cards) with no visual copy change.

## v0.17.1 — 2026-08-23

### ✨ Added

#### Docs

- Homepage SoftwareApplication JSON-LD — `name`, `description`, and `url` taken from the published site metadata (not invented fields).

- Markdown 404 body when `Accept: text/markdown`: links to `/docs`, `/llms.txt`, and `/sitemap.xml`. Status stays 404.

- Homepage canonical `/`, `og:type` website, and `/og/home` image — same 1200×630 renderer as the docs Open Graph pipeline.

- SoftwareApplication JSON-LD `sameAs` — GitHub repo and npm package pages already linked from the site chrome.

- `/llms.txt` opens with **When to use this**: Introduction, Installation, AGENTS.md, MCP, CLI, errors, npm, and GitHub.

### ♻️ Changed

#### Docs

- `/changelog` is an index of minor-version pages generated from `changelog.md` (one source, no forked copies) so each rendered page stays under the agent-readability budget.

- HTML handbook URLs negotiate markdown in `proxy.ts` and send `Vary: Accept`. The site is no longer a static `out/` export, because that Next.js mode cannot run the proxy.

## v0.17.0 — 2026-08-22

### ✨ Added

#### Console — Store

- When `tenancy.enabled`, the Store tenant picker lists `oke_tenants` only — not historical run-history strings.

#### Runtime

- `gate.auth.tenant` — tenant as an identity dimension (`true` or `{ required, source, header, resolve, authoritative }`). Claim `tid` is trusted; header/subdomain require membership. `fx.auth.listTenants` / `switchTenant` / `createTenant` / `upsertTenantRole` are session-only (`auth:tenants`). `switchTenant` mints a new family and never Set-Cookies.

- `store.schema.policy.tenant(column)` / `store.schema.unscoped()`, `oke.tenant()` RLS helper, KV `{tenantId}:` prefix, `clock.perTenant`, and `vault.secret({ perTenant })` request-time paths.

- **OKE1015** / **1016** / **1017** — tenant required, not a member, unknown or `console:*` tenant-role scope.

- `api.live(signal, input?, { onEvent })` subscribes to `delivery: "live"` HTTP SSE (callback + unsubscribe). Same handlers on exposing flows. Opt-in `autoResubscribe` reconnects with backoff and `Last-Event-ID`.

- `http.get(path).live(signal)` / `http.live(signal)` expose a live signal as GET SSE. `fx.live` is the stream carrier. Multiple audiences of one signal boot when gates or match shape differ.

- `signal(..., { delivery: "live", retention: { maxAge, maxCount } })` caps the retained tape (AND-combined; omit for unbounded). Drivers prune on write and when `live()` opens.

- Live SSE resume: reconnects send `Last-Event-ID`. A missing cursor is **OKE1014** / HTTP 410 `LiveResumeGap` — not a silent full replay. `autoResubscribe` then replays the remaining tape after backoff.

- `useLive(api, signal, input?)` on `okengine/client-react` — `{ events, latest, error, isConnected }`.

### 💥 Breaking Changes

#### Runtime

- Turning on `gate.auth.tenant` is fail-loud: SQL tables need `policy.tenant(...)` or `unscoped()`; KV prefixes keys; vault contracts default per-tenant; flows default `tenantScoped: true`. Tenant-role scopes never melt into the JWT.

- No-arg `http.*.live()`, `flow({ live: true })`, resource `.live()`, and Manifest `live: boolean` are gone. `live` is the signal name.

- `SignalBus.live()` is an `AsyncIterable` of `{ id, payload }` (not callback + unsubscribe). Duplicate `(signal, gates, match)` is **OKE1013**.

### ♻️ Changed

#### Runtime

- Client gzip budget is 4 kB (was 3 kB) so `api.live` SSE subscribe fits the published cap.

- Kernel edge gzip budget is 16 kB (was 15 kB) so Last-Event-ID resume (OKE1014 / 410) fits the edge encoder.

### 🐛 Fixed

#### Runtime

- Store-only `oke()` lazy-loads live SSE resume (OKE1014 / 410) so apps that never declare Signal stay under the 51 kB gzip cap.

- `autoResubscribe: true` waits with exponential backoff (500ms, doubling to 30s) before each reconnect so a closed SSE stream cannot tight-loop thousands of requests.

- `createClient(app)` types `.live(signal)` flows as subscribe (`onEvent`), not JSON RPC — `$routes` now carries `live` / `stream`.

- Store-only `oke()` lazy-loads the durable Flow runner so graphs that never run durable Flows stay under the 51 kB gzip cap after tenancy.

### 🔒 Security

- Built-in `oke_vault_secrets` enables RLS with `tenant_id = oke.tenant() OR tenant_id IS NULL` (same helper as domain tables). ENABLE without FORCE so the Vault adapter still sees every row; Console / `oke_app` cannot list another tenant's ciphertext. Global `NULL` rows stay visible.
