high priority medium complexity backend pending backend specialist Tier 2

Acceptance Criteria

ProxyRegistrationService is implemented as a stateless class annotated with @riverpod (or @Riverpod(keepAlive: true) if required) and is injectable throughout the app
Service accepts a ProxyActivityRequest value object and returns a ProxyActivityResult (sealed class with Success and Failure variants)
Attribution validation is delegated to ActivityAttributionValidator before any write occurs; invalid requests return a typed failure with a specific ValidationError reason
On successful validation, a ProxyActivityRecord is persisted via ProxyActivityRepository with acting_coordinator_id and attributed_mentor_id correctly populated
ProxyAuditLogger.logProxySubmission() is called after each successful persistence, capturing actor, target mentor, activity type, timestamp, and submission channel ('single')
Duplicate detection queries proxy_activities for records matching (attributed_mentor_id, activity_type, date_window) and returns ProxyActivityResult.failure with reason DuplicateDetected when a conflict is found
The configurable date window for duplicate detection defaults to the same calendar day (UTC) and is injectable via a DuplicateDetectionConfig parameter
Service does not hold any mutable state; every method call is pure with respect to in-memory state
All Supabase errors (network, RLS violation, constraint violation) are caught, wrapped in a ProxyActivityResult.failure with a typed SupabaseError reason, and never rethrown as raw exceptions
Unit tests cover: successful submission, attribution validation failure, duplicate detected, Supabase write error, audit log failure does not roll back the write

Technical Requirements

frameworks
Flutter
Riverpod
flutter_bloc (for downstream BLoC integration)
apis
Supabase REST API (proxy_activities table insert)
Supabase Row Level Security policies for coordinator scope
data models
ProxyActivityRecord
ProxyActivityRequest
ProxyActivityResult
ProxyActivityStatus
ValidationResult
DuplicateDetectionConfig
performance requirements
Single record submission must complete (validation + write + audit) within 2 seconds on a standard mobile connection
Duplicate detection query must use a composite index on (attributed_mentor_id, activity_type, activity_date) to avoid full-table scans
Service must not block the UI thread; all async operations use Future and are awaited in the calling BLoC
security requirements
acting_coordinator_id must always be sourced from the authenticated Supabase session — never from caller-supplied input
RLS policies on proxy_activities must restrict writes to coordinators managing the attributed mentor's chapter/unit
Audit log entries must be written server-side via a Supabase Edge Function or database trigger to prevent client-side tampering
All PII fields (mentor name, coordinator name) must be excluded from client-side logs; only IDs are logged locally

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Model ProxyActivityResult as a sealed class (Dart 3 sealed keyword) with ProxyActivityResult.success(ProxyActivityRecord record) and ProxyActivityResult.failure(ProxyRegistrationError error) variants. ProxyRegistrationError should itself be a sealed class with subtypes: ValidationError, DuplicateDetected, RepositoryError, AuditError. Use Riverpod's Provider (not StateNotifier) since the service is stateless — expose it as a simple Provider. The duplicate detection query should be a single Supabase .select().eq().gte().lte().limit(1) call rather than fetching all records.

Guard against race conditions in bulk scenarios: duplicate detection is best-effort at the service level; the database unique constraint is the authoritative guard. Do not use transactions for the audit log write — log failure should never block the activity record being committed.

Testing Requirements

Write unit tests using flutter_test with mocked ProxyActivityRepository and ProxyAuditLogger (via Mockito or manual fakes). Test all sealed result variants: Success, ValidationFailure (each rule), DuplicateDetected, SupabaseError. Integration tests should verify the full Supabase write path against a local Supabase emulator or staging project, confirming RLS enforcement rejects out-of-scope coordinator writes. Minimum 90% branch coverage on the service class.

Include a test that confirms audit logging failure does NOT roll back the activity record (fire-and-forget audit semantics).

Component
Proxy Registration Service
service medium
Epic Risks (3)
high impact high prob scope

Partial failures in bulk registration — where some mentors succeed and others fail — create a complex UX state that is easy to mishandle. If the UI does not clearly communicate which records succeeded and which failed, coordinators may re-submit already-saved records (creating duplicates) or miss failed records entirely (creating underreporting).

Mitigation & Contingency

Mitigation: Design the per-mentor result screen as a primary deliverable of this epic, not an afterthought. Use a clear list view with success/failure indicators per mentor name, and offer a 'Retry failed' action that pre-selects only the failed mentors for resubmission.

Contingency: If partial failure UX proves too complex to deliver within scope, implement a simpler all-or-nothing submission mode for the initial release with a clear error message listing which mentors failed, and defer the partial-retry UI to a follow-up sprint.

medium impact medium prob technical

Submitting proxy records for a large group (e.g., 30+ mentors) as individual Supabase inserts may cause latency issues or hit rate limits, degrading the coordinator experience and potentially causing timeout failures that leave data in an inconsistent state.

Mitigation & Contingency

Mitigation: Implement the BulkRegistrationOrchestrator to batch inserts using a Supabase RPC call that accepts an array of proxy records, reducing round-trips to a single network call. Add progress indication using a stream of per-record results if the RPC supports it.

Contingency: If the RPC approach is blocked by Supabase limitations, fall back to chunked parallel inserts (5 records per batch) with retry logic, capping total submission time and surface a progress bar to manage coordinator expectations.

medium impact medium prob technical

Unifying state management for both single and bulk proxy flows in a single BLoC risks state leakage between flows — for example, a previously selected mentor list persisting when a coordinator switches from bulk to single mode — causing confusing UI states or incorrect submissions.

Mitigation & Contingency

Mitigation: Define separate, named state subtrees within the BLoC for single-proxy state and bulk-proxy state, with explicit reset events triggered on flow entry. Write unit tests for state isolation scenarios using the bloc_test package.

Contingency: If unified BLoC state becomes unmanageable, split into two separate BLoCs (ProxySingleRegistrationBLoC and ProxyBulkRegistrationBLoC) sharing only common events via a parent coordinator Cubit.