- ChannelsView platformOrder now includes the three CN provider
platforms so channel pricing can be configured for them; composite
group expansion/attachment stays limited to the five main platforms
(matches backend isConcreteRequestPlatform and composite-routes
target_platform validation)
- SyncPricingModels maps kimi->moonshot, zhipu->zhipu,
deepseek->deepseek; also fixes gemini mapping to "google" which
matched zero catalog entries (provider key is "gemini")
- Add CN platform colors to channel pricing model tag classes
Require oauth state/redirect consistency, fail closed on missing proxy,
and remove password login from create/reauth UI (admin-only password path stays off by default).
Add mode-first connectivity probes for text/image/video/search/tts/stt/realtime,
standalone voice and web-search paths, media upload options, and in-browser
image/audio/video preview (including ZDR-safe b64 images and edit validation).
Persist reasoning ceilings and exact mappings for OpenAI groups, enforce them across HTTP and WebSocket forwarding, and invalidate cached auth snapshots.
Debounced requests can finish out of order, allowing an earlier response to replace newer results or repopulate a cleared field. Track a request generation and gate state updates, with deterministic regression coverage.
Constraint: Preserve the existing 300 ms debounce and admin usage API contract
Rejected: Add AbortController plumbing | sequence invalidation matches repository patterns without changing API signatures
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep async filter results gated against superseded queries
Tested: Focused Vitest (4 tests), vue-tsc, ESLint, and full frontend suite except two pre-existing rollback assertion failures
Not-tested: Live browser against production-sized user data
Related: https://github.com/Wei-Shaw/sub2api/issues/4551
The project's dark theme uses the custom slate-based dark-* palette
(928 dark:bg-dark-* / 787 dark:border-dark-* occurrences), but a
minority of surfaces still used Tailwind's neutral gray-* scale, which
has a visibly cooler hue next to slate cards — most noticeably the
filter dropdown panels on the usage, accounts and subscriptions pages.
Migrate the remaining dark:bg-gray-* / dark:border-gray-* (and their
hover: variants) to the dark-* palette across 12 components: filter
dropdowns, chart card borders, menu separators, and small badges.
49 class-string substitutions, no structural or logic changes;
dark:text-gray-* is untouched since gray text on dark surfaces is the
established project-wide convention.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The user info banner in UserBalanceModal renders on a dark:bg-dark-700
container, but the email line kept text-gray-900 and the balance line
text-gray-500 with no dark variants, leaving near-black text on a dark
background. Align both with the pattern already used elsewhere in the
same dialog (text-gray-900 dark:text-gray-100 / text-gray-500
dark:text-gray-400).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Admins often recreate monitors with the same endpoint, model, and request settings. A server-side duplicate keeps the stored API key out of the browser, creates a disabled copy for review, and uses stable operation identity to recover ambiguous retries without creating extra rows.
Constraint: Stored monitor API keys must never be returned to the browser
Constraint: Applying a request template must preserve internal duplicate recovery metadata
Rejected: Rebuild the monitor from list data | list responses only contain a masked API key
Rejected: Copy runtime state and history | a duplicate should start as an unverified configuration
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep duplicated monitors disabled until an administrator reviews and enables them
Tested: Go unit tests for repository, service, and admin handler; integration-tag compile; go vet; golangci-lint v2.9; frontend Vitest, ESLint, typecheck, production build; Playwright duplicate flow
Not-tested: PostgreSQL container integration locally because Docker is unavailable; CI will execute the database-backed suite
Admins often need another account with the same provider and routing configuration. Duplicate on the server so credentials never return to the browser, preserve exact group priorities atomically, start the copy paused, and recover the same copy after ambiguous idempotency-store failures.
Constraint: Admin account responses redact credentials, so duplication must remain server-side
Constraint: OAuth and setup-token credentials rotate and must not be shared across account rows
Rejected: Copy raw account JSON to the clipboard | exposes credentials outside the server
Rejected: Duplicate rotating credentials | account-scoped refresh locks can race token rotation
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep copies paused, avoid automatic upstream probes, and exclude rotating credential types unless token ownership is redesigned
Tested: Targeted Go tests, Go vet, server build; frontend lint, typecheck, Vitest suite, production build; integration test compiled
Not-tested: Docker-backed PostgreSQL execution because Docker is unavailable
Related: Wei-Shaw/sub2api#1379
Related: Wei-Shaw/sub2api#2928