Implement RLS policies for location data isolation
epic-geographic-peer-mentor-map-data-infrastructure-task-003 — Implement row-level security policies on the mentor_locations table enforcing organisation-scoped access. Coordinators may only SELECT rows where organisation_id matches their JWT claim. Peer mentors may only INSERT and UPDATE their own row. Verify policies block cross-organisation reads via Supabase policy tests.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
To simulate different user roles in pgTAP tests, use `SET LOCAL role = authenticated;` combined with `SET LOCAL request.jwt.claims = '{"sub": "
Consider a Postgres security label or comment on each policy documenting the business rule it enforces, to aid future audits. Cross-reference these policies against the Norwegian Personal Data Act (Personopplysningsloven) requirements for location data minimisation.
Testing Requirements
Automated policy tests using `supabase test db` with pgTAP. Write SQL test functions covering: (1) coordinator same-org SELECT returns rows; (2) coordinator cross-org SELECT returns zero rows; (3) mentor self INSERT succeeds; (4) mentor other-user INSERT fails; (5) mentor self UPDATE succeeds; (6) mentor other-user UPDATE fails; (7) anonymous SELECT returns zero rows; (8) anonymous INSERT fails; (9) service role SELECT returns all rows; (10) service role INSERT bypasses policies. Each test uses `set_config('request.jwt.claims', ...)` to simulate different authenticated users. All 10 tests must pass in CI.
Document test setup/teardown to avoid polluting the database between runs.
Supabase's hosted PostGIS extension behaviour may differ from the local emulator for spatial RPC functions, causing bounding-box queries to return incorrect results or fail in production while passing locally.
Mitigation & Contingency
Mitigation: Write integration tests against the Supabase emulator from the start and run the same test suite against a staging Supabase project before merging. Use ST_DWithin and ST_MakeEnvelope in plain SQL first, validate with psql, then wrap as RPC.
Contingency: If PostGIS RPC proves unreliable, fall back to client-side bounding box filtering on a full fetch of consented mentor locations (acceptable for up to ~200 mentors per chapter) until the spatial query is stabilised.
OpenStreetMap tile usage may require attribution handling and rate limiting. Switching to Google Maps Flutter plugin mid-implementation would require significant rework of the map-provider-integration abstraction.
Mitigation & Contingency
Mitigation: Define the map-provider-integration abstraction interface before selecting the SDK so that the concrete implementation is swappable. Implement OSM first with correct attribution. Document Google Maps as the alternate with its API key setup steps.
Contingency: If OSM tiles are rejected by stakeholders or tile server limits are hit, activate the Google Maps Flutter plugin implementation behind the same interface without touching any UI or service code.
Incorrect RLS configuration could allow a coordinator to query mentor locations from a different organisation, constituting a GDPR data breach.
Mitigation & Contingency
Mitigation: Write dedicated RLS integration tests with two isolated test organisations and assert that cross-organisation queries return zero rows. Include these tests in CI. Have a second developer review all RLS policy SQL before migration is applied.
Contingency: If a cross-organisation data leak is discovered post-deployment, immediately disable the map feature via the organisation feature flag, revoke the affected Supabase RLS policy, and notify the data protection officer per the organisation's GDPR incident response procedure.