From 9d60b9a244d04529ac3911923fdf401a50d370ed Mon Sep 17 00:00:00 2001 From: chihlasm Date: Fri, 10 Apr 2026 03:52:52 +0000 Subject: [PATCH] feat: apply require_tenant_context to all user-facing routers Co-Authored-By: Claude Sonnet 4.6 --- backend/app/api/router.py | 212 +++++++++++++++++++++++--------------- 1 file changed, 131 insertions(+), 81 deletions(-) diff --git a/backend/app/api/router.py b/backend/app/api/router.py index d588afc9..ed32ba58 100644 --- a/backend/app/api/router.py +++ b/backend/app/api/router.py @@ -1,51 +1,89 @@ -from fastapi import APIRouter -from app.api.endpoints import auth, trees, sessions, sidebar, invite, categories, tags, folders, step_categories, steps, admin, accounts, webhooks, shares, shared, tree_markdown -from app.api.endpoints import admin_dashboard, admin_audit, admin_plan_limits, admin_feature_flags, admin_settings, admin_categories -from app.api.endpoints import ratings, analytics -from app.api.endpoints import target_lists -from app.api.endpoints import maintenance_schedules -from app.api.endpoints import feedback -from app.api.endpoints import ai_builder -from app.api.endpoints import ai_fix -from app.api.endpoints import ai_chat -from app.api.endpoints import copilot -from app.api.endpoints import assistant_chat -from app.api.endpoints import survey -from app.api.endpoints import admin_survey -from app.api.endpoints import tree_transfer -from app.api.endpoints import ai_suggestions -from app.api.endpoints import kb_accelerator -from app.api.endpoints import beta_signup -from app.api.endpoints import scripts -from app.api.endpoints import integrations -from app.api.endpoints import onboarding -from app.api.endpoints import branding -from app.api.endpoints import supporting_data -from app.api.endpoints import ai_sessions -from app.api.endpoints import flow_proposals -from app.api.endpoints import flowpilot_analytics -from app.api.endpoints import notifications -from app.api.endpoints import public_templates -from app.api.endpoints import admin_gallery -from app.api.endpoints import uploads -from app.api.endpoints import script_builder -from app.api.endpoints import beta_feedback -from app.api.endpoints import session_branches -from app.api.endpoints import session_handoffs -from app.api.endpoints import session_resolutions +from fastapi import APIRouter, Depends + +from app.api.deps import require_tenant_context +from app.api.endpoints import ( + admin, + admin_audit, + admin_categories, + admin_dashboard, + admin_feature_flags, + admin_gallery, + admin_plan_limits, + admin_settings, + admin_survey, + ai_builder, + ai_chat, + ai_fix, + ai_sessions, + ai_suggestions, + analytics, + assistant_chat, + auth, + beta_feedback, + beta_signup, + branding, + categories, + copilot, + feedback, + flow_proposals, + flowpilot_analytics, + folders, + integrations, + invite, + kb_accelerator, + maintenance_schedules, + notifications, + onboarding, + public_templates, + ratings, + scripts, + script_builder, + session_branches, + session_handoffs, + session_resolutions, + sessions, + shared, + shares, + sidebar, + step_categories, + steps, + supporting_data, + survey, + tags, + target_lists, + tree_markdown, + tree_transfer, + trees, + uploads, + webhooks, + accounts, +) api_router = APIRouter() +# --------------------------------------------------------------------------- +# Public / unauthenticated endpoints — no tenant context +# +# Note: auth.router contains both public endpoints (register, login, +# forgot-password, reset-password, email/verify) and authenticated endpoints +# (GET/PATCH /me, logout, change-password, email/send-verification). +# The authenticated auth endpoints only query the `users` table, which is +# excluded from Phase 1 RLS. They work correctly without tenant context +# in Phase 1. This will need revisiting in Phase 2 when `users` gets RLS. +# --------------------------------------------------------------------------- api_router.include_router(auth.router) -api_router.include_router(trees.router) -api_router.include_router(sidebar.router) -api_router.include_router(sessions.router) -api_router.include_router(invite.router) -api_router.include_router(categories.router) -api_router.include_router(tags.router) -api_router.include_router(folders.router) -api_router.include_router(step_categories.router) -api_router.include_router(steps.router) +api_router.include_router(shared.router) # Public share links (no auth) +api_router.include_router(beta_signup.router) +api_router.include_router(webhooks.router) # Stripe webhook receiver +api_router.include_router(public_templates.router) # Public gallery (no auth, rate-limited) + +# --------------------------------------------------------------------------- +# Admin endpoints — super_admin only +# admin_categories, admin_gallery, admin_dashboard, admin query Phase 1 RLS +# tables and MUST use get_admin_db (migrated in Task 8). The remaining admin +# endpoints (admin_audit, admin_plan_limits, admin_feature_flags, +# admin_settings, admin_survey) are safe until Phase 2 extends RLS. +# --------------------------------------------------------------------------- api_router.include_router(admin.router) api_router.include_router(admin_dashboard.router) api_router.include_router(admin_audit.router) @@ -53,42 +91,54 @@ api_router.include_router(admin_plan_limits.router) api_router.include_router(admin_feature_flags.router) api_router.include_router(admin_settings.router) api_router.include_router(admin_categories.router) -api_router.include_router(accounts.router) -api_router.include_router(webhooks.router) -api_router.include_router(shares.router) -api_router.include_router(shared.router) # Public endpoints (no auth) -api_router.include_router(tree_markdown.router) -api_router.include_router(ratings.router) -api_router.include_router(analytics.router) -api_router.include_router(target_lists.router) -api_router.include_router(maintenance_schedules.router) -api_router.include_router(feedback.router) -api_router.include_router(ai_builder.router) -api_router.include_router(ai_fix.router) -api_router.include_router(ai_chat.router) -api_router.include_router(copilot.router) -api_router.include_router(assistant_chat.router) -api_router.include_router(survey.router) api_router.include_router(admin_survey.router) -api_router.include_router(tree_transfer.router) -api_router.include_router(ai_suggestions.router) -api_router.include_router(kb_accelerator.router) -api_router.include_router(beta_signup.router) -api_router.include_router(scripts.router) -api_router.include_router(integrations.router) -api_router.include_router(onboarding.router) -api_router.include_router(branding.router) -api_router.include_router(supporting_data.router) -api_router.include_router(session_handoffs.queue_router) # Must be before ai_sessions to avoid /{session_id} conflict -api_router.include_router(session_resolutions.router) # Must be before ai_sessions to avoid /{session_id} conflict -api_router.include_router(ai_sessions.router) -api_router.include_router(flow_proposals.router) -api_router.include_router(flowpilot_analytics.router) -api_router.include_router(notifications.router) -api_router.include_router(public_templates.router) api_router.include_router(admin_gallery.router) -api_router.include_router(uploads.router) -api_router.include_router(script_builder.router) -api_router.include_router(beta_feedback.router) -api_router.include_router(session_branches.router) -api_router.include_router(session_handoffs.router) + +# --------------------------------------------------------------------------- +# User-facing endpoints — tenant context required +# --------------------------------------------------------------------------- +_tenant_deps = [Depends(require_tenant_context)] + +api_router.include_router(trees.router, dependencies=_tenant_deps) +api_router.include_router(sidebar.router, dependencies=_tenant_deps) +api_router.include_router(sessions.router, dependencies=_tenant_deps) +api_router.include_router(invite.router, dependencies=_tenant_deps) +api_router.include_router(categories.router, dependencies=_tenant_deps) +api_router.include_router(tags.router, dependencies=_tenant_deps) +api_router.include_router(folders.router, dependencies=_tenant_deps) +api_router.include_router(step_categories.router, dependencies=_tenant_deps) +api_router.include_router(steps.router, dependencies=_tenant_deps) +api_router.include_router(accounts.router, dependencies=_tenant_deps) +api_router.include_router(shares.router, dependencies=_tenant_deps) +api_router.include_router(tree_markdown.router, dependencies=_tenant_deps) +api_router.include_router(ratings.router, dependencies=_tenant_deps) +api_router.include_router(analytics.router, dependencies=_tenant_deps) +api_router.include_router(target_lists.router, dependencies=_tenant_deps) +api_router.include_router(maintenance_schedules.router, dependencies=_tenant_deps) +api_router.include_router(feedback.router, dependencies=_tenant_deps) +api_router.include_router(ai_builder.router, dependencies=_tenant_deps) +api_router.include_router(ai_fix.router, dependencies=_tenant_deps) +api_router.include_router(ai_chat.router, dependencies=_tenant_deps) +api_router.include_router(copilot.router, dependencies=_tenant_deps) +api_router.include_router(assistant_chat.router, dependencies=_tenant_deps) +api_router.include_router(survey.router, dependencies=_tenant_deps) +api_router.include_router(tree_transfer.router, dependencies=_tenant_deps) +api_router.include_router(ai_suggestions.router, dependencies=_tenant_deps) +api_router.include_router(kb_accelerator.router, dependencies=_tenant_deps) +api_router.include_router(scripts.router, dependencies=_tenant_deps) +api_router.include_router(integrations.router, dependencies=_tenant_deps) +api_router.include_router(onboarding.router, dependencies=_tenant_deps) +api_router.include_router(branding.router, dependencies=_tenant_deps) +api_router.include_router(supporting_data.router, dependencies=_tenant_deps) +# session_handoffs queue router must come before ai_sessions to avoid conflict +api_router.include_router(session_handoffs.queue_router, dependencies=_tenant_deps) +api_router.include_router(session_resolutions.router, dependencies=_tenant_deps) +api_router.include_router(ai_sessions.router, dependencies=_tenant_deps) +api_router.include_router(flow_proposals.router, dependencies=_tenant_deps) +api_router.include_router(flowpilot_analytics.router, dependencies=_tenant_deps) +api_router.include_router(notifications.router, dependencies=_tenant_deps) +api_router.include_router(uploads.router, dependencies=_tenant_deps) +api_router.include_router(script_builder.router, dependencies=_tenant_deps) +api_router.include_router(beta_feedback.router, dependencies=_tenant_deps) +api_router.include_router(session_branches.router, dependencies=_tenant_deps) +api_router.include_router(session_handoffs.router, dependencies=_tenant_deps)