feat(auth): block disabled user accounts at the subscription guard

RequireActiveTenantSubscription now optionally takes an AuthRepository
and rejects the request with 40311/user_disabled when the actor's user
row is anything other than active. Wire the repo through the tenant
router, surface the new error code in admin-web's
membershipBlockedErrors set, persist a "disabled" membership status when
markStoredMembershipBlocked sees user_disabled, and add localized copy
on the blocked screen and shell membership banner.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-30 01:31:26 +08:00
parent e15806bd91
commit c9267d2fae
8 changed files with 47 additions and 4 deletions
+1
View File
@@ -273,6 +273,7 @@ export const apiClient = createApiClient({
});
const membershipBlockedErrors = new Set([
"user_disabled",
"trial_plan_expired",
"subscription_required",
"subscription_inactive",
+1 -1
View File
@@ -107,7 +107,7 @@ export function markStoredMembershipBlocked(reason = "subscription_inactive"): S
membership: {
plan_code: current?.plan_code ?? "",
plan_name: current?.plan_name ?? "",
status: "expired",
status: reason === "user_disabled" ? "disabled" : "expired",
blocked: true,
blocked_reason: reason,
start_at: current?.start_at ?? null,