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

@@ -0,0 +1,60 @@
"""
Centralized query filters for ResolutionFlow.
Provides reusable SQLAlchemy filter builders for tree access control
and step visibility, used across multiple endpoint modules.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import or_, and_, true as sa_true
if TYPE_CHECKING:
from app.models.user import User
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 account
"""
from app.models.tree import Tree
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_step_visibility_filter(current_user: User):
"""Build SQLAlchemy filter for step visibility based on user.
Returns steps that are:
- Public steps (visible to all)
- Team steps (visible to same account members)
- User's own private steps
"""
from app.models.step_library import StepLibrary
if current_user.account_id:
return or_(
StepLibrary.visibility == 'public',
and_(StepLibrary.visibility == 'team', StepLibrary.account_id == current_user.account_id),
StepLibrary.created_by == current_user.id # Own private steps
)
else:
return or_(
StepLibrary.visibility == 'public',
StepLibrary.created_by == current_user.id
)