Add prominent warning messages when JWT secret is auto-generated:
- Use multi-line banner format for better visibility
- Include actionable guidance for production deployments
- Update both setup.go and security_secret_bootstrap.go
This helps operators notice the security concern and take
appropriate action before deploying to production.
Replace the native browser confirm() dialog in SoraAdminView with the
project's ConfirmDialog component for UI consistency.
Changes:
- Import ConfirmDialog component
- Add confirm dialog state management (showConfirmDialog, confirmDialogMessage, pendingClearUserId)
- Replace clearUserStorage() with confirmClearStorage() and handleConfirmClear()
- Add ConfirmDialog to template with danger styling
Add quoteIdentifier() function to safely quote PostgreSQL identifiers
following PostgreSQL's quoting rules (wrap in double quotes, escape
internal quotes by doubling).
This provides defense-in-depth for the CREATE DATABASE statement,
complementing the existing validateDBName() input validation.
Changes:
- Add quoteIdentifier() function with proper escaping
- Use quoted identifier in CREATE DATABASE statement
- Add comprehensive unit tests for quoteIdentifier()
- Create SoraAdminView with overview, user stats, and generations tabs
- Add /admin/sora route for Sora management
- Add i18n support (zh/en) for Sora admin page
- Extract Prometheus metrics to prommetrics package to avoid import cycles
- Integrate SetDBConnections/SetRedisConnections in OpsMetricsCollector
- Fix config_test.go viper isolation by creating empty config file in temp dir
- Fix TestLoadForcedCodexInstructionsTemplate path handling for Windows
- Add SoraGeneratePage.spec.ts with comprehensive tests for Sora generation
- Add UserEditModal.spec.ts with tests for user edit modal
- Update sora_handler_test.go with additional field tests
Backend changes:
- Add SoraHandler for admin Sora management APIs
- GET /api/v1/admin/sora/stats - system statistics
- GET /api/v1/admin/sora/users - user storage stats
- GET /api/v1/admin/sora/generations - generation records
- DELETE /api/v1/admin/sora/users/:id/storage - clear user storage
- Add sora_storage_quota_bytes to AdminUser DTO
- Add SoraStorageQuotaBytes to UpdateUserInput for admin user updates
- Add comprehensive tests for SoraHandler
Frontend changes:
- Add soraAdminAPI for Sora management
- Add sora_storage_quota_bytes and sora_storage_used_bytes to AdminUser type
- Add Sora storage quota field to UserEditModal (GB unit)
- Fix UsageLog type: add media_type, fix duration_ms to optional
- Fix AdminUsageLog type: add channel_id, billing_tier
Test fixes:
- Add window.matchMedia mock to AccountUsageCell.spec.ts
- Add tlsFingerprintProfileAPI mock to EditAccountModal.spec.ts
- Fix loadTLSProfiles function order in EditAccountModal.vue
- Fix translation key references in AccountStatusIndicator.spec.ts
Legacy instances created the settings table via ent auto-migration,
which emits Go-level defaults only. Migration 005 uses CREATE TABLE
IF NOT EXISTS, so the missing SQL DEFAULT was never backfilled. This
caused 098's raw INSERT to fail with a NOT NULL violation on
updated_at. The new migration is idempotent and safe for fresh
installs (no-op) and historical instances (backfills the default).
Two issues fixed:
1. Alipay.SupportedTypes() returned ["alipay_direct"] and Wxpay returned
["wxpay_direct"], but the frontend sends payment_type="alipay"/"wxpay".
The registry lookup failed with "payment method (alipay) is not
configured". Fix: return the base types ["alipay"]/["wxpay"].
2. When multiple providers support the same payment type (e.g. EasyPay
and Alipay direct both handle "alipay"), only the last-registered
provider's instances were reachable — the registry mapped one type to
one provider key, and SelectInstance queried by that single key.
Fix: bypass the registry in invokeProvider and let SelectInstance
query across all providers when providerKey is empty. The selected
instance's own ProviderKey (now included in InstanceSelection) is
used to create the correct provider, enabling true cross-provider
load balancing.
Closes#1592
When an Anthropic API key's credit balance is depleted, the upstream
returns HTTP 400 with message containing "credit balance". Previously,
the 400 handler only checked for "organization has been disabled",
so credit-exhausted accounts kept being scheduled — every request
returned the same error.
Treat this case identically to 402 (Payment Required): call
handleAuthError → SetError to stop scheduling the account until
an admin manually recovers it after topping up credits.
Closes#1586
- Add docs/PAYMENT.md and docs/PAYMENT_CN.md with full payment setup guide
- Mark Sub2ApiPay as deprecated in ecosystem tables (payment is now built-in)
- Add built-in payment system to features list in all 3 READMEs
Upstream removed sora feature (090_drop_sora.sql) but left i18n keys
and wire.go references. Clean up:
- Remove entire sora i18n block from en.ts and zh.ts (~190 lines)
- Remove sora nav key and unused 'data' settings tab key
- Remove sora_client_enabled from settings (fork-specific)
- Remove SoraMediaCleanupService from wire.go