critical priority medium complexity integration pending fullstack developer Tier 4

Acceptance Criteria

Tapping 'Confirm' on the wizard's final step dispatches a ProxyActivityPayload containing recorded_by_user_id (coordinator's UUID) and peer_mentor_id (target mentor's UUID) to the Proxy Registration Service
On successful service response, the wizard closes and the user is navigated back to the previous screen; a success snackbar/toast is shown
On service failure (network error, validation error, Supabase RLS rejection), the wizard remains open on the confirmation step and an inline error message is rendered below the confirm button without clearing any form state
Duplicate detection warnings surfaced by the service are displayed as non-blocking inline banners; the coordinator can still proceed after acknowledging
The confirm button is disabled and shows a loading indicator while the submission is in progress to prevent double-submission
If the user navigates away mid-submission (back gesture), the in-flight request is cancelled and no partial state is persisted
Submission failures are logged with structured context (peer_mentor_id, error code, timestamp) for debugging; no PII is logged
The ProxyActivityPayload is validated client-side (non-null required fields) before dispatch to avoid unnecessary API round-trips
RLS-rejected submissions (403/401) surface a user-facing message 'You do not have permission to register activities for this mentor' rather than a generic error

Technical Requirements

frameworks
Flutter
BLoC
Riverpod
apis
Supabase Edge Functions (proxy activity submission endpoint)
Supabase PostgreSQL 15 (activity table RLS)
data models
activity
assignment
performance requirements
Submission round-trip must complete within 3 seconds on a 4G connection
Loading state must be visible within 100ms of user tapping confirm
security requirements
recorded_by_user_id must be derived from the authenticated session JWT — never accept it from UI state alone
Supabase RLS enforces that coordinators can only submit on behalf of mentors in their organisation
Service role key must never be used client-side; all writes go through the authenticated user's JWT
ProxyActivityPayload must not include any PII fields beyond necessary UUIDs
ui components
Confirmation step widget within proxy activity wizard
Inline error banner widget
Loading/disabled button state
Success snackbar/toast

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Use a BLoC or Cubit to manage the submission lifecycle (idle → loading → success/failure). The confirm button should emit a SubmitProxyActivity event. In the BLoC, call the Proxy Registration Service and emit ProxySubmissionSuccess or ProxySubmissionFailure states. In the widget, use BlocListener to trigger navigation on success and BlocBuilder to render the inline error on failure — never mix navigation logic inside BlocBuilder.

Derive recorded_by_user_id from Supabase Auth's currentUser.id at submission time, not from wizard state, to prevent tampering. For the error banner, use a conditional widget below the CTA that appears only when the state is ProxySubmissionFailure; do not use a dialog as it breaks the 'do not close wizard' requirement. Cancel in-flight requests using a CancelToken pattern or by disposing the BLoC on page pop.

Testing Requirements

Unit tests: test BLoC/Cubit event handling for submission success, submission failure (network), submission failure (RLS 403), and duplicate warning acknowledgement. Mock the Proxy Registration Service interface. Integration tests: verify that the correct ProxyActivityPayload (with coordinator's user_id and target mentor_id) is sent to the service. Widget tests: confirm loading indicator appears on confirm tap, inline error renders on failure, wizard does not close on failure, wizard closes and navigates back on success.

E2E (flutter_test): simulate a full proxy wizard flow ending in a successful submission and verify navigation outcome. Test coverage target: ≥85% on the confirmation step widget and its BLoC.

Component
Proxy Activity Wizard
ui medium
Epic Risks (3)
medium impact medium prob scope

If the batch insert RPC returns a mix of successes and failures (e.g., 3 of 10 mentors fail due to constraint violations that slipped through application-level duplicate detection), the confirmation screen result state becomes ambiguous. A coordinator who sees '7 of 10 succeeded' may not know whether to manually register the 3 failures, retry, or escalate — leading to either duplicate registrations or silent underreporting.

Mitigation & Contingency

Mitigation: Design the Bulk Registration Service to return a strongly typed BulkRegistrationResult with per-mentor RegistrationOutcome (success | duplicate_detected | constraint_violation | permission_denied). Design the result screen to list each failed mentor with a specific, plain-language reason and a one-tap 'Retry for this mentor' action that pre-fills the activity wizard with the batch template for that individual.

Contingency: If per-mentor retry UI is too complex to deliver within the epic scope, fall back to displaying failed mentors with their error codes and instructing coordinators to use single-proxy mode for the failures. Document this as a known limitation in release notes and create a follow-up ticket for per-mentor retry in the next sprint.

medium impact medium prob dependency

The Proxy Activity Wizard must reuse the existing activity wizard step widgets (type, date, duration, notes) while injecting a proxy attribution banner and a different submission payload builder. If the existing wizard is not designed for composability, the proxy variant may require forking the widget tree, creating two maintenance-diverging codebases that will drift out of sync when the base wizard is updated (e.g., new activity types added, new mandatory fields).

Mitigation & Contingency

Mitigation: Before implementing the Proxy Activity Wizard, audit the existing activity wizard's architecture. If steps are already extracted as independent StatelessWidget/ConsumerWidget classes, compose them directly with a wrapping Column that injects the attribution banner. If they are tightly coupled inside a parent widget, refactor the existing wizard to accept a nullable ProxyContext parameter before starting the proxy variant — this refactor should be a prerequisite task in this epic.

Contingency: If refactoring the base wizard is blocked by unrelated in-flight work on that component, implement the proxy wizard as a full fork but create a shared StepWidgets library file that both the base wizard and proxy wizard import. Schedule a deduplication refactor as a tech-debt ticket in the next planning cycle.

medium impact medium prob technical

The bulk registration flow spans three sequential screens (multi-select → activity form → confirmation → result) with shared mutable state: the selected mentor list, the activity template, the per-mentor duplicate warnings, and the final submission result. Managing this state across screens without a well-designed Bloc risks state leaks, stale duplicate warning data after mentor removal, and confirmation screen inconsistencies if the user navigates back and changes the mentor selection.

Mitigation & Contingency

Mitigation: Define a single BulkRegistrationBloc (or Cubit) with explicit state transitions covering: MentorsSelected → ActivityTemplateCompleted → DuplicatesChecked → ConfirmationReady → Submitting → SubmissionResult. Each backward navigation event (e.g., 'Back' from confirmation to mentor selection) dispatches a ResetToMentorSelection event that clears downstream state. Unit test every state transition with edge cases including empty mentor list, all mentors having duplicates, and network failure during submission.

Contingency: If state management complexity causes persistent bugs in testing, simplify by passing state explicitly through Navigator arguments (immutable snapshots per screen) rather than a shared Bloc. This reduces flexibility but eliminates cross-screen state mutation bugs.