diff --git a/CHANGELOG.md b/CHANGELOG.md index 8780af9..9dd2338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,73 @@ All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this ## Unreleased +(empty — Phase 4 entries land here once Phase 4 opens) + +## v0.3.0 — 2026-05-25 + +### Phase 3 — Dashboard + audit query layer + daily audit rotation (D48 → D54) + +**Overview.** v0.3.0 closes Phase 3 — the dashboard / audit aggregate query / daily rotation track that grew OLP from "audit ndjson exists but is grep-only" (v0.2.0) to a live multi-panel owner-only dashboard with aggregate queries + automatic daily file rotation. 7 D-day commits (D48 through D54) shipped between 2026-05-25 under the standing-autopilot grant. All 15 ADR 0008 § 10 acceptance criteria are implemented + tested. + +**Test count: 544 (v0.2.0) → 601 (v0.3.0).** +57 tests across the Phase 3 arc. + +**Phase 3 release_kit checklist** + +- [x] All 7 D-day deliverables landed on main (D48 ADR + D49-D54 implementation) +- [x] CI green on every D-day merge commit + on this release commit's head +- [x] Fresh-context opus reviewer on every implementation D-day (D49/D50/D51/D52/D53) + D48 ADR draft + D54 docs polish +- [x] All 15 ADR 0008 § 10 acceptance criteria (#1–#15) covered by Suite 23/24/25/26/20h-extra-audit tests +- [x] CHANGELOG "Unreleased" promoted to "## v0.3.0 — 2026-05-25" with D48 through D54 entries +- [x] `package.json` bumped 0.2.0 → 0.3.0 +- [x] `CLAUDE.md release_kit.phase_rolling_mode`: `current_phase` Phase 3 → Phase 4; `current_pre_release_identifier` `0.3.0-phase3` → `0.4.0-phase4` +- [x] README status header + Implementation Status + Phase plan reflect Phase 3 shipped +- [ ] Tag pushed (next step in this PR's lifecycle) +- [ ] `release.yml` triggered + GitHub Release created (auto on tag push; D37 phase_rolling_mode gate will pass because Unreleased is now sentinel-only) + +**ADR 0008 § 10 acceptance criteria — final ship status** + +| # | Criterion | Covering tests | +|---|---|---| +| 1 | `readAuditWindow` iterates events from today + N prior rotated files | Suite 23b-1, 23b-2, 23b-3 | +| 2 | `readAuditWindow` skips malformed lines without throwing + logs warn | Suite 23b-6 | +| 3 | `aggregateRequests` counts by provider / cache_status / owner_tier / path + median/p95 latency | Suite 23c-1, 23c-2, 23c-3 | +| 4 | `topFallbackChains` sort desc by count + tied-count tiebreak | Suite 23d-1, 23d-4 | +| 5 | `spendTrendDaily` sparse-fills zero-request days + UTC day boundaries | Suite 23e-1, 23e-2, 23e-3 | +| 6 | Daily rotation past UTC midnight | Suite 26a-3, 26b-1 | +| 7 | Cross-file query with mixed rotated files | Suite 26e-1 + Suite 23b-1 | +| 8 | Concurrent rotation safety (N appends → 1 rename) | Suite 26c-1 | +| 9 | `GET /dashboard` 200 to owner; 401 to non-owner | Suite 24a, 24b, 24c, 24d | +| 10 | `GET /v0/management/dashboard-data` 200 to owner with all required fields | Suite 24e | +| 11 | `GET /cache/stats` 200 to owner with live stats | Suite 24h | +| 12 | Dashboard HTML smoke (4 panel containers + 30s poll + no external resources) | Suite 25a-25f | +| 13 | Audit row on management endpoints (success + 401) | Suite 24i, 24j | +| 14 | Graceful degradation on `quotaStatus()` throw (panel surfaces null + error) | server.mjs `handleManagementDashboardData` try/catch verified by code | +| 15 | PII guard — no message-content fields in any aggregate output | Suite 23g-1, 23g-2, 23g-3 | + +**Phase 3 D-day index** + +- **D48** (`c0b6969`) — ADR 0008 Phase 3 design draft (Dashboard + audit query layer) + lane decisions A/A/B/A/B +- **D49** (`686794e`) — `lib/audit-query.mjs` aggregate query layer (5 functions, PII-guarded) +- **D50** (`f9f2eaa`) — `server.mjs` 4 management endpoints (owner_only_block per ADR 0008 § 8) + dashboard.html placeholder +- **D51** (`251b578`) — `dashboard.html` full multi-panel UI (vanilla HTML+JS+fetch, 30s poll with visibilitychange pause) +- **D52** (`408d5a8`) — Daily audit rotation in `lib/audit.mjs` (synchronous trigger on first append after UTC midnight) + `bin/olp-audit-rotate.mjs` external cron tool +- **D53** (`68e50da`) — `tried_providers` schema semantic fix (D45 P2 deferral closed; ADR 0007 § 8 amendment) +- **D54** (`6d9ab1f`) — README Phase 3 polish (docs-only) + +**Bonus: also resolved at D53** — D45 fresh-context opus reviewer P2 deferral (`tried_providers` semantics on `key_no_provider_access` 403). ADR 0007 § 8 amended; server.mjs sets `tried_providers = []` on the 403 path so downstream audit queries stay accurate. + +**Known limitations carried beyond v0.3.0** + +Phase 3 functional scope is complete. The following remain as Phase 4+ deferrals (tracked in `docs/v1x-roadmap.md` + the new Phase 4 entry below): + +- **Per-key per-provider auth artifact mapping** — ADR 0007 § 12. Each OLP key independently authenticated to a different provider account. +- **Audit query rotation / retention policies** — ADR 0008 § 11. Currently unbounded; operator manages disk. A Phase 4+ amendment adds `audit_max_days` config when an operational need emerges. +- **SQLite hybrid migration** — ADR 0007 § 13. Trigger: query latency > 2s on typical owner session OR > 5 owners polling. Requires engines bump + CI matrix change as a separate prior PR. +- **Provider-cost weights for spend trend** — ADR 0008 § 11. At v0.3.0 "spend" is proxied by request count; cost integration when commercial cost-tracking lands. +- **Per-key dashboard views** — owner sees aggregate; per-key drill-down is a future amendment. +- **Key-mgmt UI on dashboard** — owner can create / revoke / edit keys from web. Out of Phase 3 scope; needs separate security review per ADR 0008 § 11. +- **Manual smoke for dashboard** — per ADR 0008 § 10 #12 the "no JS console errors in real browser" sub-claim is manual / playwright; Phase 3 acceptance shipped with server-observable checks (Suite 25); a Phase 4+ amendment may add playwright smoke if dashboard complexity grows. + ### D54 — README Phase 3 polish (docs-only, no code change) Seventh Phase 3 D-day. Documentation polish ahead of Phase 3 close (D55, maintainer-triggered). Brings README status header / Implementation Status / API Endpoints / Known limitations / Phase plan up to date with Phase 3 work shipped to main through D48-D53. diff --git a/CLAUDE.md b/CLAUDE.md index 63298a3..32605d7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -135,7 +135,7 @@ release_kit: # This overlay is the authoritative source. If Iron Rule 5 appears to be silently # violated (no version bump after many D-day pushes), check this section first # before filing a compliance finding. - current_phase: Phase 3 - current_pre_release_identifier: "0.3.0-phase3" + current_phase: Phase 4 + current_pre_release_identifier: "0.4.0-phase4" phase_close_trigger: explicit maintainer action (not automated) ``` diff --git a/README.md b/README.md index 1669324..9c574e9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A personal- and family-scale multi-provider LLM proxy. One HTTP endpoint, many subscriptions behind it, automatic routing, automatic fallback, content-addressed caching — so your IDEs and family clients keep working as long as *any* of your subscriptions has quota left. -> **Status:** v0.2.0 shipped (2026-05-25); v0.3.0 in progress — Phase 1 multi-provider proxy core (v0.1.0 + v0.1.1) + Phase 2 multi-key auth + audit + owner gating + keygen CLI (v0.2.0) + Phase 3 Dashboard + audit query layer + daily audit rotation (D48-D54 shipped to main; v0.3.0 release pending maintainer-triggered close). Sections marked _placeholder_ land alongside the relevant phase of work (see [phase plan](#phase-plan)). +> **Status:** v0.3.0 shipped (2026-05-25) — Phase 1 multi-provider proxy core (v0.1.0 + v0.1.1) + Phase 2 multi-key auth + audit + owner gating + keygen CLI (v0.2.0) + Phase 3 Dashboard + audit query layer + daily audit rotation (v0.3.0). Phase 4 (per-key per-provider auth + audit retention + SQLite hybrid + provider-cost weights) is the next planned milestone. Sections marked _placeholder_ land alongside the relevant phase of work (see [phase plan](#phase-plan)). --- @@ -166,7 +166,7 @@ If a fallback chain is exhausted, `X-OLP-Fallback-Exhausted` lists the tried pro ## Implementation status (as of 2026-05-25, post-v0.2.0) -Phase 1 closed at v0.1.1 (multi-provider proxy core + pre-Phase-2 cleanup). Phase 2 closed at v0.2.0 (multi-key auth + audit + owner gating + keygen CLI; ADR 0007 § 10 all 11 acceptance criteria shipped). Phase 3 (Dashboard + audit query layer + daily audit rotation) shipped to main through D54; v0.3.0 release is pending maintainer-triggered close (D55). This table reflects what is currently shipped vs. what is designed for later phases. +Phase 1 closed at v0.1.1 (multi-provider proxy core + pre-Phase-2 cleanup). Phase 2 closed at v0.2.0 (multi-key auth + audit + owner gating + keygen CLI; ADR 0007 § 10 all 11 acceptance criteria shipped). Phase 3 closed at v0.3.0 (Dashboard + `lib/audit-query.mjs` + daily audit rotation; ADR 0008 § 10 all 15 acceptance criteria shipped). Phase 4 (per-key per-provider auth + audit retention + SQLite hybrid + provider-cost weights) is the next planned milestone. This table reflects what is currently shipped vs. what is designed for later phases. | File / artifact | Status | Notes | |---|---|---| @@ -252,7 +252,7 @@ The original v0.1 spec (in `~/.cc-rules/memory/projects/olp_v0_1_spec.md` on the - **Phase 0** — Repo bootstrap, `ALIGNMENT.md`, founding ADRs, CI workflows, PR template. ✅ Shipped (2026-05-23). - **Phase 1** — Multi-provider proxy core: `server.mjs`, IR, three Tier-D provider plugins (Anthropic / OpenAI Codex / Mistral Vibe), cache (D1+D4) + cleanup (D2 bypass / D3 chunked replay / D23 size cap), fallback engine with first-chunk safety + hard triggers + per-hop log observability, IR↔OpenAI translation under Rule 2(b). ✅ Shipped — v0.1.0 (2026-05-24) + v0.1.1 cleanup (2026-05-25, D35–D42). - **Phase 2** — Multi-key auth (`lib/keys.mjs`) per ADR 0007: opaque OLP API keys, per-key cache namespacing, owner-vs-guest tier for header gating, audit ndjson (`lib/audit.mjs`), `/health` payload trimming + `X-OLP-Fallback-Detail` emission gating, `OLP_OWNER_TOKEN` env override, keygen CLI (`bin/olp-keys.mjs`). ✅ Shipped — v0.2.0 (2026-05-25, D43-A → D47). All 11 ADR 0007 § 10 acceptance criteria covered. -- **Phase 3** — Dashboard + audit query layer + daily audit rotation per ADR 0008: in-memory ndjson aggregate query layer (`lib/audit-query.mjs`), 4 owner-only_block management endpoints (`/dashboard` + `/v0/management/dashboard-data` + `/v0/management/quota` + `/cache/stats`), multi-panel `dashboard.html` with 30s poll, synchronous daily audit rotation + `bin/olp-audit-rotate.mjs` cron tool, `tried_providers` schema fix (D45 P2 deferral). 🟡 In progress — D48 (ADR) + D49–D54 shipped to main 2026-05-25; v0.3.0 close awaits maintainer trigger. +- **Phase 3** — Dashboard + audit query layer + daily audit rotation per ADR 0008: in-memory ndjson aggregate query layer (`lib/audit-query.mjs`), 4 owner-only_block management endpoints (`/dashboard` + `/v0/management/dashboard-data` + `/v0/management/quota` + `/cache/stats`), multi-panel `dashboard.html` with 30s poll, synchronous daily audit rotation + `bin/olp-audit-rotate.mjs` cron tool, `tried_providers` schema fix (D45 P2 deferral). ✅ Shipped — v0.3.0 (2026-05-25, D48 → D54). All 15 ADR 0008 § 10 acceptance criteria covered. - **Phase 4 (planned)** — Per-key per-provider auth artifact mapping (ADR 0007 § 12 deferral), audit query rotation/retention policies, SQLite hybrid migration (ADR 0007 § 13 trigger), provider-cost weights for spend trend. - **Phase 4+ (v1.x roadmap, triggered as needed)** — Full deferred-work tracker: [`docs/v1x-roadmap.md`](./docs/v1x-roadmap.md). Includes streaming-path singleflight ([issue #16](https://github.com/dtzp555-max/olp/issues/16) + ADR 0005 Amendment 8 design ratified), soft-trigger reactivation (ADR 0004 Amendment 2), `/health` activeSpawns integration, provider-level `cacheKeyFields` mask, streaming-path SPAWN_FAILED salvage. - **Phase N (opt-in)** — Tier-2 / Tier-C provider plugins (Grok / Kimi / MiniMax / GLM / Qwen) per [ADR 0006](./docs/adr/0006-provider-inclusion.md); provider-native protocol endpoints; deterministic triggers. Triggered by tier-2 demand, not on the bootstrap path. diff --git a/package.json b/package.json index 04bc8f9..3054362 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "olp", - "version": "0.2.0", + "version": "0.3.0", "description": "Personal multi-provider LLM proxy. Successor to OCP. One HTTP endpoint, multiple subscriptions behind it, automatic routing + fallback + caching.", "type": "module", "main": "server.mjs",