feat(tenant): per-tenant brand and question limit overrides

Add nullable brand_limit / question_limit columns on tenants so ops
admins can override the plan-derived brand-library quotas per account.
When set, these take precedence over config.yml plan defaults across the
brand-library summary, question materialization, and the daily
monitoring worker's primary-client plan resolution.

Ops side exposes them on admin-user create plus a new
PUT /admin-users/:id/limits endpoint, invalidating the brand-library
summary cache on change. The ops-web AdminUsers view gains matching
inputs on the create and edit modals.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-24 09:04:06 +08:00
parent d69510274c
commit 348f2e3451
16 changed files with 413 additions and 63 deletions
@@ -1053,13 +1053,15 @@ type TemplateAssistTask struct {
}
type Tenant struct {
ID int64 `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
FrozenAt pgtype.Timestamptz `json:"frozen_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
ID int64 `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
FrozenAt pgtype.Timestamptz `json:"frozen_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
BrandLimit pgtype.Int4 `json:"brand_limit"`
QuestionLimit pgtype.Int4 `json:"question_limit"`
}
type TenantImageStorageUsage struct {