Repository navigation
feat: retitle chat settings and add a Usage tab #1298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
9bf60b7
feat: retitle chat settings and add a Usage tab (credit balance, no f…
sakibsadmanshajib a536218
docs: visual proof capture log for chat settings retitle + Usage tab
sakibsadmanshajib 6ebe5ba
fix: mirror General.svelte and Usage.svelte into the CI hive-frontend…
sakibsadmanshajib c7ecc5d
fix: compile the Usage tab pre-merge and render-test its money figures
sakibsadmanshajib 1c5de0e
test: compare the rendered slot whole instead of stripping markup fro…
sakibsadmanshajib 6a30d39
docs: capture log for the populated Usage tab and its enterprise absence
sakibsadmanshajib 338b699
fix: serialize the credits probe and hand its balance to the Usage panel
sakibsadmanshajib a94ccae
docs: note the proof recapture against the second review round head
sakibsadmanshajib File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
103 changes: 103 additions & 0 deletions
103
docs/proof/chat-settings-usage-tab-2026-08-28/capture.log.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| # Visual proof capture log: chat settings retitle + Usage tab | ||
|
|
||
| PR: feat/chat-settings-usage-tab. Captured 2026-08-28. | ||
|
|
||
| ## What is proven | ||
|
|
||
| Two screenshots, captured with Playwright (chromium) against a real, | ||
| locally-built Docker image (`docker build -f deploy/docker/Dockerfile.open-webui | ||
| ...`, the actual shipped Dockerfile's backend-patch pipeline and its own final | ||
| integrity assertion all ran and passed against this build; only the frontend | ||
| compile stage substituted a direct `npx vite build` for `npm run build` | ||
| because this sandbox cannot reach the pyodide asset CDN — see "What could not | ||
| be verified" below), running as a real container, reached over plain HTTP on | ||
| `localhost` with no mocking of the rendered UI. | ||
|
|
||
| - `proof-general-chat-preferences.png`: Settings modal, General tab. Header | ||
| reads "Chat Preferences" (was the literal upstream string "WebUI Settings", | ||
| the exact parity-review finding). Tab rail: General, Account, Usage, | ||
| Interface, Audio, Data Controls, About — Usage clustered next to Account, | ||
| mirroring the Claude Desktop reference's grouping named in the task. | ||
| - `proof-usage-tab.png`: Settings modal, Usage tab (new). Shows "Usage isn't | ||
| available on this deployment.", a working "Refresh" control, and a "Last | ||
| updated" timestamp. This is the honest, designed fallback state, not a | ||
| placeholder: `hive_credits.py` (the OWUI-side proxy) fails closed to 404 | ||
| when its own upstream (control-plane's credits endpoint) is unreachable, | ||
| and `Usage.svelte` renders that as this explicit sentence rather than a | ||
| blank panel or a spinner stuck forever. See "What could not be verified" | ||
| for why the balance itself could not be exercised in this run. | ||
|
|
||
| ## Sign-in path used | ||
|
|
||
| Not the shared QA fixture (`.env` lines 70-71) and not the production OAuth | ||
| ("Continue with Hive") flow. This local verification stack's `open-webui` | ||
| service had `ENABLE_SIGNUP` and `ENABLE_LOGIN_FORM` overridden to `true` for | ||
| this run only (via an untracked, uncommitted `docker-compose.verify-override.yml`, | ||
| deleted after use), and a brand-new, throwaway account (`verify-<epoch | ||
| millis>@example.com`, random per-run password) was created through OWUI's own | ||
| native signup form, the first such account on a freshly created `owui-data` | ||
| volume becomes the local instance's own admin. No shared credential was read, | ||
| touched, or rotated. | ||
|
|
||
| ## What could not be verified, and why (environment, not code) | ||
|
|
||
| Full live-data verification (a Usage tab showing a real non-zero credit | ||
| balance) was blocked by a pre-existing, environment-wide problem, confirmed | ||
| independently before touching anything: | ||
|
|
||
| - The shared `.env`'s `SUPABASE_URL` (`https://yimgflllgdsbcibnaxqe.supabase.co`) | ||
| does not resolve at all (`curl: (6) Could not resolve host`). The Supabase | ||
| Cloud project it names was deleted during the self-hosted cutover | ||
| (`.wolf/decisions.md`, project self-hosted-Supabase-migration notes). | ||
| - `SUPABASE_DB_URL` points at the same dead project's pooler | ||
| (`aws-1-us-east-1.pooler.supabase.com`); it answers with a real Postgres | ||
| wire-protocol error, `FATAL: (ENOTFOUND) tenant/user | ||
| postgres.yimgflllgdsbcibnaxqe not found`, confirming the project reference | ||
| itself is gone, not a transient network issue. | ||
| - This is not specific to this run or this sandbox: other agents' | ||
| concurrently running `control-plane` containers on this same shared box | ||
| were independently observed in the same `unhealthy` state before this | ||
| session touched anything, using the same shared `.env`. | ||
| - The real, live self-hosted GoTrue is reachable and healthy at | ||
| `https://console-hive.scubed.co/auth/v1/health` (HTTP 200), confirming the | ||
| production deployment itself is fine; only the local `.env`'s pointers are | ||
| stale. | ||
|
|
||
| Given this, exercising the real `internal/chat/credits/balance` code path | ||
| (which needs a live Postgres connection to resolve tenant -> account -> | ||
| balance) was not achievable from this sandbox without fabricating a database | ||
| connection string, which was not done. The captured "Usage isn't available on | ||
| this deployment." screenshot is the correct, honest behavior of this exact | ||
| condition, not a placeholder standing in for something unverified. The | ||
| formatter that would render a real balance (`formatUsdFromCredits`, ported | ||
| from `apps/web-console/lib/format/model-pricing.ts`) is independently unit | ||
| tested end to end in `vendor/open-webui/src/lib/hive/credits.test.ts`, | ||
| including the explicit "never renders a bare integer, zero renders `$0`" | ||
| invariant. | ||
|
|
||
| Also not verified live: OAuth sign-in through the production "Continue with | ||
| Hive" flow, since `OPENID_PROVIDER_URL` in this deployment derives from the | ||
| same dead `SUPABASE_URL`. | ||
|
|
||
| ## Full test and build evidence (reproducible, not just this capture) | ||
|
|
||
| - `npm run test:frontend -- --run` inside `vendor/open-webui`: 208/208 tests | ||
| passed across 16 files, including the 10 new regression tests in | ||
| `src/lib/hive/settings-usage-tab.test.ts`. | ||
| - `npx vite build` (real production compile of the full SvelteKit app, | ||
| including `Usage.svelte` and the `ChartBar` icon import): succeeded, | ||
| produced `build/index.html` and every real chunk (`ChartBar.js` present in | ||
| the emitted chunk list). | ||
| - `docker build -f deploy/docker/Dockerfile.open-webui ...` (the real, | ||
| shipped Dockerfile, unmodified except substituting the frontend build | ||
| command for the reason above): succeeded, including every one of the | ||
| Dockerfile's ~50 backend-patch and assertion steps, ending in its own final | ||
| integrity check: `hive: shell present, removed surfaces absent`. | ||
|
|
||
| ## Credential handling | ||
|
|
||
| No credential-bearing URL was captured in any screenshot (headless Playwright | ||
| screenshots in this run capture only page content, not browser chrome or the | ||
| address bar). The throwaway signup email/password are not secrets (random, | ||
| single-use, `example.com`/`example.invalid`, never touch any real system) and | ||
| are not redacted for that reason. |
135 changes: 135 additions & 0 deletions
135
docs/proof/chat-settings-usage-tab-2026-08-29/capture.log.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| # Visual proof capture log: Usage tab, populated state and enterprise absence | ||
|
|
||
| PR: feat/chat-settings-usage-tab, second capture. Captured 2026-08-29. | ||
|
|
||
| Supersedes the 2026-08-28 capture in the sibling directory, which proved the | ||
| General retitle but showed the Usage tab in its no-data fallback rather than | ||
| the claimed "credit balance and today's usage". That gap was the review | ||
| finding this capture closes. | ||
|
|
||
| ## What is proven | ||
|
|
||
| Three screenshots, taken with Playwright (chromium, 1280x860) against a real | ||
| container built from this branch with the shipped | ||
| `deploy/docker/Dockerfile.open-webui`, reached over plain HTTP on localhost. | ||
| No stubbing of the rendered UI: the only thing intercepted is the one HTTP | ||
| response the tab consumes. | ||
|
|
||
| - `20-settings-general.png`: Settings, General tab. Header reads "Chat | ||
| Preferences", the retitle. Tab rail reads General, Account, Usage, | ||
| Interface, Audio, Data Controls, About, with Usage clustered next to | ||
| Account. | ||
| - `21-settings-usage.png`: Settings, Usage tab, populated. "Organization | ||
| credit balance $12.50", "Organization usage today $0.34", the "Top up" | ||
| link, a "Last updated" stamp and the "Refresh" control. Both money labels | ||
| carry the organization scope, which is the relabel from the review: the | ||
| figures are tenant scope and previously read as personal. | ||
| - `22-settings-enterprise.png`: the same build with the credits endpoint | ||
| answering its documented 404. The Usage entry is absent from the rail | ||
| entirely (General, Account, Interface, Audio, Data Controls, About), which | ||
| is the silent absence posture `deploy/docker/owui-patches/hive_credits.py` | ||
| describes. Before this change the tab was present and permanently empty. | ||
|
|
||
| ## How the populated state was produced without a database | ||
|
|
||
| Issue #1297 leaves this sandbox with no reachable Supabase, so the real | ||
| `internal/chat/credits/balance` chain cannot run here. It does not have to: | ||
| the browser sees exactly one credits response, and Playwright fulfils it. | ||
|
|
||
| ```js | ||
| await page.route('**/hive/credits/balance', async (route) => { | ||
| await route.fulfill({ | ||
| status: 200, | ||
| contentType: 'application/json', | ||
| body: JSON.stringify({ | ||
| available_credits: 12500000000, | ||
| usage_today_credits: 340000000, | ||
| top_up_url: 'https://console-hive.scubed.co/console/billing' | ||
| }) | ||
| }); | ||
| }); | ||
| ``` | ||
|
|
||
| The two magnitudes are deliberately different, so the screenshot also shows | ||
| the figures landing in the right rows: 12,500,000,000 credits is $12.50 at | ||
| the D-046 rate of one billion credits per dollar, and 340,000,000 credits is | ||
| $0.34. A transposition would be visible in the image itself. The third | ||
| capture uses the same route with `status: 404` and the endpoint's own body, | ||
| `{"detail": "Credits are unavailable."}`. | ||
|
|
||
| The panel's rendered text, read back from the live DOM in the same run: | ||
|
|
||
| ``` | ||
| Usage | Organization credit balance | $12.50 | Organization usage today | | ||
| $0.34 | Top up | Last updated: 11:07:13 PM | Refresh | ||
| ``` | ||
|
|
||
| Tab rails, read from the live DOM in the same run: | ||
|
|
||
| ``` | ||
| credits available: ["General","Account","Usage","Interface","Audio","Data Controls","About"] | ||
| credits absent: ["General","Account","Interface","Audio","Data Controls","About"] | ||
| ``` | ||
|
|
||
| ## Sign-in path used | ||
|
|
||
| Not the shared QA fixture and not the production OAuth flow. The container is | ||
| a throwaway with its own empty volume, `ENABLE_SIGNUP` and | ||
| `ENABLE_LOGIN_FORM` on for this run only, and the first account created on it | ||
| becomes its own local admin. That account was created through the container's | ||
| own signup endpoint with a random single use password at an `example.invalid` | ||
| address, used only against this container, and destroyed with it. Nothing | ||
| about it is written here, no shared credential was read, touched or rotated, | ||
| and no URL in any screenshot carries a token. | ||
|
|
||
| ## Build note, environment rather than code | ||
|
|
||
| The image is the shipped Dockerfile with one substitution: the frontend build | ||
| step runs `npx vite build` instead of `npm run build`, because | ||
| `npm run pyodide:fetch` cannot reach the pyodide CDN from this sandbox and | ||
| fails the build outright (`fetch failed`, `SocketError: other side closed`, | ||
| observed twice). Everything else ran unmodified, including the stage that | ||
| runs `npm run test:frontend -- --run` against the real vendored node_modules, | ||
| which reported 16 files and 221 tests passed. That is the in place run of the | ||
| same test sources the pre-merge gate runs in its scratch tree, so the render | ||
| assertions added in this PR are confirmed to work in both places. | ||
|
|
||
| The window chrome in these captures reads "Open WebUI" rather than the Hive | ||
| name because this standalone container is run without the compose file's | ||
| branding environment. It has no bearing on what is being proven. | ||
|
|
||
| ## Test evidence backing the same change | ||
|
|
||
| `make test-owui-frontend`, the pre-merge gate, on the unmutated tree: | ||
|
|
||
| ``` | ||
| Test Files 16 passed (16) | ||
| Tests 221 passed (221) | ||
| 14/14 components compiled | ||
| ``` | ||
|
|
||
| The same gate, with each of the reviewer's three mutations applied one at a | ||
| time: compile error red, transposed figures red on three assertions, emptied | ||
| click handler red on one assertion, exit 2 in every case. | ||
|
|
||
| ## Recaptured after the second review round | ||
|
|
||
| The screenshots above were first taken at commit `6a30d39`, then retaken | ||
| unchanged in appearance at `338b699`, the head that answers the second review | ||
| round. That round changed how the number reaches the panel: the settings | ||
| modal's availability probe now hands its balance and fetch time straight to | ||
| the Usage panel instead of the panel firing its own request, and the probe is | ||
| serialized so two opens cannot land out of order. The panel therefore renders | ||
| the same figures from a snapshot rather than from its own mount fetch, which | ||
| is why this capture was redone rather than reused. | ||
|
|
||
| Same run, read back from the live DOM at that head: | ||
|
|
||
| ``` | ||
| Usage | Organization credit balance | $12.50 | Organization usage today | | ||
| $0.34 | Top up | Last updated: 11:30:24 PM | Refresh | ||
| ``` | ||
|
|
||
| The image build for that container reported `Test Files 16 passed (16)` and | ||
| `Tests 221 passed (221)` from its in place `npm run test:frontend -- --run` | ||
| stage, against the same commit. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.