fix(config): preserve raw config.yaml fields when saving dashboard changes#165
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes a regression in the dashboard config save flow where rewriting config.yaml from the reduced /config JSON response could silently drop YAML-only fields (e.g., host/port). The new flow fetches and parses the current config.yaml, applies only dashboard-managed changes, and writes back merged YAML; it also surfaces YAML parse failures as actionable errors.
Changes:
- Added a
config.yamlparse/merge helper (parseConfigYaml/mergeConfigYaml) based onjs-yaml. - Updated
/dashboard/configsave logic to use the rawconfig.yamlas the merge base (instead of/configJSON). - Added focused unit tests for the YAML merge helper.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| dashboard/src/lib/config-yaml.ts | Introduces YAML parse + merge utilities used to preserve YAML-only fields during dashboard saves. |
| dashboard/src/lib/tests/config-yaml.test.ts | Adds tests validating that the merge preserves omitted YAML fields and works from an empty file. |
| dashboard/src/app/dashboard/config/page.tsx | Switches YAML save flow to fetch/merge raw config.yaml and improves surfaced error messages. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return {}; | ||
| } | ||
|
|
||
| return parsed; | ||
| } catch (error) { | ||
| const message = error instanceof Error ? error.message : String(error); |
There was a problem hiding this comment.
parseConfigYaml returns {} when the YAML parses successfully but the root value is not a mapping (e.g., a list, scalar, or null). On save, this would treat an existing non-empty config.yaml as empty and can silently overwrite it, losing data. Consider throwing a parse/shape error when rawYaml is non-empty and the root is not an object (with an actionable message like “expected a mapping at the document root”).
| return {}; | |
| } | |
| return parsed; | |
| } catch (error) { | |
| const message = error instanceof Error ? error.message : String(error); | |
| throw new Error("Invalid current config.yaml: expected a mapping at the document root"); | |
| } | |
| return parsed; | |
| } catch (error) { | |
| const message = error instanceof Error ? error.message : String(error); | |
| if (message.startsWith("Invalid current config.yaml:")) { | |
| throw new Error(message); | |
| } |
| expect(merged).toContain("host: ''"); | ||
| expect(merged).toContain("port: 8317"); | ||
| expect(merged).toContain("auth-dir: ~/.cli-proxy-api"); | ||
| expect(merged).toContain("debug: true"); | ||
| expect(merged).toContain("enable: true"); |
There was a problem hiding this comment.
These assertions depend on the exact YAML string formatting produced by js-yaml (quotes, ordering, spacing), which can change across versions/options and make the test flaky. A more robust approach is to parse merged back with js-yaml and assert on the resulting object shape/values (including that omitted fields are still present).
| describe("mergeConfigYaml", () => { | ||
| it("preserves fields omitted from /config JSON such as host and port", () => { | ||
| const rawYaml = [ |
There was a problem hiding this comment.
The PR description mentions surfacing invalid YAML as a specific parse error, but the test suite doesn’t currently cover the invalid-YAML path (e.g., mergeConfigYaml throwing with the expected message prefix). Adding a focused test for malformed YAML would prevent regressions in that UX improvement.
- parseConfigYaml: throw on non-object YAML root instead of silently
returning {} (prevents data loss when config.yaml has unexpected
structure)
- executeSave: only reset dirty state when all saves succeed so the
form stays dirty on partial failures and the user can retry
- auth-dir guard: use key-presence check instead of truthiness to
avoid overwriting intentional empty-string values
- config-yaml tests: expand from 2 to 13 covering invalid YAML,
non-object root, array replacement, null handling, new-key addition
itsmylife44
left a comment
There was a problem hiding this comment.
Code Review — PR #165: config.yaml roundtrip fix
Overview
The core approach is sound — fetching raw YAML, parsing, merging only changed fields, and writing back preserves untouched fields that the /config JSON endpoint doesn't serialize. Good fix for a real data-loss regression.
🔴 BLOCKER (1)
1. parseConfigYaml() silently returns {} for non-object YAML roots — data loss risk
config-yaml.ts:15-18 — If config.yaml contains valid YAML but the root is not a mapping (e.g. a YAML array [] or scalar "oops"), parseConfigYaml silently returns {}. Then mergeConfigYaml writes back only the changed fields, effectively destroying the entire original config.
For a PR whose purpose is "preserve untouched YAML fields," this is still a silent data-loss path.
Fix: Throw an error instead of returning {}:
if (!isPlainObject(parsed)) {
throw new Error("Invalid current config.yaml: root value is not a YAML mapping");
}Also: move the isPlainObject check outside the try/catch to avoid double-wrapping the error message ("Invalid current config.yaml: Invalid current config.yaml: ...")
🟡 IMPORTANT (3)
2. executeSave() resets dirty state even on partial save failure
page.tsx:398 — setOriginalConfig(config) runs unconditionally after the save loop, even when errors.length > 0. This means if YAML fetch fails or YAML PUT fails, the toast shows an error but the form is no longer "dirty" — the user loses visibility that some changes weren't persisted and can't retry via the Save button.
Fix: Only reset state when all saves succeed:
if (errors.length === 0) {
setOriginalConfig(config);
setRawJson(JSON.stringify(stripOAuthIds(config), null, 2));
}3. auth-dir guard uses truthiness, not key presence
page.tsx:359 — !liveConfig["auth-dir"] is a truthiness check. If auth-dir is intentionally set to empty string "", it's treated as "not present" and gets overridden with "~/.cli-proxy-api".
Fix: Use in operator:
if (liveConfig && !("auth-dir" in liveConfig) && !("auth-dir" in yamlChanges)) {4. Test coverage too narrow for a data-integrity function
Only 2 happy-path tests. Missing:
- Invalid YAML syntax → throws
- Non-object YAML root → throws (the blocker above)
- Array values are replaced wholesale, not merged
nullvalues round-trip correctly- New keys added to existing YAML
🟢 NIT (2)
5. yaml.load() default schema is safe in js-yaml v4
!!js/function etc. were removed from the default schema in v4. No action needed, but CORE_SCHEMA would be a hardening option if desired.
6. Merge is 1-level deep only
Sufficient for current config shapes, but worth documenting. If nested objects gain sub-keys edited independently in the future, this will need recursive merge.
✅ What's good
- The raw-YAML-based merge approach correctly solves the original regression
getErrorMessage()helper improves error surface area over generic strings- YAML parse errors now produce actionable messages
- The
auth-dirpersistence guard is a good defensive measure
Fix commit available
I've pushed the fixes to branch fix/config-yaml-roundtrip on origin (commit 7c307e0):
- parseConfigYaml throws on non-object root
- executeSave only resets dirty state on success
- auth-dir guard uses key-presence checks
- Tests expanded from 2 → 13 (parseConfigYaml + mergeConfigYaml edge cases)
All 13 config-yaml tests pass, build succeeds (71 pages, 0 errors).
🤖 I have created a release *beep* *boop* --- ## [0.1.68](dashboard-v0.1.67...dashboard-v0.1.68) (2026-04-06) ### Features * update to OhMyOpenAgent with presets, advanced options, and config management ([#164](#164)) ([ae80424](ae80424)) ### Bug Fixes * **build:** make clean-checkout dashboard builds reproducible ([#167](#167)) ([bd79d3b](bd79d3b)) * **config:** preserve raw config.yaml fields when saving dashboard changes ([#165](#165)) ([44b07c9](44b07c9)) * **lint:** align eslint tooling and clear dashboard warnings ([#168](#168)) ([0f582d9](0f582d9)) * **oauth:** use manual launch flow when incognito mode is enabled ([#166](#166)) ([2bc8566](2bc8566)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
:robot: I have created a release *beep* *boop* --- ## [0.1.73](https://github.com/itsmylife44/cliproxyapi-dashboard/compare/dashboard-v0.1.72...dashboard-v0.1.73) (2026-04-12) ### Features * add admin force logout all users control ([012b8ee](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/012b8ee0ac23e7aa1b00d118475d232175f0b13d)) * add auto-update popup notification for admins ([dc3ade7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/dc3ade741233edc2a6e83bbac6205bae7c1954b7)) * add auto-update popup notification for admins ([77ac83d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/77ac83dcb0d7fd56a21ec2b2fdb240b638036422)) * add client-side pagination to logs page ([e61b268](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e61b268da95837d0c7dc022e8c5ba78833d8cf9b)) * add CLIProxyAPIPlus, Copilot and Kiro providers support ([6dc06a0](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6dc06a078777de94a7f8c30c4259b168a9fdccf8)) * add Copilot quota tracking and improve model grouping by provider ([01dcb6f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/01dcb6f5cbecd0859bbee0041377d83da383fa47)) * add dashboard deployment via webhook from admin settings ([0da0cfa](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0da0cfa67a5b7a117b2f55094c1ca619f0db0621)) * add dashboard UX improvements and Telegram quota alerts ([#108](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/108)) ([6ec4da7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6ec4da766e51fb8893ee55896069aaabfca1ad77)) * add estimated cost tracking per model in Usage Analytics ([#175](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/175)) ([081fe04](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/081fe042f521878e9e6ba3e018466c9cf69db653)) * add fullscreen update overlay with progress animation and auto-reload ([#97](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/97)) ([0248de2](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0248de28e057a0c5d47a828ca97da92717e68ee3)) * add get-status.sh and get-log.sh helper scripts for webhook ([c7bba14](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c7bba149c7ca862f026425f3f59d3c6c4c82382a)) * add global-error boundary and metadata title template ([54657d2](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/54657d2901b3a303a97e72ceba8146ac94341e27)) * add iFlow, Kimi, and Qwen OAuth provider support ([3e83485](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3e83485b51583ae1a83fd2b719581f2bf2da8cc8)) * add iFlow, Kimi, and Qwen OAuth provider support ([68ea9b4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/68ea9b4b6ca76e02d2c9b5ea72d0ae250ade4aaf)) * add Kimi quota support and update provider docs ([ca3cf4d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ca3cf4daf51a03f1d8a0f6e246aee58b4f9c18ed)) * add local setup for macOS/Windows/Linux via Docker Desktop ([14eadcc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/14eadcc320d9cec2480e589942d0289538ef9f3c)) * add local setup for macOS/Windows/Linux via Docker Desktop ([#36](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/36)) ([27bb36a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/27bb36acc7fb8190c28c4a6453da110d4fe4112f)) * add logs viewer from PR [#1](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/1) ([b5c2bf5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b5c2bf50db7cdaa72ad299133f3a77b43bc643ac)) * add missing Perplexity Pro web UI models to sidecar ([b606493](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b6064930d3b860bfb08cde95285e587294ff3554)) * add model auto-discovery for custom providers ([#32](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/32)) ([ffc0a9b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ffc0a9b5c72b5378d8db74bddaa856ec2943e5f3)) * add multi-arch Docker build (amd64 + arm64) for Apple Silicon support ([61d455c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/61d455c4d9918c9ff11da91fd3137de3c1897edc)) * add OAuth account enable/disable toggle ([d6ad7ef](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d6ad7ef4c2af78ff396b807a1230e1a6a410fc4e)) * add OAuth health status badges and fix alias model override priority ([ce1084a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ce1084ac24c6b09359505f88c936c5c6e6da34f9)) * add oh-my-opencode-slim support with variant toggle ([#143](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/143)) ([152dc42](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/152dc42e682f81eca90a1016ec18c1cffa544175)) * add optional webhook deploy service installation to install.sh ([ea73737](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ea7373761b80f87eeee4c40e0633f578f298f5a7)) * add Perplexity Pro sidecar with dashboard cookie management ([#54](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/54)) ([69fc1a5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/69fc1a5ebf6bfe5060a76aa1e7c8f5ee8bc25d78)) * add persistent dashboard header with live status pulse and user panel ([#99](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/99)) ([46c86de](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/46c86de4e806a575a023441cefdcd873bf56f421)) * add persistent usage tracking with per-user views and time filters ([5cf088e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5cf088ec26033d0806136887f742c4047b82e2f4)) * add provider group management and priority ordering ([#84](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/84)) ([a2d540b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a2d540b88f276e3623917bb7559b33b2f314be2b)), closes [#78](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/78) * add provider key naming, fix OAuth ownership registration and ID anonymization ([ac5a28b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ac5a28b43c153fbacd78ab2c193e4f0b3bd74696)) * add qwen and iflow oauth provider support ([b3fafeb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b3fafeb35044228fd2cbac8af2ff51d390e1d9ce)) * add qwen code and iflow oauth provider flows ([4f5ab3c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4f5ab3c2b3d89b270fdca289db46194986db7701)) * add real Kimi quota tracking via /v1/usages endpoint ([26523e8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/26523e818fdbfb58daecc253098e3c206ffcadb7)) * add real Kimi quota tracking via /v1/usages endpoint ([1905012](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/1905012c0f03a27c6d98e5ee07a6d6d7561b0a46)) * add recharts visualizations to dashboard pages ([#106](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/106)) ([850b389](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/850b389c30d6c431e7e7ccd3ec33f48beb9f0d11)) * add separate proxy update notification component ([21627df](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/21627df6de73d90f3325271ea186bebb15fd1b81)) * add server-side session revocation with sessionVersion ([4e75221](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4e752212a0081fa38910d815f05f443d97d1046f)) * add server-side session version revocation ([317ae1e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/317ae1e4c8be9533c8a408c2f0adccea26d0455f)) * add setup wizard with inline forms and sequential step locking ([12e597b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/12e597b14dc6cdef48cf63aea5e3b086bee22eea)) * add variant, temperature, prompt_append, description to agent/category configs ([54e1a5f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/54e1a5f1f4b1ff213e1fc30dc1c425b35e57e144)) * add Windows PowerShell dev-local script for local development ([6e812bb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6e812bb5865b0a9a55128060b85a37384c1d7412)) * allow non-admin users to view their own usage stats ([6fc67a3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6fc67a3fdf6437c11c3dca510674ed8101543ea2)) * **api:** add custom provider CRUD endpoints ([1379c57](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/1379c577ab9ca4144854539357b8ee2814320907)) * **api:** add usage collector endpoint with deduplication ([82dbe87](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/82dbe87bc68f0549644dfafab21abb0bf2d84bd5)) * **api:** add usage history query endpoint with time filters and role-based access ([5e8207c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5e8207ca07a96a73ad794fe5e4f32908f1af034e)) * **api:** expose background sync failures to users ([aeccd5f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/aeccd5fc6458e8c24e5e27e587d922d310b0383b)) * **api:** standardize error response format ([6b333dc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6b333dcb41c3827ae6175e08bb54f9451d845373)) * apply advanced Tailwind CSS layout techniques across dashboard ([72c3673](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/72c3673e75abdf32a19f85d8a91e9643629b39be)) * **config:** add environment variable validation ([b21b630](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b21b630f6c8198ec01cd2ba08fe5c72a787d2fab)) * **config:** add proxy-url validation and emergency recovery ([797fb6c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/797fb6c8d033388b07b86c21522855c0b82ef375)) * **config:** include custom providers in config generators ([86b9106](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/86b9106f7383ce73979f25d6fa844d5ef9f7dbf9)) * **config:** restart CLIProxyAPI container after saving config ([5f5c7ac](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5f5c7ace22a8ab408d2a5b73fd900e089537ee25)) * Dashboard deployment via webhook from admin settings ([579acb4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/579acb4e9e962d1527c5e80c52d8ada9c3e9e6f1)) * **db:** add ConfigTemplate and ConfigSubscription models for config sharing ([beda365](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/beda36544e5ac430fdbb19e6b15819f2545b869f)) * **db:** add custom provider schema with model mappings ([633cf60](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/633cf603c9544365a99ee83ce4020bea7db53e2b)) * **db:** add custom provider tables to entrypoint schema ([38e6c49](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/38e6c49391ca290046f7daead7df2382bed903cd)) * **db:** add custom providers migration and update dev-local.sh ([2ce880a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2ce880a999e9a62da591340261d132a4fa8df4e9)) * **db:** add UsageRecord and CollectorState models for persistent usage tracking ([3a3cf37](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3a3cf37d97d13b83a876b32c780f6e562c8be49e)) * **design:** migrate dashboard to modern light design system ([802af62](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/802af62cdb73462e55c39c8bfdb171c6f0f76805)) * **dev:** add SKIP_AUTH=1 bypass for UI-only testing ([72a4262](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/72a4262655d63ed1f6a546a5f15c235a4e911174)) * enable usage page for all users with input/output token breakdown ([d358c6a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d358c6a021fcddb7e2207eabc84322ecc660de76)) * encrypt custom provider API keys for auto-resync after proxy restart ([d194d0d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d194d0d844eef391c7ee9f00484e037bb0f59f2e)) * expose all CLIProxyAPIPlus config fields in dashboard ([#116](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/116)) ([77c3083](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/77c30837f8b42151aaca50f011a4ed0f0c55f166)) * **i18n:** add multi-language support with English and German ([#178](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/178)) ([4201006](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/42010064d32ea11b7ae97f6fa7a086f2e4244e04)) * improve settings and usage pages UI ([34e8670](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/34e867034590ddf587a8a16e6f57951d16173fda)) * **install:** auto-generate COLLECTOR_API_KEY and install usage collector cron job ([e46dcb1](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e46dcb136f70326477ed71e9e92894e246a765f2)) * **lib:** add share-code generation utility for config sharing ([df2b48f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/df2b48fe13d0f6aa822bb36a65d588206eda816b)) * make Perplexity Pro Sidecar opt-in during setup ([#160](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/160)) ([a6a52ad](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a6a52ad4f74905287f6dbcb15c1d58d59c3e7983)) * make Telegram check interval and cooldown configurable via settings ([f83eb1d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f83eb1dc85178ea310a5497c78f6550252b75c39)) * notification bell and latency indicator in header ([#130](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/130)) ([56d7196](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/56d719637c94196d6225601ecbbddb664be8dbe5)) * **observability:** implement structured logging with Pino ([22f4ef9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/22f4ef9a7f869895f58f121605a0f94aeb581a68)) * parse Codex quota into graphical progress bars instead of raw JSON dump ([7e55a3a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7e55a3a896e2becafb50d5466ba54212436e0352)) * per-user provider ownership, config sharing, and MCP type fixes ([986dadd](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/986dadd727f281e6b5aadafada682135ff7c5dfa)) * **perf:** add pagination to admin APIs ([080e02a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/080e02a6f572d0b20d6698d4de7671d33281e65d)) * **perf:** implement in-memory LRU cache for expensive operations ([f527103](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f527103a8636ba3786be1b8df75729749afded4d)) * provider-grouped quota aggregation with weighted availability formula ([f715ab4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f715ab4d454b218e71e751f5ed19e207fa26d0ad)) * **providers:** add Cursor and CodeBuddy OAuth provider support ([20eb8ae](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/20eb8ae328338113c6aec754a71848e3e967407a)) * **providers:** add Cursor and CodeBuddy OAuth provider support ([#147](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/147)) ([c0c2c96](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c0c2c96905626dac6c07f4e876b43ed7b65d0e09)) * **quota:** add model-first Antigravity snapshots with i18n ([#180](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/180)) ([404b354](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/404b3544d7a706a6c85764b2ecdea8651c56c7ac)) * **quota:** replace weighted average with per-window capacity bars and long-term priority display ([db537bb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/db537bb4676170ad3abe3d95f6d8bc083903b923)) * redesign MCP server management for complex configurations ([#79](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/79)) ([0021ebb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0021ebb4510af79ec0f00384b476c182191bbd9f)) * Release pipeline with GitHub Actions, GHCR, and Docker Socket Proxy ([#19](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/19)) ([37a1ea7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/37a1ea7629d721c93a5bdd266237dfba43d87f24)) * **reliability:** add timeout handling to AsyncMutex fetch calls ([cfe0c6c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/cfe0c6c6164b03fa135bb720b7ef90d4c350f9e3)) * reorganize quick start flows and assignment model selection ([d7a7c8a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d7a7c8a62e62129a5462c6091af5155cf9fd0d7e)) * replace GitHub API with version.json for update checks and show release notes inline ([#114](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/114)) ([cbb8eaa](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/cbb8eaa7b8858b4d84e6d222fdc078b92935bc7d)) * rewrite perplexity sidecar with auto model discovery and auto-update ([9c204ad](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/9c204ad910845924d49fe0684c22ac89f2cf8d65)) * **security:** add path traversal protection to management proxy ([d00f0d5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d00f0d587b7533a372f38ed420dea86597de7089)) * **security:** extend rate limiting to sensitive endpoints ([456bb70](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/456bb70dbe214ed0fde5a60caa1e5c2204620805)) * support importing local OAuth JSON credentials from dashboard UI ([#120](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/120)) ([cfd140c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/cfd140cca515e0f2adf0e87f9420734dd62cf475)) * switch to CLIProxyAPIPlus, add Copilot & Kiro providers, fix OAuth delete 403 ([#67](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/67)) ([00438e4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/00438e4c8ea8a06e5fc629cf9dc060e22f33ce37)) * **theme:** add browser verification harness and root theme bootstrap ([474a7fd](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/474a7fd7cd8aa721d3fb4dc67959a272eaa98386)) * **theme:** add toggle, theme-aware primitives, and chart adapter ([68e5537](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/68e5537a61c8390382f50d09c7a66ac45d021014)) * **theme:** convert all remaining shared components to CSS variable tokens ([7b54c07](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7b54c07d39db033662f0cf1b70ee427a1c0c239a)) * **theme:** convert all routes, loading skeletons, and system pages to dark mode ([4329209](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4329209075f12db3306704c4cb22958c8fb3f72a)) * **theme:** migrate chart consumers to useChartTheme hook, convert first batch of shared components ([c313611](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c3136115a78e9b64f55e795c939420463dfcf62d)) * **ui:** add custom provider management interface ([2446076](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2446076b60254aa913f1aa20a5eecdddbca288ae)) * **ui:** rewrite usage page with persistent data, time filters, and admin/user views ([15e55f8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/15e55f849d664d62829b95a3921ff95b83ffeffa)) * update to OhMyOpenAgent with presets, advanced options, and config management ([#164](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/164)) ([ae80424](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ae80424751f311322c55434384c6ddbdca78bb2a)) * **usage:** add COLLECTOR_API_KEY for external cron-based usage collection ([0e48a9b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0e48a9bd8c65d96c3bb0e53ec93d24d083988924)) * **usage:** add latency tracking to usage records and enhance dashbo… ([#138](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/138)) ([c56a657](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c56a6573413bcd860c7e072989f913a4c9c1f421)) * **usage:** deprecate live usage endpoint in favor of persistent DB tracking ([e9c5d35](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e9c5d350a3a233f0647cfb29bd88d2f72f689db8)) * use models.dev as source for model context/output limits instead of hardcoded heuristics ([81ffcc0](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/81ffcc0024b504b0fda98df7f14f17aa4eb92578)) * use pre-built GHCR images instead of local Docker builds ([73b487d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/73b487d90fad7e48129216f48984c6f5728701b8)) * use pre-built GHCR images instead of local Docker builds ([80d8807](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/80d8807eb0176125bc8927a8ce346ce4eaf7b8ff)) * **validation:** standardize input validation with Zod ([71f59e5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/71f59e5ee95eac4a7b8483aa3b712ed0ef81efd0)) ### Bug Fixes * abort config save if current config fetch fails to prevent data loss ([e2c4819](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e2c4819714d7fe24b641d077b24c8f2fc83a2bab)) * accept valid docker tags for proxy update versions ([4078831](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/407883189631384b0ff3253b44625d2906b2c715)) * add all management endpoints to proxy allowlist to unblock config saves ([27b9e8b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/27b9e8bc91839bb079360bd5bfa378dc3774ffec)) * add apiKeyEncrypted migration to entrypoint.sh and PROVIDER_ENCRYPTION_KEY to install.sh ([082362c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/082362c043ac009ad4d52c628a8091a51dc33d3b)) * add auth-dir default to prevent CLIProxyAPI crash on startup ([f598989](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f598989ce812f9e9d5656a41a7ae4d267ec1bf3b)) * add build-time env placeholders for Next.js validation ([79c29bc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/79c29bc2765e8c209c2b3d20fcf7be659a78f2ba)) * add CLIProxyAPI config.yaml generation and auth-dir for local setup ([b2c05d6](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b2c05d6f9013e0d1e1c997a1851e79aa3619b4bb)) * add Gemini CLI quota support to dashboard ([#127](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/127)) ([e3f6704](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e3f6704584c3aba512c54980bc6ae96b6899dbb9)) * add latencyMs column to usage_records in entrypoint migration ([c13f5d0](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c13f5d04107d232dd79219b3f9af84272ad2bb21)) * add LOG_LEVEL to install.sh env template ([8f6796b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/8f6796bd46946115ccfed15e5413b75c37562c15)) * add missing migrations to bootstrap scripts ([15b387e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/15b387ec9159a9c1581fd60f70a5837c7df68697)) * add missing tables to entrypoint.sh for existing installs ([dd5e2c9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/dd5e2c94dc7e6dcb062419d171f96247def3faa7)) * address Cubic code review feedback ([3214c1c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3214c1c7376e2bd886b648cdc95274c698707695)) * address Cubic code review findings ([a48765f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a48765f56048832fd9a878f0bab43172c869e51d)) * address diffray code review issues ([edb15dc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/edb15dcc690b02926dee26a08e1c6814699fa7e9)) * address oracle review findings ([075b256](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/075b2560ae6b38af6ae13b2be229a5a84a8aed7f)) * address react-doctor findings to improve score from 84 to 94 ([174ec4b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/174ec4b3076eb2daa5bb40a84955555442db871f)) * address remaining Cubic review feedback ([5c4f66d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5c4f66d056ea9cd5cc1930a56140e100b6316a9e)) * address remaining diffray code review issues ([0a6a104](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0a6a104b0236d393d82a41430ad60c0fc080f696)) * address second Cubic review round ([7322596](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/73225961fbdcb49c2ac77bd25e68ddbd0ea08378)) * **agent-config:** dedupe and sort available model IDs ([11c6df4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/11c6df4e26a57c203d4298d68453a34d9f588ffc)) * allow http:// base URLs for internal Docker service providers ([e36ad15](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e36ad15a74c45ede58d1464f3f0c44617a217119)) * allow non-admin OAuth management read endpoints ([2e1e9f7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2e1e9f72c12a79975a8a5d9b703e73d9627e19f2)) * apply provider filter to charts and stats on quota page ([1b99157](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/1b99157fda2a48f917699ed316efefc07625ee50)) * avoid long blocking qwen oauth callback polling ([8483c80](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/8483c804362214b92cf6a42c70847721b3359efa)) * backend hardening — rate limiting, error standardization, security ([#122](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/122)) ([e2bed94](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e2bed948ef07d3d219e0170abdb9443e0704e9f3)) * bind all ports to localhost and write BOM-less UTF-8 .env on Windows ([920e2d5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/920e2d506962b3001bd311e85b0cd737edd36703)) * block SSRF redirect bypass in fetch-models endpoint ([#40](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/40)) ([bedaa7a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bedaa7abd66a233d792ae08be3f321b5a37f7ecf)) * **branding:** switch normal OMO naming to Open Agent ([28f30f1](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/28f30f1b8b0c08bcd279e03d6679ec1cc7aa7efa)) * **build:** make clean-checkout dashboard builds reproducible ([#167](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/167)) ([bd79d3b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bd79d3bc1a6980f263c6928f088e5b6e1a83c1f5)) * capture provider OAuth ownerships after successful callback ([268c412](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/268c41272916c06b5714881db4d16a41f3370811)) * **ci:** decouple tag-contributors from build pipeline ([d4914cd](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d4914cdc2d6164e61e6941b537346d16c605c416)) * **ci:** handle missing releases in tag-contributors job ([06b9941](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/06b994118d7a0ff16227155cd5e9c567fafb5025)) * **ci:** reliable Docker build trigger with output fallback and workflow_dispatch ([eb620c1](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/eb620c1c91bc5389e79f0f773cec1a689657a053)) * **ci:** reliable Docker build trigger with output fallback and workflow_dispatch ([035d979](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/035d979b8be7a53e0f108e6414e13cfc44411791)) * **ci:** use correct all-contributors-auto-action ([86770ea](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/86770ea3b5c47830effbaefcb0e2463c86d0fcf4)) * clarify uptime label as proxy uptime in dashboard header ([912cf7b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/912cf7b175cc675b00d9d23766108c9027e51197)) * Claude OAuth quota fallback — handle 429, update model, parse unified headers ([a06327e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a06327ee827df20797973c25549a2204475c5929)) * clean stale digests on self-hosted runner before export ([df10ecd](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/df10ecd23caeeade41441e10029547c6d3c10fb7)) * clear update state when auth fails or user is not admin ([ca46861](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ca468619b6945b92c05ca22b5d59956f02015c2d)) * collapse non-admin usage to single owned key when only one key exists ([09e89f8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/09e89f8447495d31b9f22bc2e9d61d0c34457711)) * **config-sync:** await lastSyncedAt update for subscribers ([fb5c282](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/fb5c2828310b1105842bba253a69c40d627d95f6)) * **config-sync:** use deterministic hash for stable version detection ([c303ee1](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c303ee176b05d7d7b2ecd2aa37631c495d951d0b)) * **config:** always persist auth-dir on config save ([#149](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/149)) ([18cf244](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/18cf2442c7556a41035d4eb7fba37a993b2d17bf)) * **config:** force-quote YAML strings to prevent special char issues ([5e7fa64](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5e7fa64e5b9db4a019b2ff6c3868c1e5b9562305)) * **config:** preserve raw config.yaml fields when saving dashboard changes ([#165](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/165)) ([44b07c9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/44b07c9d4de40559b10c4e70f8cc84dc2b89fca3)) * **config:** preserve unmanaged fields on save via GET-then-merge ([2565aca](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2565acac07e0f8eabb0337f179fceec2493476bf)) * **config:** retry on load failure and re-fetch after save ([5b0558d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5b0558dd03243f14f1c01fad11dd0dc57fb997f2)) * **config:** use deep merge to preserve nested unmanaged fields ([d8e1413](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d8e1413e8cb1c2fc7c16a88beac427cc81dd2578)) * connect logger to log-storage for UI display ([7d7636e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7d7636e8b8c405e749f2c5f2674f5dbb7b22a3ec)) * containers page responsive table layout ([e308ec3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e308ec350b15a3356c9f5b4c60d91b08ff8ebedf)) * correct custom provider re-save state and URL validation ([248764f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/248764f9eb4c7e726a60463a46739c972870ded6)) * correct foreground argument parsing in deploy script ([a096a64](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a096a646e360cd674c661040188710a4d4dac4de)) * correct model-to-provider heuristics and add missing provider mappings ([#87](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/87)) ([27d2df2](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/27d2df2af5b44105eb3c0d91bc89528f5f256ecc)) * correct plugin config paths and add OCX profile setup in Config Sync instructions ([14bd5a8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/14bd5a8f9170cf0845252ffa48a9c1ad816a8f9a)) * dashboard UI consistency - remove glassmorphism, standardize to blue/slate theme ([e3f8dfd](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e3f8dfdc1269bcb6cf0d8906ed05bd648cba9c1c)) * **db:** add slim_overrides column migration to agent_model_overrides ([4812b91](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4812b91959de20fe8d9ab3c897049818304dcdf6)) * deduplicate model IDs to prevent duplicate React keys in ModelSelector ([dca83b4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/dca83b4ae09aba3cd54606663ef2a8323ab483ff)) * deduplicate proxy models, suppress chart warnings, and fix 24h time format ([e41d27c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e41d27c231be545418c5f435839d7323f5b28a14)) * defer API_URL check to runtime so Docker build succeeds without env vars ([4c49853](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4c49853a5d7841df2dffbfd863873c5fca3fe0ce)) * disable quota group drilldown and lock turbopack root ([5612ba5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5612ba50c1c53f215d0a8a3a768e27a27ccb5033)) * **docker:** copy messages directory for i18n support ([d7298d5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d7298d51ca7c86e36652a458575ffc18cdc42ffd)) * eliminate Edge Runtime warnings by splitting instrumentation into Node.js-only module ([48a5bda](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/48a5bda8aee83650e206b6a46cba4a7faab703c7)) * eliminate fetch response leaks and clear dashboard lint blockers ([#65](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/65)) ([ce5fc17](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ce5fc175b153b2de4fde461808c9dd9754c339f9)) * enable NETWORKS in docker-socket-proxy for container update flow ([054275f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/054275f0dfec697db3678481b8bbe947c6511cb1)) * enforce admin-only system actions and handle null provider keys ([283b599](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/283b599f783b9a31ddf8e78eb32a8aa9e46e9b59)) * ensure DEFAULT_PLUGINS used when no saved plugins exist ([f775903](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f775903b6477b3ab7f2f48dc35ccaf83ed5616bf)) * ensure first model selection change triggers autosave ([6d350f8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6d350f83673d2a5ba749d8ac67f5bb1588d985f9)) * explicitly pass API_URL and DASHBOARD_URL to dashboard container ([3baaf53](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3baaf5375354628370f5c73e82336bcfceadcec1)) * fallback proxy update when compose is unavailable ([84c675f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/84c675fa714536fdc052a529f22510226f9bb8dd)) * filter usage page to only show dashboard-generated API keys, exclude OAuth auth-file indices ([d2a9ad6](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d2a9ad6f85cfe320cee5ae343824746f6d8c03aa)) * filter usage to dashboard API keys only, add quota cache (2min TTL) and handle Claude 429 rate limits ([d329a3b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d329a3bacd6ef02a2bc694a6b78d041d5aef9993)) * generate URL-safe postgres password in install flow ([be8e5bc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/be8e5bc642f31b7421b6e007e57c735870551435)) * group usage by API key instead of endpoint ([64be3a3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/64be3a3cc14eb6593601587e7c7762e06836be6c)) * handle 'completed'/'failed' status values from deploy script ([f086739](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f0867393d0dae3734d1900bc17b04868a78a30fa)) * handle dashboard-v prefix in semver parsing for release tags ([8dc88ce](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/8dc88ce7b068ea5db102bf6ba01c0ad3f5f0f15c)) * handle Kiro device_code OAuth flow without initial URL ([4e219cc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4e219cc952444bc0040a5812188cd7d81c9d4d97)) * harden collector concurrency and reduce proxy/dashboard load ([#81](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/81)) ([e6c2d6a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e6c2d6a7259470c1efeb4305646168930cc070e6)) * harden cost estimation component ([f505d15](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f505d15f2f42113d92cad963a1568e2d27080855)) * harden Docker setup with security and resource improvements ([71dae30](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/71dae30549128222add769ed0b071287af208477)) * **health:** use GET instead of HEAD for proxy healthcheck ([#63](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/63)) ([ca90255](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ca9025523157225b6de4c98c2b9a8813de4f7a0c)) * **health:** use proxy root endpoint instead of /v0/management for healthcheck ([#61](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/61)) ([50ab3e3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/50ab3e3cc97abe5791f4f5ccfbef5bdc18ec04d2)) * ignore null quota fractions in capacity calculations ([87ed48a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/87ed48a3cc408e9cfa2802c44fbb533bf648f3b6)) * improve dashboard UX with tooltips, consistent spacing, and proper navigation ([c2f056a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c2f056a8dff33d724fde7ad72e6129f9259b834c)) * improve PostgreSQL password auth error handling and documentation ([#135](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/135)) ([1dbed04](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/1dbed043fd32079bdc45fbec6b390f744cbb9b78)) * improve resilience and UX across dashboard ([16ea6e1](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/16ea6e1a2f2d60ec81db8bd24f40c77197a2a443)) * improve stale lock detection in deploy script ([9f1d9de](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/9f1d9de6573306b71f27f191fbc8a78064b2d082)) * include custom provider models in agent assignment model selector ([#155](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/155)) ([5369dd3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5369dd37a22c212a2855e9b4c7c3ffdedcb859d3)) * include custom provider models in generated config bundle ([6584815](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/65848158891ab3f27afd1f30510603903f6444c3)) * include docker-proxy in install script and deploy flow ([c5478bf](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c5478bfdee63318b02da7ae75e3099febe9a1967)) * include sessionVersion schema updates in bootstrap scripts ([44d2306](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/44d2306805b1f261248cfc20e20387a7d32d40fe)) * include user source matching in non-admin usage filter ([9170de3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/9170de304eb76a54f775de512bd648f9caa96730)) * increase CLIProxyAPI wait timeout to 60s for cold starts ([0417b74](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0417b744caa8ee7e4847ec120ea292417b7ca124)) * increase GitHub API cache TTLs to avoid rate limiting and remove duplicate password change ([32aaa30](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/32aaa300f296677dfb25f961e6eadc003611c9bc)) * **install:** avoid unbound CADDY_MODE when skipping Caddy auto-apply ([d2e4b47](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d2e4b47bd7877801872c840c146c0a01c86ee4b7)), closes [#102](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/102) * **install:** use public dashboard URL for collector cron in default mode, localhost only for external-proxy ([5f35104](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5f351041b14a43491dd61bb4a00ad231bc832115)) * keep proxy updates and dashboard deploy compose-managed ([1ea7abd](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/1ea7abd651b07ea01dd7a3f8c0af0b7c72950057)) * **lint:** align eslint tooling and clear dashboard warnings ([#168](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/168)) ([0f582d9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0f582d9da005aba9825b3b9c35d551652d694b1c)) * **lint:** remove unused params and replace unsafe management any types ([bcf7e68](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bcf7e683d6198d68f1e59b1bac245ac28f109b08)) * logger now stores logs in both dev and prod mode ([f616587](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f61658757e2f09ecf486e1a63d79e7502bc163ea)) * make PROXY_URL configurable via CLIPROXYAPI_PROXY_URL env var ([3f033c5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3f033c5835ca8ad99d297a9e400440c0c394f8a7)) * match github-copilot provider name for Copilot quota tracking ([d0e127d](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d0e127d4c9d35d4a3fd382992d334aaabe32cdd1)) * match non-admin usage by oauth source identifiers ([73fd4a7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/73fd4a7ff0d14758e32ecdededeb494d69d84223)) * memory leaks, unbounded queries, error disclosure, and performance improvements ([#49](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/49)) ([e470db5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e470db5fdc2936f96a9355ebb99d46d3792de339)) * merge docker build into release workflow to fix GITHUB_TOKEN trigger limitation ([8c73584](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/8c735849249576f94da7ab70e67c6abc57918f85)) * minor code quality improvements ([3250534](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/32505347203fc13bc668890151bbf64a1ebbae2a)) * modal styling and animation - replace glassmorphism with solid dark background, add keyframe animations ([bd81737](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bd817378e1ae3e8fc12182329a57f6ec8627bed1)) * move dynamic imports with ssr:false into client wrapper components ([7d4b815](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7d4b8151d4821ea43e59e5d3270406d38710fb3d)) * move pino dependencies to dashboard package ([df983d2](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/df983d27a5dba10735ccb801f34813bc9f90ab46)) * normalize deploy status payload and API response shape ([9473adc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/9473adc4123fd97a15d0dcf95102b11506ff85a3)) * normalize OAuth provider aliases in ownership migration ([#151](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/151)) ([ebca654](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ebca654cb36b6feb3e714bd8634edb0888ac767b)) * normalize opencode-cliproxyapi-sync to [@latest](https://github.com/latest) when loading saved plugins ([dc92958](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/dc92958dab051b45a5213fdd614556715f26276c)) * **notifications:** mark header notifications as read on click ([3541586](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3541586c98ebf8c88d345c655b5f2faf1a0ea024)) * **notifications:** persist dismissed header notifications ([6976715](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/69767155a01064d1cfc5892b474a86c7fb61cc8b)) * **oauth:** use manual launch flow when incognito mode is enabled ([#166](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/166)) ([2bc8566](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2bc85664cec4ca96e50d2b6e01e2782c0838ca67)) * **oauth:** use snapshot-diff for ownership claim instead of state-in-filename matching ([#142](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/142)) ([a788d19](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a788d19992f3e3f27f636524305b1552a19df09f)) * pass proxyUrl as prop from server to client components instead of reading process.env in browser ([156b990](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/156b990bf080c73de16ad6a66c644d0981e2d031)) * perplexity sidecar home for pip, optional auto-update, oauth config docs ([f4e0d73](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f4e0d735ecd63da6c5ed2e03f6122b655dc8e653)) * preserve original model IDs from proxy instead of transforming to dot-notation ([349f35b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/349f35b34633c3f1c72f3571aabd8b1d10001db6)), closes [#179](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/179) * prevent agents from disappearing when preset models unavailable ([7b726aa](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7b726aad51f7a89f1cd0ff0b4f97e656dad0b835)) * prevent grid row stretch when expanding quota cards (items-start) ([da1f18e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/da1f18eccb66d3d28671eaf0086761ee0b2c7c6a)) * prevent PowerShell from treating Docker stderr progress as errors ([82843e5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/82843e5b9264b3ca6363efebc9f1898621ec93b8)) * prevent quota crash for kimi accounts ([d665d11](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d665d117a7c66c9ba8f92975591c975761257dab)) * prevent quota crash for missing account email ([c553444](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c5534444bdd72e576e91a85fa49bf8a6104660ac)) * **providers:** allowlist Docker service hostnames in SSRF check ([#57](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/57)) ([370c80f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/370c80f9b5463019bd28c9a360eda1048ea2551f)) * **quota:** avoid unknown display labels for inferred providers ([6eacdfb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6eacdfbc58159a574b78bbbce1239942264418ef)) * **quota:** infer provider for unknown auth file entries ([e121c21](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e121c21c4e2db3dcf3d89d553e6790ba0db93a97)) * **quota:** normalize imported provider support mapping ([0de46ca](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0de46cadb2f3c45a2b7d80004d55a6bde835bafc)) * race conditions in provider key contribution, removal, and OAuth callback ownership ([0637049](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/063704954f59504084f7f723ffd504b6c5479c34)) * rebalance quota capacity and tighten publisher settings density ([7aa67dc](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7aa67dc739f9ee75fc9c33fdc439800ee18e68bf)) * remove CitationMode enum usage for perplexity-webui-scraper 0.7.0 ([6ad7582](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6ad7582db98e13a17a4808302d06596e253e0c68)) * remove custom provider credentials and redundant models from opencode config ([88845bf](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/88845bffdf19d216f8e0dbbe7c1a17613ff3e201)) * remove duplicate code block in deploy script ([b672e9b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b672e9b4321451e533bae0f0ef0a9c45c6d84fe6)) * remove duplicate model list from OpenCode config section ([bf7d5be](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bf7d5be8607d7362cb1f5edddfb1a73c49dbe9a2)) * remove forceQuotes from yaml dump to preserve boolean/number types ([b7f98a8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b7f98a88ca4dc088c3044e61a75047c70784c751)) * remove git pull from deploy script to prevent update failures ([f9501f7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f9501f7ead9f0cf2f3acd9210859960189109a0e)) * remove incompatible thinking/reasoning options from generated config ([#90](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/90)) ([5cacb1b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5cacb1b142e844021bef4f0f57a452951a924cde)) * remove misleading version parameter from dashboard update endpoint ([e25b30c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e25b30cbc4e162e1b470a6488c8a015d80a153c8)) * remove oversized touch-target from HelpTooltip button ([e348d45](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e348d4539a0d966ea1a3dff43168b48459b7e348)) * remove throw on missing API_URL, use empty string fallback for Docker compatibility ([4c5d13e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4c5d13e1ebb1b13abb127cb50722b9ba325236bf)) * remove turbopack.root that broke CSS module resolution ([65d097b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/65d097bbc4197b5eb4ce240bc56055ceb01f51f8)) * replace duplicate provider capacity table with enhanced chart showing long-term and short-term ([3f71127](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3f711273a666b2f72a968e9fc3f1eefffdd14cdb)) * resolve build errors from dual-write syntax and TS 5.9.3 type incompatibility ([225e8c8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/225e8c84769e1578b24decfb81af00afeff9034e)) * resolve login failure on HTTP setups and /app/logs permission denied ([e3631f4](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e3631f4ad4c11e3f895b52b674aab0a7b07713cd)) * restore CLIProxyAPI proxy update routes alongside new dashboard update routes ([0316703](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/0316703503a6a0c48160a7a44ffffb18a03c343e)) * retry Claude OAuth usage endpoint before falling back to messages ([a43522a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a43522a11a0f63ebce1fbfc04d593e00edc4fd73)) * revert provider key naming, add name input to user API keys page ([6afb7da](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6afb7da498f87b1904fe55a38b504c802fedf07b)) * run deploy script in background to avoid webhook timeout ([8e17543](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/8e175433062a6227b348e7fb42734b02457e48e1)) * save config via PUT config.yaml instead of non-existent PUT config JSON ([#115](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/115)) ([8e9b150](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/8e9b150adf27b94baa81cb1c16d5b234ac444849)) * **security:** harden SSRF, CSRF, timing, error leakage + lint cleanup ([#94](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/94)) ([5804f14](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5804f14ab7531fa2f6fc8000847b1cfe4ed04894)) * **security:** prevent race condition in setup wizard ([3e2353e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3e2353ee2e5c9a3335cd9fab3d04b3e7055ccb56)) * send raw array to PUT openai-compatibility (not wrapped object) ([580798e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/580798e536bc1fb735405b9a26afe691b697ee17)) * session secure flag falls back to NODE_ENV when X-Forwarded-Proto absent, stop trimming textarea on every keystroke ([223ae08](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/223ae08c0a22b12e9ef5ad39012291e8649418db)) * **settings:** correct key name from plugins to plugin ([4a909d3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4a909d3044c4d57912b417f1725f1797f57bd374)) * **setup:** remove obsolete API key modal after account creation ([1393d0a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/1393d0af1e9c08cb8ec51ae4878610f9a0f846e2)) * **setup:** repair wizard polling, locked logic, and broken CSS value ([3e6e3d8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3e6e3d88a827c9feadd975e0b661617260eae53d)) * show actual version instead of 'latest' in update popup ([ba0f7eb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ba0f7eb755539ee7910cbe172b18857a3dbfb745)) * show days in quota reset time instead of only hours ([072e8e0](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/072e8e0743eaa2f77dfd223a017c39ae0fea27b4)) * show device authorization code for Copilot and other device-flow providers ([527de1f](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/527de1f8df061d28ca35ee40298fbc4112727df0)) * show prisma db push output instead of silencing it ([4bae2d5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/4bae2d5a8dd5ab5ab6e93318fc7946dbceeba7f1)) * show release notes inline from version.json instead of linking to GitHub ([9551448](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/955144838b373204f2caff54a58769ead54b9cdb)) * skip lock check for forked child process to prevent self-blocking ([6d5cde7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6d5cde70cbc685c2bb6c1cdabb29171026153ead)) * stabilize quota account identifiers ([c3d0c6e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c3d0c6e4a8310bdbc9fc480b66ddf059fe69bf6d)) * stabilize recharts container sizing to avoid width -1 warnings ([9becd61](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/9becd613a6b99b4b92d4727f40b34a22469c93a2)) * support oauth deletion by account id/name and admin owner visibility ([7766069](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7766069f349238598271034ecfb24a5afe877974)) * suppress update popups while github actions build is in progress ([#52](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/52)) ([2047647](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2047647228c1fa1cc3ec80ceef782810ae6c25c3)) * surface OAuth start errors and refresh codemaps ([ceb5f95](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ceb5f95a7f05db66ef7070f525043ad9f5ad9881)) * **theme:** convert remaining hardcoded colors to opacity-based tokens ([85cfe8c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/85cfe8c0868143f438b68683b17496faf4572ae2)) * **theme:** resolve hydration mismatch with useSyncExternalStore ([b57fdeb](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b57fdeb035b64ded22d54ae7f9e1e9677849b30a)) * tmux config defaults not persisted when enabling via dashboard ([a223281](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a22328175a68db1404fba04ea1cf12508519c90d)) * track all repo paths in release-please, not just dashboard/ ([54fd32e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/54fd32e47b2ac914afe00dba2cf36e4f0881e15a)) * two bug fixes from recent PR scan (slim chains + Cursor OAuth claim latency) ([#153](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/153)) ([a2b8438](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a2b8438a42d96d102a598bb405b54b69fc4b4973)) * **ui:** improve native dropdown and date/time contrast ([c452127](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c4521276fe0fd409973ffa2efca25390dc9d8500)) * **ui:** use named Tailwind groups to prevent tooltip bleed in details sections ([cd557f2](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/cd557f229164371dc325b4bebe94206cffa8335a)) * unify model grouping logic across model selector and config generators ([c6ec7a8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c6ec7a8cef63e26983e7e54d39ecda0828d81cfe)) * unify model grouping logic across model selector and config generators ([150fec7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/150fec7517139f7faeb6b503950015e4b48cf7c6)) * update API key lastUsedAt on config sync and fix mobile responsive ([#44](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/44)) ([be3c3f1](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/be3c3f149a47f8eb6700440fafb6118b4ead5866)) * update lastSyncedAt timestamp when subscriber fetches config bundle ([e88797b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e88797b5acea5d20b264e19600c29f145f430e61)) * upgrade perplexity-webui-scraper to 0.7.0 and adapt to new API ([78a1141](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/78a1141d34c47a26e3df4e306772f1900aa4fe60)) * usage aggregation, race conditions, data loss, and client cleanup ([#46](https://github.com/itsmylife44/cliproxyapi-dashboard/issues/46)) ([a48e35a](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a48e35acf59c1abfb9190ddc950507e7373854a7)) * usage API type guards to match actual CLIProxyAPI response format ([3f8c2f5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/3f8c2f53811a868ffc74d52d15869b3a86af6abe)) * usage page reads data.data instead of data.usage ([b6e7668](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b6e7668bd986b2c42f2c4c73252fbd95ab0183a4)) * **usage:** group usage by apiKeyId/userId instead of authIndex to merge per-user entries ([bfc9df8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bfc9df84ecca6630884d9b4f84b16d476860439b)) * **usage:** resolve auth_index via /auth-files endpoint for robust user matching ([b177de7](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b177de78c88f450d934e292f0044e97a5a38423a)) * **usage:** resolve userId via source/OAuth matching instead of broken authIndex prefix ([ce69be3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/ce69be3b5206c8ed5514be4803e935b31069befc)) * **usage:** strict YYYY-MM-DD date validation, fix end-of-day boundary for to-date ([77ff899](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/77ff899f801dc8bf514ab7746a0c0136fee9bbf2)) * **usage:** use local dates for filters, strict date validation, fetch timeout, reset recordsStored on error ([5a47457](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/5a474571796edd41fb1ba742594d0812e7f244e4)) * use [@latest](https://github.com/latest) tag for opencode-cliproxyapi-sync in all default plugin lists ([c8e8b64](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c8e8b64afc5e0cb9ba0de20a32e69c20608d31a6)) * use [@latest](https://github.com/latest) tag in quick-start config section ([729d666](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/729d666707041ca6698983dce1fa7ca3351a55be)) * use API_URL env variable for proxy URL instead of non-existent CLIPROXYAPI_PROXY_URL ([be13f4c](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/be13f4ca85a0d751b5a831096377c78c6f28b103)) * use base URL directly for /models instead of hardcoding /v1 prefix ([a5089f3](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a5089f3ae28b9566aecdd59b28da1f2bcde1485b)) * use build ARG placeholders that pass env validation ([a253fcf](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/a253fcf52ec9388c57179f02a7907066f355bd42)) * use curl.exe instead of Invoke-WebRequest for API health check ([7054abe](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/7054abed148819f6754608d4426df292582066d4)) * use empty api-keys array instead of placeholder ([2bfa0ad](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2bfa0adf47fb6e61f833614633da79bea8e9a5b8)) * use explicit tailwindcss/index.css for Turbopack compatibility ([c1dba01](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c1dba01e80269560c90ce535e295df3243935c4f)) * use explicit tailwindcss/index.css import path ([51a4918](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/51a4918193d26f880a4efec1566fb4ac81341fcd)) * use internal URL for server-side proxy model fetching ([e2a01db](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e2a01db34ca2c32d1ad9e37fd3d1202601cb071c)) * use NextRequest type for validateOrigin compatibility ([f85a360](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f85a360a791269fd4abbebb34fc1e685e379e5f6)) * use no-store cache and versioned user-agent for GitHub API calls ([e0079f5](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/e0079f5ae3fbc58c8c59058fb5c8576433c1a4c8)) * use port 5433 to avoid conflicts with local Postgres and fix -Help param ([b1383de](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/b1383de3aa87ec3580d0db8ac6956498125ce143)) * use proxy API key grouping for accurate user attribution in collector ([95bc042](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/95bc042d6b9958de81a395ce2da4a9eff77bcf63)) * use Sonnet model for quota fallback, parse 7d_sonnet unified header ([6cfc219](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6cfc219fc906bdbae70e62e4929463f32af0bcaa)) * use time-based stale lock detection (10 min timeout) ([2239a98](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2239a98cc57abf70cabd193f1ebd720b0b3086fb)) * use webhook for dashboard self-update instead of docker compose ([c87f4e8](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/c87f4e82e49a199f08fbdacdfad3367ff5d5eefa)) * use webhook for dashboard self-update instead of docker compose ([074b618](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/074b618af2e8e1a1051cf8e37fb7eb5cda278da4)) * user list reads data.data instead of data.users ([2a5198b](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/2a5198b7b0e97a6f3febb3e40deeab5b8461184d)) * wrap PUT body in openai-compatibility object and handle update on empty list ([6504aa9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/6504aa97b468cd20c16f501e793c00ce79a3dc79)) ### Performance Improvements * **db:** add composite index for provider key lookups ([103101e](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/103101e025ea34ebf93e7b52aec72bff52135064)) * **db:** add index on SyncToken.tokenHash ([bba0ba9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/bba0ba96f577bb14b9a228ee4f5f34032f85a911)) * **db:** optimize Prisma queries with select clauses ([f7e7ae9](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/f7e7ae9551f5119ad692e861dfc9144dba34baf1)) * improve React performance across dashboard ([d903568](https://github.com/itsmylife44/cliproxyapi-dashboard/commit/d90356887cb19aa24e582540648dc460d9350eec)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
This fixes a config save regression where the dashboard could silently drop valid
fields from
config.yamlwhile saving unrelated settings.The core issue was that the dashboard used the reduced management
/configJSONresponse as the merge base for rewriting
config.yaml. That response is not alossless representation of the YAML file, so fields that exist in YAML but are not
serialized in
/configcould disappear on save.Problem
A save from
/dashboard/configcould remove untouched fields fromconfig.yaml.One concrete example is
host/port. If those values disappear, OAuth flows thatrely on callback forwarding can stop working because the callback target can no
longer be resolved correctly.
Root Cause
The previous flow was:
/api/management/config/api/management/config.yamlThat approach assumes
/configis a round-trippable representation of the YAMLconfiguration, which is not true.
What This Changes
The save flow now:
config.yamlThis preserves untouched YAML-only fields such as
hostandport.As a small follow-up improvement, invalid YAML now surfaces as a specific parse error
instead of showing a generic network failure.
Before / After
Before:
After:
How To Test
config.yamlthat contains fields not present in/config, for examplehostandport/dashboard/configconfig.yamlExpected result:
hostandportremain presentOptional validation:
Verification
Targeted test run:
npm test -- config-yaml.test.tsScope
This PR intentionally does not change deployment manifests or local environment
setup. It only fixes dashboard save behavior.
Notes
Broader repository validation is currently blocked by pre-existing issues on
mainunrelated to this change set:
npm run lintcrashes inside the repo's ESLint/Next.js stack before linting completesnpx tsc --noEmitreports existing type errors outside this PRnpm run buildis currently blocked by existing generated Prisma client/module issues