critical priority high complexity backend pending backend specialist Tier 1

Acceptance Criteria

PeerMentorAggregationService.fetchDetail(mentorId) launches all 4 repository fetches simultaneously via Future.wait and completes in near the time of the slowest single fetch, not the sum
Returned PeerMentorDetailModel contains merged data from all sources when all fetches succeed
If AssignmentHistoryRepository throws, the model is still returned with assignments set to an empty list and a non-null AssignmentFetchError in the per-source error map
If CertificationRecordRepository throws, the model is returned with certifications null/empty and a CertificationFetchError recorded — profile and activity data remain intact
If PeerMentorRepository (primary profile) throws, the service propagates a fatal PeerMentorProfileFetchError and returns no partial model
Per-source error map uses a typed enum or sealed class key (e.g., DataSource.assignments) so callers can distinguish which sources failed
Service is injectable via Riverpod provider and accepts all 4 repository dependencies via constructor for testability
Concurrency is verified by unit test confirming that two slow-responding mock repositories do not serialize their waits
No Supabase call is made twice for the same mentorId in a single fetchDetail invocation
Service does not swallow or rethrow exceptions that are not repository-level (e.g., type cast errors surface to the BLoC)

Technical Requirements

frameworks
Flutter
flutter_bloc
Riverpod
apis
Supabase REST/PostgREST — mentors, certifications, activity_logs, assignment_history tables
data models
PeerMentorDetailModel
CertificationRecord
MentorActivityLog
AssignmentHistory
AggregationResult<T>
performance requirements
Total fetch wall-clock time must not exceed max(individual fetch times) + 200 ms overhead
Each repository call must respect a 10-second timeout via Future.timeout to prevent indefinite hangs
No redundant Supabase round-trips within a single aggregation call
security requirements
Each repository call uses the authenticated Supabase client with RLS enforced — service must never bypass RLS by using service-role key on the client side
mentorId must be validated as a non-empty UUID before dispatching fetches to prevent malformed Supabase queries

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use `Future.wait([f1, f2, f3, f4], eagerError: false)` is NOT suitable here because it short-circuits on first error. Instead, wrap each repository call in a helper that returns `Either` (or a simple record `(T? value, Object? error)`) so Future.wait always resolves.

After awaiting, inspect each result and build the model. Distinguish fatal vs. non-fatal sources: PeerMentorRepository is fatal — if it fails, throw immediately. The other three are non-fatal — populate the error map.

Define a sealed class `AggregationError` with subtypes per source for type-safe error handling downstream. Use `AsyncValue` from Riverpod for each source result internally if you want to reuse Riverpod's error/loading pattern. Register the service as a `Provider` (not `FutureProvider`) because it exposes a method, not reactive state. Avoid caching at this layer — caching is the BLoC's responsibility.

Testing Requirements

Unit tests (flutter_test): (1) All-success scenario — mock all 4 repositories returning fixture data, assert merged model fields. (2) Assignment failure — mock AssignmentHistoryRepository to throw, assert model is returned with empty assignments and error map contains DataSource.assignments key. (3) Certification failure — same pattern. (4) Profile failure — assert service rethrows or wraps as fatal error, no partial model returned.

(5) Parallelism test — use Completer-based mocks that each complete after a delay; measure total elapsed time is < sum of delays. (6) Timeout test — mock one repository to never complete, assert Future.timeout fires within 10 s. Minimum 90% branch coverage on PeerMentorAggregationService. No integration tests against live Supabase in CI.

Component
Peer Mentor Profile Aggregation Service
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.