critical priority medium complexity testing pending testing specialist Tier 3

Acceptance Criteria

Single-conflict detection: given one existing active activity matching (mentorId, date, activityTypeId), service returns a list with exactly one ConflictMetadata entry
Multiple-conflict detection: given two existing activities matching the same key (submitted by two different coordinators), service returns both entries in the conflict list
No-conflict path: given no matching active activities, service returns an empty list (not null, not error)
Batch mode happy path: given a map of three keys where two have conflicts and one does not, service returns a map with correct per-key conflict lists and an empty list for the no-conflict key
Voided records excluded: given a matching activity row with status='voided', service does not include it in the conflict result
Repository mock is used — no real Supabase connection in any test
All tests pass with `flutter test` and produce no warnings
Test file follows project naming convention: proxy_duplicate_detection_service_test.dart

Technical Requirements

frameworks
Flutter
Dart
flutter_test
data models
activity
activity_type
performance requirements
All unit tests must complete in under 5 seconds total
security requirements
Test fixtures must not include real personnummer, real names, or real UUIDs from production data

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Dependents (28)
epic-proxy-activity-registration-orchestration-task-001 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-002 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-003 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-004 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-005 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-006 component Cross-Epic Component bulk-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-007 component Cross-Epic Component bulk-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-008 component Cross-Epic Component bulk-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-009 component Cross-Epic Component bulk-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-010 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-orchestration-task-011 component Cross-Epic Component bulk-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-001 component Cross-Epic Component bulk-participant-list depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-002 component Cross-Epic Component bulk-participant-list depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-003 component Cross-Epic Component bulk-participant-list depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-004 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-005 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-006 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-007 component Cross-Epic Component proxy-peer-mentor-selector depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-008 component Cross-Epic Component proxy-peer-mentor-selector depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-009 component Cross-Epic Component proxy-peer-mentor-selector depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-010 component Cross-Epic Component proxy-activity-form depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-011 component Cross-Epic Component proxy-activity-form depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-012 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-013 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-014 component Cross-Epic Component proxy-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-015 component Cross-Epic Component bulk-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-016 component Cross-Epic Component bulk-registration-screen depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-ui-task-017 component Cross-Epic Component bulk-registration-screen depends on proxy-duplicate-detection-service

Implementation Notes

Define a clear ActivityRepositoryInterface (abstract class) that proxy-duplicate-detection-service depends on so it can be mocked without real Supabase calls. Test data should use fixed UUID constants defined at the top of the test file for readability. For the voided exclusion test, ensure the repository mock returns a record with status='voided' and verify the service filters it out — this confirms the filtering logic is in the service layer, not assumed to be in the query. Use group() blocks to organise tests by scenario category (single, batch, edge cases).

Testing Requirements

Pure unit tests using flutter_test. Mock the ActivityRepository (or equivalent query interface) using Mockito or manual fakes. Test cases: (1) single conflict returned, (2) multiple conflicts same key, (3) empty result no match, (4) batch map with mixed results, (5) voided status excluded, (6) null/empty input to batch mode returns empty map without error. Use setUp() to initialize service with mock repository.

Verify mock.check() is called with the exact parameters passed to the service.

Component
Proxy Duplicate Detection Service
service medium
Epic Risks (2)
medium impact medium prob scope

Overly strict duplicate matching (exact date + type) may flag legitimate back-to-back sessions of the same activity type on the same day as duplicates, frustrating coordinators and undermining trust in the feature.

Mitigation & Contingency

Mitigation: Confirm with product owners whether the matching key should be (mentor_id, date, activity_type_id) only or should also consider duration and time-of-day. Document the chosen threshold in the service and surface it in the duplicate warning dialog for transparency.

Contingency: If false-positive rates are high in user testing, add a duration-window tolerance parameter to the detection query that can be tuned without code changes.

high impact low prob security

If the current session token is invalidated between the coordinator starting the proxy form and submitting it, the activity-attribution-service may fail to resolve the coordinator's user ID, causing a silent attribution error.

Mitigation & Contingency

Mitigation: Read the coordinator's user ID from the session at service call time rather than at form-open time. Validate the session is still active before committing the insert, and surface a clear re-authentication prompt if it has expired.

Contingency: If a mis-attributed record is detected post-submission, the audit log retains the original session metadata, allowing a corrective record to be created with accurate attribution.