feat: Phase 2 tenant isolation — RLS on 11 session tables #134

Merged
chihlasm merged 16 commits from feat/tenant-isolation-phase-2 into main 2026-04-11 07:02:25 +00:00
Showing only changes of commit b9fcdd5d73 - Show all commits

View File

@@ -29,7 +29,6 @@ from app.models.session_branch import SessionBranch # noqa: F401
from app.models.fork_point import ForkPoint # noqa: F401 from app.models.fork_point import ForkPoint # noqa: F401
from app.models.session_handoff import SessionHandoff # noqa: F401 from app.models.session_handoff import SessionHandoff # noqa: F401
from app.models.session_resolution_output import SessionResolutionOutput # noqa: F401 from app.models.session_resolution_output import SessionResolutionOutput # noqa: F401
import os
from app.core.config import settings from app.core.config import settings
@@ -38,21 +37,16 @@ def _alembic_sync_url() -> str:
"""Return a psycopg2-compatible sync URL for Alembic. """Return a psycopg2-compatible sync URL for Alembic.
Priority order: Priority order:
1. Railway native PG env vars (PGHOST/PGPASSWORD/PGUSER/PGDATABASE) — these 1. DATABASE_URL_SYNC — in Railway this is set as a reference variable
are auto-linked per-environment by the Railway PostgreSQL service, so they (${{pgvector.DATABASE_URL}}) that resolves to the correct postgres
always carry the correct superuser credentials for the current environment superuser credentials for the current environment (production, PR preview,
(production, PR preview, etc.), including fresh DBs with no custom roles yet. etc.). This always works even on fresh databases before any custom roles
have been created, because it uses the postgres superuser.
2. ADMIN_DATABASE_URL (resolutionflow_admin, BYPASSRLS) converted to a sync 2. ADMIN_DATABASE_URL (resolutionflow_admin, BYPASSRLS) converted to a sync
driver — used for local dev and stable environments where the role exists. driver — fallback for local dev where DATABASE_URL_SYNC may not be set.
3. DATABASE_URL_SYNC — last resort / legacy fallback.
""" """
pg_host = os.getenv("PGHOST") if settings.DATABASE_URL_SYNC:
pg_user = os.getenv("PGUSER") return settings.DATABASE_URL_SYNC
pg_password = os.getenv("PGPASSWORD")
pg_db = os.getenv("PGDATABASE")
pg_port = os.getenv("PGPORT", "5432")
if all([pg_host, pg_user, pg_password, pg_db]):
return f"postgresql://{pg_user}:{pg_password}@{pg_host}:{pg_port}/{pg_db}"
admin_url = settings.ADMIN_DATABASE_URL admin_url = settings.ADMIN_DATABASE_URL
if admin_url and "+asyncpg" in admin_url: if admin_url and "+asyncpg" in admin_url: