medium priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

Widget renders correctly when no notifications exist (unfiltered state): displays illustration placeholder, localized headline 'No notifications', and a generic sub-message
Widget renders correctly when a filter is active but yields no results: sub-message is contextually different (e.g., 'No notifications match this filter') and the 'Clear filter' CTA button is visible
CTA button is hidden when no filter is active
Tapping the CTA button triggers the provided onClearFilter callback without error
Widget uses only design token values for typography (font size, weight, color) and spacing — no hardcoded style values
Illustration placeholder renders at a fixed accessible size with a meaningful Semantics label (e.g., 'Empty notifications illustration')
Headline and sub-message are wrapped in Semantics widgets with appropriate labels for VoiceOver/TalkBack announcement
Widget passes Flutter accessibility audit (no contrast violations against dark and light backgrounds)
All user-facing strings are sourced from the app's localization layer (no hardcoded English strings)
Widget is stateless and accepts all data via constructor parameters (isFilterActive, onClearFilter)

Technical Requirements

frameworks
Flutter
flutter_localizations
data models
NotificationFilterState
performance requirements
Widget build time must not exceed 16ms (single frame budget)
No unnecessary rebuilds — widget should be const-constructible when no callbacks are provided
security requirements
No sensitive notification content displayed in empty state
ui components
Design token typography classes
Design token spacing constants
AppButton (existing reusable widget) for CTA
Semantics wrapper
SvgPicture or placeholder Container for illustration

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Keep the widget strictly stateless: accept `bool isFilterActive` and `VoidCallback? onClearFilter` as constructor parameters. Use the app's existing design token system for all spacing and typography — do not introduce hardcoded values. The illustration placeholder should be a fixed-size Container or SvgPicture with ExcludeSemantics wrapping unless a meaningful description can be provided.

Wrap the headline in a `Text` widget inside a `Semantics` node with `header: true` so screen readers announce it as a section heading. Place the widget in `lib/features/notifications/widgets/notification_empty_state.dart`. Since this widget has no dependencies on other tasks, it can be implemented and tested in isolation immediately.

Testing Requirements

Widget tests using flutter_test and WidgetTester. Test scenarios: (1) unfiltered empty state — verify headline text, sub-message text, illustration presence, CTA button absence; (2) filtered empty state — verify contextual sub-message, CTA button presence; (3) CTA tap — verify onClearFilter callback fires exactly once; (4) semantics tree — verify Semantics labels on illustration, headline, sub-message, and CTA button using SemanticsController; (5) const construction — verify widget can be instantiated as const when no callbacks provided. Target 100% branch coverage for this low-complexity widget.

Epic Risks (3)
high impact medium prob technical

Supabase Realtime channels on mobile networks can drop silently. If reconnection logic is flawed, users miss notifications without knowing it, undermining the audit-trail guarantee.

Mitigation & Contingency

Mitigation: Implement exponential-backoff reconnection with a maximum of 5 retries; expose a channel-status stream to the BLoC so it can trigger a full-fetch fallback when the channel reconnects after a gap.

Contingency: If Realtime reliability proves insufficient in production, fall back to polling the repository every 60 seconds as a background supplement to the Realtime channel.

high impact medium prob security

Coordinator and org-admin RLS expansions require joining user_roles and org_memberships tables. An incorrect policy could expose notifications to wrong users or block legitimate access entirely.

Mitigation & Contingency

Mitigation: Write dedicated RLS integration tests for each role (peer mentor, coordinator, org admin) using separate Supabase test projects. Review policies with the security checklist before merging.

Contingency: If an RLS defect is discovered post-deployment, disable the expanded-scope policy and revert to user-scoped-only access while a corrected migration is prepared and tested.

medium impact medium prob integration

JSONB payload structure may vary across notification types created by different Edge Functions (reminder, expiry, scenario, pause). Missing or renamed fields will cause runtime parse failures.

Mitigation & Contingency

Mitigation: Define a canonical NotificationPayload union type in a shared schema document. Each Edge Function must validate its payload against this schema before inserting. Add fallback parsing with default values in the domain model.

Contingency: Wrap all payload parsing in try/catch and log malformed payloads to a monitoring channel; render a generic notification item rather than crashing when the payload cannot be parsed.