诚实性修复: API限流Retry-After(wait=60s)+断言 / purge定时接线(04:00 cron+actor+测试) / Channel表单校验(ref+rules+validate) / README PG数字513

This commit is contained in:
seagull
2026-09-12 02:20:50 +08:00
parent b3f3095d53
commit 67540e8d30
40 changed files with 1805 additions and 31 deletions
+11
View File
@@ -30,6 +30,11 @@ class TenantMembershipPermission(BasePermission):
not requested or requested == key_tenant.code
)
# Superusers keep the historical bootstrap contract: they are operators
# for every seeded tenant (seed_initial_data + the 0002 backfill).
if getattr(user, "is_superuser", False):
return True
tenant_code = request.META.get(
"HTTP_X_TENANT_ID", getattr(settings, "TENANT_DEFAULT", "default")
)
@@ -38,6 +43,12 @@ class TenantMembershipPermission(BasePermission):
from .models import Tenant, TenantMembership
# An unknown (or inactive) tenant is a *parameter* error, not an
# authorization failure. Answering it here would mask it as 403; the
# view layer returns 400「无法识别租户」 instead.
if not Tenant.objects.filter(code=tenant_code, is_active=True).exists():
return True
return TenantMembership.objects.filter(
user=user,
tenant__code=tenant_code,