1. Redeem code affiliate rebate: balance-type redeem codes now trigger
invite rebate for the inviter. Payment fulfillment uses context key
to prevent double-rebate.
2. Batch concurrency update: new POST /admin/users/batch-concurrency
endpoint supporting mode=set/add with all=true for all users.
3. Markdown page rendering: new GET /api/v1/pages/:slug API serves local
.md files. Custom menu items with url="md:slug" render markdown with
collapsible TOC sidebar, scroll spy, and copy buttons on code blocks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix gofmt alignment in admin_service.go and trailing newline in
antigravity_credits_overages.go
- Suppress errcheck for fmt.Sscanf in client.go GetMinimumAmount
Remove SimulateClaudeMaxEnabled field and related logic from
admin_service.go, and remove applyClaudeMaxCacheBillingPolicyToUsage,
applyClaudeMaxNonStreamingRewrite, setupClaudeMaxStreamingHook calls
from antigravity_gateway_service.go. These symbols are not yet
available in upstream/main.
Replace process-memory sync.Map + per-model runtime state with a single
"AICredits" key in model_rate_limits, making credits exhaustion fully
isomorphic with model-level rate limiting.
Scheduler: rate-limited accounts with overages enabled + credits available
are now scheduled instead of excluded.
Forwarding: when model is rate-limited + credits available, inject credits
proactively without waiting for a 429 round trip.
Storage: credits exhaustion stored as model_rate_limits["AICredits"] with
5h duration, reusing SetModelRateLimit/isRateLimitActiveForKey.
Frontend: show credits_active (yellow ⚡) when model rate-limited but
credits available, credits_exhausted (red) when AICredits key active.
Tests: add unit tests for shouldMarkCreditsExhausted, injectEnabledCreditTypes,
clearCreditsExhausted, and update existing overages tests.
Previously, v-model.number produced "" when input was cleared, causing
JSON decode errors on the backend. Also, normalizeLimit treated 0 as
"unlimited" which prevented setting a zero quota. Now "" is converted
to null (unlimited) in frontend, and 0 is preserved as a valid limit.
ClosesWei-Shaw/sub2api#1021
Add a dedicated modal in group management for viewing, adding, editing,
and deleting per-user rate multipliers within a group.
Backend:
- GET /admin/groups/:id/rate-multipliers - list entries with user details
- PUT /admin/groups/:id/rate-multipliers - batch sync (full replace)
- DELETE /admin/groups/:id/rate-multipliers - clear all entries
- Repository: GetByGroupID, SyncGroupRateMultipliers methods on
user_group_rate_multipliers table (same table as user-side rates)
Frontend:
- New GroupRateMultipliersModal component with:
- User search and add with email autocomplete
- Editable rate column with local edit mode (cancel/save)
- Batch adjust: multiply all rates by a factor
- Clear all (local operation, requires save to persist)
- Pagination (10/20/50 per page)
- Platform icon with brand colors in group info bar
- Unsaved changes indicator with revert option
- Unit tests for all three backend endpoints