refactor: tech debt reduction - extract hooks, deduplicate helpers, update deps, add CI

- Extract useCustomStepFlow hook from TreeNavigationPage (1040 → 759 lines)
- Create core/filters.py with shared tree/step visibility filters
- Create services/export_service.py from session export logic
- Add GitHub Actions CI/CD pipeline (pytest + lint + build)
- Add GIN index migration for full-text search on trees
- Update FastAPI 0.128.5, Pydantic 2.12.5, SQLAlchemy 2.0.46, +5 more
- Fix regex → pattern deprecation in Query() params

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-08 08:14:22 -05:00
parent f4eb3fe186
commit b97596d286
12 changed files with 786 additions and 557 deletions

View File

@@ -4,7 +4,7 @@ from uuid import UUID
import secrets
from fastapi import APIRouter, Depends, HTTPException, status, Query, Request
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_, true as sa_true, update
from sqlalchemy import select, func, or_, update
from sqlalchemy.orm import selectinload
from app.core.database import get_db
@@ -21,6 +21,7 @@ from app.schemas.tree import (
)
from app.api.deps import get_current_active_user, require_engineer_or_admin, require_admin
from app.core.permissions import can_edit_tree, can_access_tree
from app.core.filters import build_tree_access_filter
from app.core.subscriptions import check_tree_limit
from app.core.audit import log_audit
from app.core.config import settings
@@ -29,28 +30,6 @@ from app.core.tree_validation import can_publish_tree
router = APIRouter(prefix="/trees", tags=["trees"])
def build_tree_access_filter(current_user: User):
"""Build the access filter for trees based on user permissions.
Returns trees that are:
- All trees (for super admins)
- Default/system trees (visible to all)
- Public trees
- User's own trees
- Trees from user's team
"""
if current_user.is_super_admin:
return sa_true()
conditions = [
Tree.is_default == True,
Tree.is_public == True,
Tree.author_id == current_user.id,
]
if current_user.account_id:
conditions.append(Tree.account_id == current_user.account_id)
return or_(*conditions)
def build_tree_response(tree: Tree) -> TreeListResponse:
"""Build TreeListResponse with category_info and tags."""
category_info = None