critical priority medium complexity backend pending backend specialist Tier 8

Acceptance Criteria

The detection loop iterates over all participants in BulkRegistrationRequest regardless of earlier conflict findings
Each participant is checked with their own peer_mentor_id plus the shared activity data
Participants with detected duplicates are collected into BulkConflictSummary.conflicts
Participants with no duplicates are collected into BulkConflictSummary.cleanParticipants
After the loop completes, if conflicts.isEmpty the service proceeds to batch insert; if non-empty it returns BulkRegistrationConflictsDetected
A single participant's detection failure (network error) does not abort the entire loop — it is treated as a conflict with error type 'detection_failed' and flagged for coordinator review
The loop handles lists of 1 to 50+ participants without performance degradation beyond linear growth
BulkConflictSummary.conflicts.length + BulkConflictSummary.cleanParticipants.length == BulkRegistrationRequest.participants.length (all participants accounted for)

Technical Requirements

frameworks
Flutter
BLoC
apis
Supabase RPC (per-participant duplicate check)
Supabase REST API
data models
BulkRegistrationRequest
BulkParticipantEntry
BulkConflictSummary
BulkParticipantConflict
performance requirements
Use Future.wait() with a controlled concurrency limit (max 5 parallel checks) to avoid Supabase rate limiting
Total detection time for 20 participants should not exceed 6 seconds on a standard mobile connection
Avoid sequential await-in-loop pattern — parallelize detection calls where possible
security requirements
Each detection call must be scoped to the coordinator's organization — no cross-org data leakage
peer_mentor_id list must be validated against the coordinator's org before the loop begins

Execution Context

Execution Tier
Tier 8

Tier 8 - 48 tasks

Can start after Tier 7 completes

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

Implementation Notes

Implement the loop using Future.wait() on a list of detection futures, not a sequential for-await loop. To avoid overwhelming Supabase with concurrent requests, batch participants into groups of 5 using a simple chunking utility (List> chunks = [...]). Collect results into two lists (conflicts, clean) using a fold or partition operation on the settled futures. Use a Result wrapper for each future so individual failures don't propagate to Future.wait().

A participant whose detection call throws should be added to conflicts with a special conflict_type: 'detection_error' — this surfaces the issue to the coordinator rather than silently dropping the participant. The cleanParticipants list is the authoritative input to the batch insert step — it must be computed here, not re-derived later.

Testing Requirements

Write unit tests using flutter_test with a mocked ProxyDuplicateDetectionService. Required test scenarios: (1) all participants clean → BulkConflictSummary has empty conflicts; (2) all participants duplicated → all in conflicts list, none in cleanParticipants; (3) mixed results → correct separation into conflicts and cleanParticipants; (4) one participant's detection throws → treated as conflict with error type, loop continues; (5) participant count invariant holds (conflicts + clean == total); (6) loop does not short-circuit on first conflict. Performance test: mock 50 participants with 100ms detection delay each — verify parallel execution completes significantly faster than 5000ms.

Component
Bulk Registration Service
service high
Epic Risks (3)
high impact low prob integration

If the Supabase batch RPC partial-inserts some records before encountering an error and does not roll back cleanly, the bulk service may report failure while orphaned records exist in the database, corrupting reporting data.

Mitigation & Contingency

Mitigation: Wrap the bulk insert in an explicit Supabase transaction via the RPC function. Write an integration test that simulates a mid-batch constraint violation and asserts zero records were written.

Contingency: If a partial-write incident occurs, the registered_by audit field allows identification and deletion of the orphaned records. Implement a coordinator-facing bulk submission status screen to surface any such anomalies.

medium impact medium prob scope

When a bulk submission of 15 participants has 4 duplicates, the aggregated conflict summary may be too complex for coordinators to process quickly, leading to blanket override decisions that defeat the purpose of duplicate detection.

Mitigation & Contingency

Mitigation: Design the conflict result type to support per-participant override flags, so the UI can present a clear list of conflicting participants with individual cancel/override toggles rather than a single global decision.

Contingency: If coordinator usability testing reveals the conflict review screen is too complex, simplify to a 'skip all conflicts and submit the rest' mode as an immediate fallback while a more granular UI is designed.

high impact low prob security

If the coordinator role check inside proxy-registration-service is inconsistent with the route-level guard, a regression in the guard could allow peer mentors to call the service directly via deep links, submitting records with incorrect attribution.

Mitigation & Contingency

Mitigation: Enforce role authorization at both the route guard level (coordinator-role-guard) and inside each service method independently. Write a security test that calls the service directly with a peer mentor session token and asserts rejection.

Contingency: If a bypass is discovered, immediately enable the server-side RLS policy as the final enforcement layer and audit any records written during the exposure window using the registered_by field.