feat: tenant isolation Phase 0 — app-layer filters, UUID audit, CI gate #132

Merged
chihlasm merged 22 commits from feat/tenant-isolation-phase-0 into main 2026-04-09 04:42:19 +00:00
Showing only changes of commit 68eabf27f4 - Show all commits

View File

@@ -12,6 +12,7 @@ from app.models.user import User
from app.schemas.category import CategoryCreate, CategoryUpdate, CategoryResponse, CategoryListResponse from app.schemas.category import CategoryCreate, CategoryUpdate, CategoryResponse, CategoryListResponse
from app.api.deps import get_current_active_user from app.api.deps import get_current_active_user
from app.core.permissions import can_manage_category, can_create_category from app.core.permissions import can_manage_category, can_create_category
from app.core.filters import tenant_filter
router = APIRouter(prefix="/categories", tags=["categories"]) router = APIRouter(prefix="/categories", tags=["categories"])
@@ -108,10 +109,12 @@ async def get_category(
detail="You don't have access to this category" detail="You don't have access to this category"
) )
# Get tree count # Get tree count — scoped to the requesting account so cross-account
# trees in shared categories are not counted.
count_query = select(func.count(Tree.id)).where( count_query = select(func.count(Tree.id)).where(
Tree.category_id == category.id, Tree.category_id == category.id,
Tree.is_active == True Tree.is_active == True,
tenant_filter(Tree, current_user.account_id),
) )
count_result = await db.execute(count_query) count_result = await db.execute(count_query)
tree_count = count_result.scalar() or 0 tree_count = count_result.scalar() or 0