medium priority low complexity documentation pending documentor Tier 3

Acceptance Criteria

CertificationExpiryRepository section documents every public method signature in Dart, including parameter types, return types (Future<List<MentorCertification>>), and the exact threshold semantics (60/30/7 days measured as calendar days from now at midnight UTC)
NotificationRecordRepository section documents insert, update, and read method signatures, the deduplication key definition (mentor_id + notification_type + threshold_days + date_window), and what happens on a duplicate insert attempt (upsert vs. exception)
FcmPushNotificationSender section documents all public methods, every error type that can be thrown or returned (NoTokenError, FcmDeliveryError, MaxRetriesExceededError), retry behavior (max attempts, back-off strategy), and what callers must handle
Expiry RLS policy section specifies: which Supabase tables the policy applies to, the policy SQL expression, which roles are permitted to read/write, and step-by-step instructions for an admin to temporarily override or disable the policy in a migration context
Dependency diagram is included (ASCII, Mermaid, or embedded image) showing the data-foundation interfaces as a layer consumed by orchestration-services components
Documentation is written in English, stored in the repository under docs/ or as inline dartdoc comments with a corresponding docs/certificate-expiry-data-foundation.md overview file
All method signatures in the documentation match the implemented code exactly (verified by a reviewer cross-checking against source files)

Technical Requirements

frameworks
Dart dartdoc (inline documentation)
Markdown (overview document)
apis
Supabase RLS policy SQL (documentation of existing policy, not creation)
Firebase Cloud Messaging HTTP v1 API (error code reference)
data models
MentorCertification
NotificationRecord
DeliveryAttempt
FcmToken
performance requirements
Documentation must be generated by dartdoc without warnings
security requirements
RLS policy documentation must not include production service role keys or passwords
Admin override instructions must note that override requires service role access and should be time-limited

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Write the primary documentation as dartdoc comments directly on the abstract classes / interfaces so that IDE tooling surfaces it inline. Supplement with a single docs/certificate-expiry-data-foundation.md file that provides the narrative overview, the dependency diagram, and the RLS policy section (which is SQL, not Dart, and does not belong in dartdoc). For the dependency diagram, a Mermaid flowchart is preferred because it renders natively in GitHub and most documentation sites. The RLS policy section should include the verbatim SQL of the CREATE POLICY statement alongside a plain-English explanation of each clause.

For the admin override section, document both the Supabase Dashboard UI path and the equivalent SQL (ALTER POLICY / DROP POLICY) so that it is actionable in both contexts.

Testing Requirements

No automated tests required for documentation itself. However, before merge, a peer review checklist must confirm: (1) every public method in each documented interface exists in the actual source code with a matching signature, (2) the RLS policy SQL snippet matches the policy deployed in the Supabase project, (3) the dependency diagram accurately reflects current task dependencies, and (4) dartdoc generates without errors or warnings when run against the annotated files.

Component
Certificate Expiry RLS Visibility Policy
infrastructure medium
Dependencies (4)
Add the three threshold query methods to CertificationExpiryRepository: getMentorsExpiringWithinDays(60), getMentorsExpiringWithinDays(30), and getMentorsExpiringWithinDays(7). Each method must use efficient date-range SQL via Supabase RPC or filter chaining, returning only mentors whose certificate expires within the specified window but have NOT already received a notification for that threshold. Optimize with composite indexes. epic-certificate-expiry-notifications-data-foundation-task-004 Add the hasNotificationBeenSentForThreshold(mentorId, thresholdDays) query method to NotificationRecordRepository to prevent duplicate notification dispatches. Implement the recordThresholdNotificationSent(mentorId, thresholdDays, notificationType) write method. Add a getUnreadCount(recipientId) convenience query for badge display. Ensure atomic upsert behavior to handle concurrent edge function invocations safely. epic-certificate-expiry-notifications-data-foundation-task-006 Add the core message delivery method sendPushNotification(recipientId, title, body, data) to FcmPushNotificationSender. Implement delivery tracking by persisting send attempts and FCM response statuses to Supabase. Add batch send support for sendBulkPushNotifications(recipients, payload) to handle coordinator broadcast scenarios. Implement retry logic with exponential backoff for transient FCM errors. epic-certificate-expiry-notifications-data-foundation-task-008 Write automated tests that verify the expiry RLS policy is enforced for coordinator role queries and public/unauthenticated queries. Confirm that expired mentor records are suppressed even when queried via the Flutter Supabase client. Test that active mentor records remain visible. Test that admin role access is not blocked by the policy. Verify that the policy cannot be bypassed by client-side filter manipulation. epic-certificate-expiry-notifications-data-foundation-task-010
Epic Risks (3)
high impact medium prob technical

The RLS policy predicate that checks certification_expiry_date and suppression_status on every coordinator list query could cause full table scans at scale, degrading response time for coordinator contact list screens across all chapters.

Mitigation & Contingency

Mitigation: Add a partial index on (certification_expiry_date, suppression_status) filtered to active mentors. Benchmark the policy predicate against a representative data set (500+ mentors) during development using EXPLAIN ANALYZE on Supabase staging.

Contingency: If the index does not resolve the performance issue, introduce a computed boolean column is_publicly_visible that is updated by the mentor_visibility_suppressor service and indexed separately, shifting the predicate cost to write time rather than read time.

medium impact medium prob integration

FCM device tokens become invalid when users reinstall the app or switch devices. If the token management strategy does not handle token refresh reliably, notification delivery will silently fail for a significant portion of the user base without surfacing errors.

Mitigation & Contingency

Mitigation: Implement the FCM token refresh callback in the Flutter client to upsert the latest token to Supabase on every app launch. Store token with a last_refreshed_at timestamp. The FCM sender should handle UNREGISTERED error codes by deleting stale tokens.

Contingency: If token staleness becomes widespread, add a token health check that forces re-registration during the expiry check edge function run by querying mentors whose token was last refreshed more than 30 days ago and triggering a silent push to prompt re-registration.

medium impact low prob integration

The certification expiry and notification record tables may have column naming or constraint conflicts with existing tables in the peer mentor status and certification management features, causing migration failures in shared Supabase environments.

Mitigation & Contingency

Mitigation: Audit existing table schemas for user_roles, certifications, and notification tables before writing migrations. Prefix new columns with expiry_ to avoid collisions. Run migrations against a clean Supabase branch environment before merging.

Contingency: If a conflict is found post-merge, apply ALTER TABLE migrations to rename conflicting columns and issue a hotfix migration. Communicate schema changes to all dependent feature teams via a shared migration changelog.