chore: merge main into feat/tenant-isolation-phase-0

Resolve add/add conflicts by keeping the complete Phase 0 versions
of test_tenant_isolation_p0.py and the design spec (our branch is
a superset of the squash-merged copilot hotfix content).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-04-09 04:42:05 +00:00
2 changed files with 21 additions and 4 deletions

View File

@@ -8,7 +8,7 @@ from datetime import datetime, timezone, timedelta
from typing import Optional, Any
from uuid import UUID
from sqlalchemy import select
from sqlalchemy import select, or_
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
@@ -103,13 +103,23 @@ async def start_conversation(
Returns (conversation, greeting_message).
"""
# Load tree
# Load tree — must be accessible to this account.
# Allows own account's trees, default trees, and public trees.
# Raises ValueError (caught by endpoint as 404) if not found or not accessible.
result = await db.execute(
select(Tree).options(selectinload(Tree.tags)).where(Tree.id == tree_id)
select(Tree).options(selectinload(Tree.tags)).where(
Tree.id == tree_id,
or_(
Tree.account_id == account_id,
Tree.author_id == user_id,
Tree.is_default == True,
Tree.is_public == True,
),
)
)
tree = result.scalar_one_or_none()
if not tree:
raise ValueError(f"Tree {tree_id} not found")
raise ValueError(f"Tree {tree_id} not found or not accessible")
conversation = CopilotConversation(
user_id=user_id,