critical priority medium complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

Panel renders a grouped list of chapters, each containing peer mentors whose certifications are expired or expiring within the configured threshold (default 30 days)
Each mentor row displays: mentor full name, certification expiry date formatted as dd.MM.yyyy, and a status badge ('Expired' in red-equivalent design token, 'Expiring Soon' in amber-equivalent)
A 'Send Reminder' button is present both per individual mentor row and as a bulk action per chapter group header
Individual reminder button is disabled while a reminder for that mentor is pending (pending state tracked in BLoC per task-013)
Chapter group bulk reminder button is disabled if all mentors in the group already have reminders sent or pending
Panel shows a skeleton loading indicator while data is being fetched from the BLoC state
Panel shows an empty state illustration and message ('No certifications require attention') when no expiring/expired mentors exist in scope
Panel respects the org hierarchy scope provided by AdminPortalBloc — switching scope triggers a reload
All text and interactive elements meet WCAG 2.2 AA contrast and touch-target requirements
Screen reader (TalkBack/VoiceOver) announces status badge values and button labels semantically using Flutter Semantics widget

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
flutter_test
apis
AdminCertificationService (internal)
AdminNotificationDispatcher (internal)
data models
CertificationRecord (mentorId, mentorName, chapterId, chapterName, expiryDate, status)
CertificationStatusPanelState
AdminPortalState
performance requirements
Grouped list must render within 300ms for up to 200 mentor records using ListView.builder
Chapter grouping logic must be performed in the BLoC or a pure function, not inside build()
Widget must not rebuild from unrelated AdminPortalBloc state changes
security requirements
Mentor personal data (name, expiry) must not be cached beyond the widget lifecycle
Reminder dispatch must include the admin's authenticated user ID for audit logging
Supabase RLS must restrict certification reads to admins with scope over the relevant org unit
ui components
CertificationStatusPanel (stateless BlocBuilder wrapper)
ChapterCertificationGroup (chapter header + mentor list)
MentorCertificationRow (name, expiry, badge, remind button)
CertificationStatusBadge (Expired / Expiring Soon variants)
CertificationEmptyState
CertificationLoadingSkeleton

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Group the flat certification list by chapterId inside a BLoC selector or a dedicated CertificationGroupingUseCase to avoid re-grouping on every build. Use BlocSelector to extract only the certification-relevant slice of AdminPortalState so unrelated state changes do not rebuild the panel. Model CertificationStatus as an enum (expired, expiringSoon) and derive badge colour from design tokens, not hardcoded hex values. For the 'Send Reminder' action, dispatch a typed event to the BLoC (task-013) rather than calling the service directly from the widget.

This keeps the widget purely declarative. HLF's certification tracking is a critical feature area — expiry date logic must treat 'today' as expired (not just past dates) and the configurable threshold should come from app config or design tokens rather than being hardcoded.

Testing Requirements

Write widget tests using flutter_test: (1) renders loading skeleton when BLoC state is loading; (2) renders empty state when certification list is empty; (3) renders grouped mentors with correct badge variants for expired vs expiring; (4) 'Send Reminder' taps dispatch SendCertificationReminder event to the BLoC; (5) per-mentor button is disabled when that mentor's reminder is in pending state; (6) chapter bulk button dispatches reminder for all mentors in that chapter. Use a MockAdminPortalBloc. Add golden tests for the status badge variants and the empty state to catch visual regressions. Verify Semantics tree includes accessible labels for badges and buttons.

Component
Certification Status Panel
ui medium
Epic Risks (3)
high impact medium prob technical

If org node selection in AdminStateBLoC does not correctly propagate to all dependent data streams (statistics, activity log, user list, certification panel), some panels may show data from the previously selected org scope, creating a confusing and potentially dangerous mixed-scope view.

Mitigation & Contingency

Mitigation: Model org node selection as a single source of truth in AdminStateBLoC. All downstream providers derive their query parameters from this single stream via Riverpod's watch pattern. Write integration tests that verify every data stream emits a reload event when the selected node changes.

Contingency: If scope propagation bugs are detected in QA, add an explicit full-state reset on org node change (clear all cached data and refetch from scratch) as a safe but less efficient fallback until the targeted propagation is fixed.

medium impact medium prob technical

The Admin Dashboard Screen must adapt its layout for Flutter Web (wider viewports, mouse interaction, larger grid) and mobile embedding. Flutter Web responsive layout support has historically required non-trivial workarounds, and the adaptive grid may introduce significant additional development time.

Mitigation & Contingency

Mitigation: Define breakpoints and grid behaviour in the design system before implementation. Use LayoutBuilder with explicit breakpoint constants rather than MediaQuery scattered across widgets. Prototype the web layout with a skeleton screen before implementing live data binding.

Contingency: If web layout proves intractable within sprint, deliver a mobile-first layout for all platforms initially and track a dedicated web-optimisation task for the next sprint.

high impact low prob security

A bug in the Role Assignment Panel's permission scope validation could allow an org_admin to assign roles beyond their authority (e.g., assigning super_admin to a user), representing a serious privilege escalation vulnerability.

Mitigation & Contingency

Mitigation: Enforce role assignment scope on both the client (disable unavailable roles in the panel UI) and the server (UserManagementService validates the target role is within the admin's permitted scope before persisting). Write security-focused tests that attempt out-of-scope role assignments and assert rejection.

Contingency: If an escalation vulnerability is discovered, immediately disable the role assignment panel via feature flag, revoke any incorrectly assigned roles, and deploy a server-side fix before re-enabling.