Both guards run per-route (NOT global — APP_GUARD stays a signed decision, 高危#4):
TenantIsolationGuard: fail-closed — no active tenant → 403.
AuthorizationGuard: delegates the capability check to Better Auth ac (single
source of truth), so role→permission mapping is never scattered here.
Permission tiers (S3 human call): workspace:read for all members;
workspace:create/update/delete for owner+admin. Row scoping by tenant is enforced in
the repository — handlers/controllers never name a tenant id.
工作区 CRUD 参考切片的 HTTP 控制器(多租户 S3 · D2/§9.1 / FR-4/FR-5)。
Remarks
Workspace CRUD reference slice (global-tenancy S3 · D2/§9.1 / FR-4/FR-5).
Both guards run per-route (NOT global — APP_GUARD stays a signed decision, 高危#4):
TenantIsolationGuard: fail-closed — no active tenant → 403.AuthorizationGuard: delegates the capability check to Better Authac(single source of truth), so role→permission mapping is never scattered here.Permission tiers (S3 human call):
workspace:readfor all members;workspace:create/update/deletefor owner+admin. Row scoping by tenant is enforced in the repository — handlers/controllers never name a tenant id.