high priority medium complexity frontend pending frontend specialist Tier 13

Acceptance Criteria

ProxyRegistrationScreen is registered as a named GoRouter route (e.g. /proxy-registration) accessible only to coordinator and admin roles
When accessed by a non-coordinator role (peer mentor), the screen renders the existing no-access widget with an appropriate message and back navigation
When accessed by a coordinator role, the screen renders the full scaffold: AppBar with title 'Register Activity for Peer Mentor' and back button, scrollable body (SingleChildScrollView), and a sticky bottom submit button
Screen dispatches a LoadProxyRegistrationData event to ProxyRegistrationBloc on initState / first build
BLoC loading state renders a centered CircularProgressIndicator in the body area
BLoC error state renders an inline error message with retry action
BLoC loaded state renders the scrollable form area (placeholder content acceptable at this stage)
Sticky submit button is disabled while BLoC is in loading state
Screen handles back navigation correctly — pressing back does not leave orphaned BLoC instances
Screen is covered by a BlocProvider that scopes ProxyRegistrationBloc to the screen's lifetime

Technical Requirements

frameworks
Flutter
BLoC
GoRouter
data models
ProxyRegistrationState
ProxyRegistrationEvent (LoadProxyRegistrationData)
performance requirements
Screen must reach first meaningful paint within 300ms on a mid-range device
BLoC must not be recreated on every rebuild — use BlocProvider.value or context.read correctly
security requirements
Route guard must be enforced at the router level, not only in the widget tree, to prevent direct deep-link access by unauthorized roles
Role check must read from the authenticated session — never from local state that can be spoofed
ui components
AppBar with design token styling
SingleChildScrollView for scrollable body
AppButton (sticky, full-width) for submit
CircularProgressIndicator for loading state
Existing NoAccessWidget for role-gated state

Execution Context

Execution Tier
Tier 13

Tier 13 - 6 tasks

Can start after Tier 12 completes

Dependencies (21)
epic-proxy-activity-registration-orchestration-task-001 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-002 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-003 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-004 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-005 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-010 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-006 component Cross-Epic Component proxy-registration-screen depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-007 component Cross-Epic Component proxy-registration-screen depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-008 component Cross-Epic Component proxy-registration-screen depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-009 component Cross-Epic Component proxy-registration-screen depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-011 component Cross-Epic Component proxy-registration-screen depends on bulk-registration-service
epic-proxy-activity-registration-core-services-task-001 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-002 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-003 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-008 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-004 component Cross-Epic Component proxy-registration-screen depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-005 component Cross-Epic Component proxy-registration-screen depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-006 component Cross-Epic Component proxy-registration-screen depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-007 component Cross-Epic Component proxy-registration-screen depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-009 component Cross-Epic Component proxy-registration-screen depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-010 component Cross-Epic Component proxy-registration-screen depends on activity-attribution-service

Implementation Notes

Use GoRouter's redirect mechanism at the route definition level to enforce the role guard — this is more robust than checking inside the widget and prevents unauthorized users from seeing the screen even briefly. The BLoC should be provided via BlocProvider inside the route's builder, not globally, so it is disposed when the screen is popped. Use a Column with Expanded(child: SingleChildScrollView(...)) and a fixed-height submit button at the bottom — not a Stack — to avoid the sticky button obscuring scrollable content. The LoadProxyRegistrationData event should trigger loading of the coordinator's accessible peer mentors list from Supabase; even if the mentor selector widget is added in a later task, the data should be loaded here to avoid a second loading flash.

Testing Requirements

Widget tests (flutter_test): verify no-access state renders for peer mentor role (mock auth), verify scaffold renders for coordinator role, verify LoadProxyRegistrationData event is dispatched on screen build (use MockBloc), verify loading state shows progress indicator, verify error state shows retry button, verify submit button is disabled during loading. Integration test: navigate to route as coordinator via GoRouter test harness, verify screen mounts without exceptions. Unit test: ProxyRegistrationBloc LoadProxyRegistrationData event handling (initial state transition).

Component
Proxy Registration Screen
ui medium
Epic Risks (4)
medium impact high prob scope

The bulk registration screen combines pre-filled defaults, a dynamic multi-select participant list, per-participant conflict badges, and a batch submission confirmation — making it one of the most complex screens in the application. Scope creep or underestimated interaction complexity could cause the epic to exceed its estimate significantly.

Mitigation & Contingency

Mitigation: Implement the bulk screen in two vertical slices: (1) participant selection and form submission without conflict handling, (2) conflict badge rendering and override flow. Validate slice 1 with coordinators before building slice 2.

Contingency: If the full conflict review UI cannot be completed within the epic, ship the bulk screen with a simplified 'skip all duplicates' fallback mode and defer per-participant override toggles to a follow-up sprint.

medium impact medium prob technical

The proxy-registration-bloc must manage state across two distinct flows (single proxy and bulk) with branching conflict paths, intermediate buffering of bulk participant selections, and reliable state reset. Incorrect state transitions could leave the UI in a loading or stale-conflict state after submission.

Mitigation & Contingency

Mitigation: Model the BLoC state as a sealed class hierarchy with exhaustive pattern matching in the UI. Write state-machine unit tests that exercise every valid transition and assert that invalid transitions are no-ops. Use flutter_bloc's BlocObserver in debug builds to log all transitions.

Contingency: If BLoC state bugs surface in QA, introduce an explicit ResetToIdle event triggered on screen disposal to guarantee clean state, and add a 'Start over' affordance visible to the coordinator at any conflict step.

high impact medium prob technical

The typeahead peer mentor selector with multi-select mode may be difficult to operate with VoiceOver/TalkBack, particularly the dynamic search results list and the selected-chip removal controls, risking WCAG 2.2 AA non-compliance for screen reader users.

Mitigation & Contingency

Mitigation: Wrap all search result items and selected chips with explicit Semantics widgets providing role, label, and selected-state announcements. Test the selector with VoiceOver on iOS and TalkBack on Android during development, not only at QA time.

Contingency: If the multi-select typeahead cannot be made fully accessible within the sprint, provide an alternative flat scrollable list with checkboxes as a fallback mode, toggled by an accessibility-settings flag.

high impact medium prob security

The peer mentor selector must apply RLS chapter-scope filtering to show only mentors the coordinator is responsible for. If the Supabase query for the selector does not correctly join against the coordinator's chapter assignments, coordinators may see mentors from other chapters, violating data isolation.

Mitigation & Contingency

Mitigation: Implement the selector's data query using the same RLS-aware Supabase client used by the contact list feature, which already handles chapter-scope filtering. Write an integration test with a multi-chapter coordinator fixture asserting cross-chapter mentors are not returned.

Contingency: If a data isolation breach is discovered, immediately add a client-side chapter_id filter as a defence-in-depth measure and audit selector query logs for any unauthorised cross-chapter results.