Implement DuplicateDetectionBLoC & E2E Integration Tests
epic-duplicate-activity-detection-state-management-task-010 — Implement the DuplicateDetectionBLoC managing the full state machine: idle → checking → duplicate_found (with candidate list) → resolving → resolved / cancelled. Wire BLoC into the activity wizard save intercept, proxy registration path, and bulk registration consolidated summary flow. Connect analytics event emission and audit trail logging. Write end-to-end integration tests covering all four scenarios: self-registration, intentional same-day duplicate, proxy overlap, and coordinator queue resolution.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Model the BLoC state machine as a Dart sealed class hierarchy: DuplicateDetectionIdle, DuplicateDetectionChecking, DuplicateDetectionFound({required List
For bulk registration, detect the bulk context flag in the event and route duplicates directly to the coordinator queue rather than the bottom sheet. Analytics events should use a thin AnalyticsService abstraction (no direct SDK calls in BLoC). For E2E tests, use flutter_test integration_test package with a dedicated Supabase test project seeded via a setup script that inserts test organizations, users, and activities before each test scenario.
Testing Requirements
Unit tests: test all BLoC state transitions with mocked services. Test that proxy path sends peer mentor identity to detection service. Test that bulk registration batches duplicates instead of interrupting. Test analytics event emission for each resolution path.
Test concurrent CheckForDuplicates events are queued, not dropped. Integration tests (real Supabase test project): E2E scenario 1 — self-registration, no duplicate. E2E scenario 2 — same-day duplicate, KEEP_BOTH resolution, verify duplicate_reviewed=true in database and audit log entry exists. E2E scenario 3 — proxy overlap, REPLACE resolution, verify candidate deleted and new activity persisted.
E2E scenario 4 — bulk registration with 5 duplicates, coordinator bulk-dismisses, verify 5 audit log entries. Verify RLS prevents cross-organization data access in all scenarios. Minimum 90% branch coverage on BLoC.
For bulk registration with many participants, running duplicate checks sequentially before surfacing the consolidated summary could introduce a multi-second delay as each peer mentor is checked individually against the RPC. This degrades the bulk submission UX significantly.
Mitigation & Contingency
Mitigation: Issue all duplicate check RPC calls concurrently using Dart's `Future.wait` or a bounded parallel executor (max 5 concurrent calls to avoid Supabase rate limits). The BLoC collects all results and emits a single BulkDuplicateSummary state with the consolidated list.
Contingency: If concurrent RPC calls hit Supabase connection limits or rate limits, implement a batched sequential approach with a progress indicator showing 'Checking participant N of M' so the coordinator understands the delay is expected and bounded.
In proxy registration, the peer mentor's ID must be used as the duplicate check parameter, not the coordinator's ID. If the proxy context is not correctly threaded through the BLoC and service layer, duplicate checks will silently run against the wrong person, missing actual duplicates.
Mitigation & Contingency
Mitigation: Define a `SubmissionContext` model that carries the effective `peer_mentor_id` (distinct from `submitter_id`) and pass it explicitly through the BLoC event payload. The DuplicateDetectionService always reads peer_mentor_id from SubmissionContext, never from the authenticated user session.
Contingency: If SubmissionContext threading proves difficult to retrofit into the existing proxy registration BLoC, add an assertion in DuplicateDetectionService that throws a descriptive error when peer_mentor_id is null or matches the coordinator's own ID in a proxy context, making the bug immediately visible in testing.