high priority medium complexity backend pending backend specialist Tier 4

Acceptance Criteria

DuplicateActivityDetectorService class exists in `lib/features/duplicate_detection/domain/services/`
Service exposes getPendingDuplicates(String orgId) → Future<List<SuspectedDuplicate>> that delegates to repository
Service exposes resolveAsDuplicate(String duplicateId, String resolvedBy, String? notes) → Future<void> that updates status to confirmedDuplicate
Service exposes markAsFalsePositive(String duplicateId, String resolvedBy, String? notes) → Future<void> that updates status to falsePositive
Service exposes getDetectionConfig(String orgId) → Future<DuplicateDetectionConfig?> that returns org configuration
Business rule enforced: resolveAsDuplicate must set resolved_at to DateTime.now().toUtc() and resolved_by to the provided userId
Business rule enforced: once a record has status confirmedDuplicate or falsePositive, calling resolve again throws an AlreadyResolvedException
A Riverpod Provider (duplicateDetectorServiceProvider) is defined that constructs DuplicateActivityDetectorService with the injected repository provider
A Riverpod AsyncNotifier or FutureProvider (pendingDuplicatesProvider(orgId)) is defined for reactive UI consumption
Service methods propagate typed exceptions from repository — no swallowing of errors with empty catch blocks
Service is fully testable — DuplicateActivityDetectorRepository is injected, not instantiated inside the service

Technical Requirements

frameworks
Flutter
Riverpod (riverpod / flutter_riverpod)
Dart null safety
apis
DuplicateActivityDetectorRepository (task-009)
data models
SuspectedDuplicate
DuplicateDetectionConfig
DuplicateStatus enum
performance requirements
getPendingDuplicates must not cache stale data — each call fetches from repository
Riverpod provider should use AsyncNotifier pattern for auto-dispose to avoid memory leaks on navigation away
security requirements
resolvedBy parameter must be derived from auth state — service should accept it as parameter but callers must source it from the authenticated user session, not from user input
Service must not expose raw database errors to UI — wrap in domain exception types

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Use Riverpod's `ref.watch` pattern for the provider. Define `duplicateActivityDetectorRepositoryProvider` first (from task-009), then define `duplicateActivityDetectorServiceProvider` as a `Provider` that reads the repository provider. For the reactive pending duplicates, define `pendingDuplicatesProvider` as a `FutureProvider.family, String>` taking orgId as the family argument. The AlreadyResolvedException should be a simple Dart class extending Exception with a descriptive message.

Avoid adding caching or debouncing at this layer — that concern belongs in the BLoC or UI layer. Keep service methods thin: validate business rules, delegate to repository, return results.

Testing Requirements

Write unit tests with flutter_test and a mocked DuplicateActivityDetectorRepository. Test scenarios: (1) getPendingDuplicates delegates to repository and returns mapped list, (2) resolveAsDuplicate calls updateReviewStatus with confirmedDuplicate status and sets resolved_at timestamp, (3) markAsFalsePositive calls updateReviewStatus with falsePositive status, (4) calling resolveAsDuplicate on an already-resolved record throws AlreadyResolvedException, (5) repository exception propagates as-is from service methods, (6) getDetectionConfig returns null when repository returns null without throwing. Test Riverpod provider initialization in a ProviderContainer to verify provider graph builds without errors.

Component
Duplicate Activity Detector
infrastructure high
Epic Risks (3)
medium impact high prob technical

Fingerprint-based similarity matching may produce high false-positive rates for common activity types (e.g., weekly group sessions with the same participants), causing alert fatigue among coordinators and undermining trust in the detection system.

Mitigation & Contingency

Mitigation: Start with conservative, high-confidence thresholds (exact peer mentor match + same date + same activity type) before adding looser fuzzy matching. Allow NHF administrators to tune thresholds based on observed false-positive rates. Log all detection decisions for retrospective threshold calibration.

Contingency: Introduce a snooze mechanism allowing coordinators to dismiss false positives for a configurable period. Track dismissal rates per activity type and automatically raise the similarity threshold for activity types with high dismissal rates.

medium impact medium prob technical

A database trigger on the activities insert path adds synchronous overhead to every activity registration. For HLF peer mentors with 380 annual registrations or coordinators doing bulk proxy registration, this could create perceptible latency or lock contention.

Mitigation & Contingency

Mitigation: Implement the trigger as a DEFERRED constraint trigger (fires after the transaction commits) or replace it with a LISTEN/NOTIFY pattern that queues detection work asynchronously via an Edge Function, completely decoupling detection from the registration write path.

Contingency: Disable the synchronous trigger entirely and rely solely on the scheduled Edge Function for batch detection. Accept a detection delay of up to the scheduling interval (e.g., 15 minutes) in exchange for zero impact on registration latency.

medium impact medium prob dependency

The duplicate detection logic must be validated and approved by NHF before go-live, including agreement on threshold values and the review workflow. NHF stakeholder availability for sign-off may delay this epic's release independently of technical readiness.

Mitigation & Contingency

Mitigation: Gate the feature behind the NHF-specific feature flag so technical deployment can proceed independently of business approval. Involve an NHF administrator in threshold calibration sessions during QA, reducing the formal sign-off surface to policy and workflow rather than technical details.

Contingency: Release the detection system in 'silent mode' — flagging duplicates internally without surfacing notifications to coordinators — until NHF approves the workflow. Use the silent period to collect real data on false-positive rates and refine thresholds before activating notifications.