Configure Supabase RLS policies for consent table
epic-geographic-peer-mentor-map-consent-privacy-task-005 — Write and apply Row Level Security policies on consent_grants and consent_audit_log tables so that a peer mentor can only read and modify their own consent record, coordinators can read consent status for mentors in their chapter, and no role can delete audit log entries. Policies must be tested against all three organisation roles.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Write policies as a numbered SQL migration file (e.g., 0012_consent_rls_policies.sql) using Supabase migration conventions. Define separate named policies per operation (SELECT, INSERT, UPDATE) rather than combined USING + WITH CHECK in one policy — this makes auditing clearer. For the coordinator chapter-scoped SELECT, use a subquery: EXISTS (SELECT 1 FROM contact_chapter cc WHERE cc.contact_id = consent_grants.mentor_id AND cc.org_unit_id = (auth.jwt()->>'chapter_id')::uuid). Ensure the JWT custom claims hook sets chapter_id and role for every session token.
Document the service role bypass explicitly in a comment in the migration file so future developers understand it is intentional. After applying, verify with \d+ consent_grants in psql to confirm RLS is enabled.
Testing Requirements
Write a dedicated SQL test script (or use pgTAP / Supabase test helpers) that: (1) creates three test users with roles mentor, coordinator, admin and assigns them to the same org/chapter, (2) seeds consent_grants with one row per mentor, (3) asserts each SELECT/INSERT/UPDATE/DELETE operation returns expected rows or raises insufficient_privilege for each role. Include negative tests: coordinator attempting DELETE on consent_grants must fail, mentor attempting SELECT on another mentor's row must return empty. Run tests in CI against a local Supabase stack (supabase start). Coverage: all 6 policy branches exercised.
Document expected results in a policy-test-results.md file.
If the privacy policy text or consent terms change after mentors have already opted in, existing consent records may become legally insufficient, requiring re-consent from all opted-in mentors which could temporarily reduce map coverage.
Mitigation & Contingency
Mitigation: Store a consent_version field on every consent record. Implement a consent version check in location-consent-service that compares the stored version against the current policy version from location-privacy-config and flags stale consents for re-consent prompting.
Contingency: If a policy update invalidates existing consents, suppress affected mentors from the map, queue them for re-consent notification via the existing in-app notification system, and restore map visibility only after new consent is recorded.
A poorly designed consent dialog may lead to low opt-in rates, reducing map utility for coordinators to the point where the feature delivers insufficient value to justify maintenance cost.
Mitigation & Contingency
Mitigation: Follow plain-language writing guidelines from the cognitive accessibility feature. User-test the dialog with 2-3 peer mentors from Blindeforbundet before implementation is finalised. Ensure the dialog explains the benefit to the mentor, not just the data collection facts.
Contingency: If opt-in rate after launch is below 40%, conduct a targeted usability study and iterate on dialog copy and layout. The coordinator can also send a bulk opt-in invitation notification (per the user story) to non-consenting mentors.