critical priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

LoadPeerMentorDetail event carries a non-nullable mentorId String field
RefreshPeerMentorDetail event carries a non-nullable mentorId String field and is structurally distinct from LoadPeerMentorDetail to allow separate handling if needed
PeerMentorDetailInitial is an empty state with no data fields
PeerMentorDetailLoading carries the current mentorId so the UI can show a skeleton specific to the right mentor
PeerMentorDetailLoaded carries: mentorId, PeerMentorDetailModel data, and an empty perSourceErrors map
PeerMentorDetailPartialError carries: mentorId, PeerMentorDetailModel data (partially populated), and a non-empty perSourceErrors map typed as Map<DataSource, Object>
PeerMentorDetailError carries: mentorId and a fatal error Object — no partial data
All events and states are implemented as sealed classes (Dart 3+) or with equatable for value equality
All state classes implement copyWith for immutability
No business logic exists in event/state class bodies — they are pure data containers

Technical Requirements

frameworks
Flutter
flutter_bloc
equatable
data models
PeerMentorDetailModel
DataSource (enum)
AggregationError
performance requirements
State classes are immutable value objects — no heap-allocated mutable fields
security requirements
State classes must not hold raw Supabase response objects — only domain model types

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use Dart 3 sealed classes: `sealed class PeerMentorDetailState {}` with `final class PeerMentorDetailLoaded extends PeerMentorDetailState {}` etc. This gives exhaustive switch checking at compile time, which is safer than an abstract class hierarchy. Use `package:equatable` for value equality on all states — this is required for BlocBuilder to correctly detect state changes and avoid unnecessary rebuilds. Do NOT use flutter_bloc's Equatable mixin on events unless you want event deduplication (usually undesirable for refresh events).

Keep the `DataSource` enum in a shared types file so both the service (task-002) and BLoC (task-005) reference the same enum without a circular import. Define the enum in the domain layer, not in either the service or BLoC file.

Testing Requirements

Unit tests (flutter_test): (1) Equatable/equality — two PeerMentorDetailLoaded instances with identical fields are equal. (2) copyWith — verify each field can be independently updated. (3) Type safety — assert that BlocBuilder compiles with the defined state hierarchy. (4) Sealed class exhaustiveness — in a switch on PeerMentorDetailState, the Dart analyzer warns if a case is missing (compile-time validation).

These are primarily compile-time and structural tests; logic coverage comes in task-005.

Component
Peer Mentor Detail BLoC
service medium
Epic Risks (3)
medium impact medium prob technical

The parallel Future.wait aggregation pattern may produce race conditions or incorrect merged state when some repositories resolve significantly faster than others, particularly if the BLoC receives a RefreshDetail event while a prior fetch is still in flight.

Mitigation & Contingency

Mitigation: Implement cancellation token pattern in the aggregation service to abort in-flight fetches on new events. Add BLoC test scenarios for rapid successive refresh events to validate state consistency.

Contingency: If race conditions persist, switch to a sequential-with-timeout fetch strategy for the first release and profile the performance impact before deciding whether parallel fetch optimization is worth the complexity.

medium impact medium prob integration

Integrating PeerMentorDetailScreenWidget into the existing StatefulShellRoute navigation structure may conflict with the Contacts tab's existing route hierarchy, requiring changes to navigation-route-config that could affect other teams' features.

Mitigation & Contingency

Mitigation: Coordinate with the Contact List and Contact Detail feature teams before adding the new route. Review the existing StatefulShellRoute configuration and confirm the peer mentor detail route can be nested under the Contacts branch without path conflicts.

Contingency: If route conflicts arise, temporarily implement the peer mentor detail as a modal overlay (push route) rather than a shell route child, preserving functionality while the navigation architecture conflict is resolved.

low impact high prob dependency

The course enrollment screen that the certification alert banner links to may not yet exist or may be implemented in a separate feature epic, leaving a broken navigation tap for HLF users in the initial release.

Mitigation & Contingency

Mitigation: Check the certification management feature implementation status before finalizing Epic 4 scope. If the enrollment screen is not available, design the tap action to open the HLF course enrollment URL in an external browser as an interim solution.

Contingency: Implement the CTA as a configurable action: if the enrollment route exists in the router, push it; otherwise, launch the configured org-specific enrollment URL via url_launcher, ensuring HLF users can always take action on expired certifications.