Implement batch attribution enforcement
epic-proxy-activity-registration-core-services-task-005 — Extend activity-attribution-service with a batch method that applies attribution enforcement across a list of proxy activity records in a single operation. Each record in the batch must have registered_by and attributed_to populated before the batch is submitted. Failed attribution on any single record must be reported per-record without aborting the entire batch, supporting partial success in bulk registration flows.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Implement as an extension of SupabaseActivityAttributionService. The batch method should follow a clear two-phase approach: Phase 1 (synchronous) — iterate all records, override registered_by from auth session, run validation, split into validRecords and failedRecords. Phase 2 (async) — if validRecords is non-empty, call supabase.from('activities').insert(validRecords.map((r) => r.toJson()).toList()). On insert success, populate succeeded with the returned rows.
On insert exception, move all validRecords to failed with the persistence exception. The BatchAttributionResult and BatchAttributionFailure models should be defined in the domain layer as part of task-001 or as a small addendum here. Avoid wrapping the batch insert in a try-catch that silently swallows errors — always surface exceptions via BatchAttributionFailure so callers know what happened.
Testing Requirements
Unit tests: empty batch, all records valid and inserted, all records fail validation, mixed valid/invalid batch (verify correct split), batch size limit exceeded, Supabase insert failure moves all to failed list, auth session override applied to every record. Verify that a valid batch uses exactly one Supabase insert call. Integration test: submit a mixed batch against Supabase test project and verify database state matches succeeded list only. Test that failed records are not partially inserted.
flutter_test with mocktail. 85%+ branch coverage.
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.
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.