critical priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

MentorLocationService is defined as an abstract class (or Dart abstract interface class) with exactly three methods: fetchMentorsInBoundingBox, getMentorsSortedByDistance, clearCache
fetchMentorsInBoundingBox(BoundingBox box, FilterCriteria criteria) returns Future<Either<MentorLocationFailure, List<MentorLocation>>> or equivalent result type
getMentorsSortedByDistance(Coordinates origin, FilterCriteria criteria) returns Future<Either<MentorLocationFailure, List<MentorLocation>>>
clearCache() returns Future<void> — no failure return needed (cache failures are silent/logged)
MentorLocationFailure is a sealed class with four subtypes: ConsentCheckFailure, NetworkFailure, CacheFailure, ValidationFailure — each carrying a message field and appropriate context fields (e.g., NetworkFailure has statusCode)
All types are in lib/features/geographic_map/domain/ with no Flutter framework imports
The interface file includes a Dart doc comment on each method describing its contract, error conditions, and consent enforcement responsibility
A fake/stub implementation FakeMentorLocationService is provided in test/fakes/ for use by BLoC tests in subsequent tasks

Technical Requirements

frameworks
Dart (domain layer — no Flutter imports)
fpdart or dartz for Either (if used by project)
Riverpod (interface registered as abstract provider)
data models
MentorLocation
FilterCriteria
BoundingBox
Coordinates
MentorLocationFailure subtypes
performance requirements
Interface definition only — no runtime performance impact
security requirements
Interface contract must document that implementations MUST NOT return MentorLocation entries with consentStatus != granted — enforcement is at the implementation level but the contract must state this explicitly

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use Dart's abstract interface class keyword (Dart 3+) rather than abstract class to signal that this is a pure interface with no default implementations. Define the sealed failure hierarchy in a separate file mentor_location_failure.dart alongside the interface. Choose Either over exceptions for all async methods — this forces callers (BLoCs) to handle failures explicitly and aligns with functional patterns common in Flutter BLoC projects. If the project does not yet use fpdart/dartz, define a lightweight Result type locally to avoid the dependency.

The FakeMentorLocationService should expose a call log so BLoC tests can assert fetchMentorsInBoundingBox was called with the expected arguments.

Testing Requirements

No tests required for the interface itself. However, create FakeMentorLocationService in test/fakes/fake_mentor_location_service.dart that implements MentorLocationService with configurable responses (e.g., setNextResponse(Either result)).

This fake will be used by all downstream BLoC tests. Write one smoke test confirming FakeMentorLocationService correctly implements all three method signatures at compile time.

Component
Mentor Location Service
service high
Epic Risks (2)
medium impact medium prob technical

The dual BLoC state machines (map view state + filter state) may introduce subtle synchronisation bugs where filter changes do not correctly re-trigger viewport queries, causing stale data to appear on the map.

Mitigation & Contingency

Mitigation: Define all BLoC state transitions in a state diagram before implementation. Use flutter_bloc's BlocObserver in development mode to log every state transition. Write explicit unit tests for filter-change → re-query transitions.

Contingency: If state synchronisation bugs appear in integration testing, refactor to a single unified BLoC that owns both map viewport state and filter state, eliminating cross-BLoC dependencies.

low impact medium prob scope

Cached mentor location data may become stale (mentors move, pause, or revoke consent) and coordinators in offline mode could be shown incorrect mentor information, leading to wasted outreach.

Mitigation & Contingency

Mitigation: Display a clear timestamp on cached data indicating when it was last synced. Set cache TTL to 24 hours and show an 'offline — data from [date]' banner. Revoked consent removes the mentor from the cache on next successful sync via contact-cache-sync-repository.

Contingency: If cache staleness causes user complaints, reduce TTL to 4 hours and implement background sync on app foreground. Accept that very-recently-revoked mentors may appear briefly in offline mode — document this as a known limitation in the privacy policy.