high priority medium complexity backend pending backend specialist Tier 2

Acceptance Criteria

When the active org is HLF, the returned PeerMentorDetailModel has assignments set to null or empty and the model's assignmentsVisible flag is false
When the active org is Blindeforbundet, assignment data is present in the model if successfully fetched
When the active org is NHF, the model suppresses Blindeforbundet-specific encrypted mission fields
Filtering is applied after merge — raw data from repositories is never exposed pre-filter to the BLoC or UI
OrgLabelsNotifier is read via Riverpod ref.read (not ref.watch) inside the service method to capture current org at call time without making the service reactive
Adding a new org-specific filter requires changing only a single filter configuration map/class, not modifying the aggregation logic itself
Unit tests confirm that identical raw data produces different filtered models for HLF vs. Blindeforbundet org contexts
No org-specific business logic leaks into the UI layer — the widget receives an already-filtered model

Technical Requirements

frameworks
Flutter
Riverpod
data models
PeerMentorDetailModel
OrgLabels
OrgFilterConfig
performance requirements
Filtering is a synchronous, in-memory transform — zero additional network calls
Filter map lookup is O(1) by org ID
security requirements
Org context must be sourced from the authenticated session's org claim, not from a user-controllable parameter, to prevent privilege escalation
Filtered-out fields must be set to null/empty in the model, not merely hidden in the UI, so they cannot be accessed via debug tools

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Introduce an `OrgDataFilterConfig` class or const map keyed by org ID that lists which model fields are visible per org. This makes the filtering declarative and easy to audit. Example structure: `{ 'hlf': FieldVisibility(assignments: false, encryptedMissions: false), 'blindeforbundet': FieldVisibility(assignments: true, encryptedMissions: true) }`. Apply the config in a private `_applyOrgFilter(PeerMentorDetailModel raw, OrgLabels org)` method called at the end of `fetchDetail`.

Use `copyWith` on the model to produce the filtered version — do not mutate. Reading Riverpod state from a service class requires passing `Ref` or a resolved `OrgLabels` value into the method; prefer passing the resolved value to keep the service unit-testable without a full ProviderContainer.

Testing Requirements

Unit tests (flutter_test): (1) HLF org context — provide mock OrgLabelsNotifier with HLF org, assert assignments field is null/empty in output model. (2) Blindeforbundet context — same raw input, assert assignments present. (3) NHF context — assert Blindeforbundet-specific fields absent. (4) Filter config isolation — add a hypothetical new org filter config, assert it applies without modifying aggregation logic.

(5) Null-safety — assert filter does not crash when a non-fatal source already returned null data before filtering. All tests use fake OrgLabelsNotifier via ProviderContainer override. Minimum 85% branch coverage on the filter layer.

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.