[Feature]: Implement Row-Level Security (RLS) for Tenant Isolation - #101
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughAdds Supabase RLS policies, per-user JWT-authenticated clients, user-scoped data-access routing, environment configuration, and an executable cross-user isolation test. ChangesRow-level security enforcement
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant BackendOperation
participant get_client
participant Supabase
participant RLS
BackendOperation->>get_client: Pass telegram_id
get_client->>Supabase: Send JWT-authenticated request
Supabase->>RLS: Evaluate User isolation policy
RLS-->>BackendOperation: Return rows matching JWT subject
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/supabase_service.py`:
- Around line 23-37: Update get_client so a missing SUPABASE_JWT_SECRET raises
an error instead of falling back to the service-role client. Remove the
warning/fallback path while preserving the JWT-authenticated create_client flow
when the secret is available.
In `@backend/tests/test_rls.py`:
- Around line 6-11: Update the import setup in test_rls.py so the intentional
sys.path mutation no longer triggers Ruff E402/I001: either dynamically load
supabase_service after the path setup, or apply the narrowly scoped lint
exception for that import while preserving get_client usage and environment
loading order.
- Around line 19-22: Update the RLS test setup and assertions so missing
SUPABASE_JWT_SECRET explicitly skips or fails the test instead of returning
success, and replace unauthorized-result logging with an assertion that
result.data is empty. Preserve resource cleanup by keeping the existing cleanup
logic in a finally block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 95a318d3-2295-4772-b4ea-c9e33f8dd23e
📒 Files selected for processing (6)
backend/.env.examplebackend/requirements.txtbackend/supabase_service.pybackend/tests/test_rls.pypublic/setup/migration_rls.sqlpublic/setup/schema.sql
|
@ErebAsh merge conflict here |
Description:
What this PR does / why we need it:
GitPhone utilizes a central Supabase instance where users are currently isolated purely by application-level filtering (
WHERE telegram_id = ?). This PR hardens the security model by enforcing PostgreSQL's native Row-Level Security (RLS) policies.By applying RLS, we ensure that a backend bug or injection vulnerability cannot result in cross-tenant data exposure (e.g., exposing another user's GitHub tokens or staged file diffs).
Changes included in this PR:
users,staged_files, andcommit_logtables inpublic/setup/schema.sql.migration_rls.sqlscript to apply the changes to the production DB.supabase_service.pyto dynamically construct user-scoped Supabase clients for user-facing flows. It now generates and passes a custom JWT (signed withSUPABASE_JWT_SECRET) in theAuthorizationheader, enforcing RLS at the API gateway layer.PyJWTtorequirements.txtand updated.env.example.backend/tests/test_rls.py) to explicitly verify that unauthorized cross-tenant data access is blocked by the database engine (returning 0 rows).How to test these changes:
public/setup/migration_rls.sqlscript in your Supabase SQL Editor.backend/.envasSUPABASE_JWT_SECRET="<secret>".cd backend pip install -r requirements.txt python tests/test_rls.pySummary by CodeRabbit
Security
Configuration
Tests