critical priority medium complexity frontend pending frontend specialist Tier 5

Acceptance Criteria

When ActivityAttributionValidator returns a DuplicateWarning, a modal dialog appears before any service write is attempted
The dialog body displays: the conflicting record's formatted date (dd MMM yyyy), formatted time range, and coordinator display name
Dialog has two actions: 'Cancel' (dismisses dialog, form stays intact, no write) and 'Proceed anyway' (triggers service call with override_duplicate: true in the payload)
After override confirmation the regular submit flow resumes (loading state, success navigation, error snackbar) as defined in task-009
The audit event payload emitted by ProxyRegistrationService includes override_duplicate: true and conflicting_activity_id when a coordinator overrides
Pressing the system Back button or tapping outside the dialog is treated as Cancel (no write)
The dialog is dismissed automatically if the coordinator navigates away from the screen before interacting
Non-duplicate submissions are unaffected — dialog is never shown when there is no conflict

Technical Requirements

frameworks
Flutter
BLoC/Cubit
flutter_bloc
apis
ActivityAttributionValidator.validate() — returns DuplicateWarning with conflicting record metadata
ProxyRegistrationService.submit(overrideDuplicate: bool)
data models
DuplicateWarning
ConflictingActivityRecord
ProxyRegistrationAuditEvent
performance requirements
Dialog must render within one frame of the DuplicateWarning state being emitted
security requirements
override_duplicate flag must be validated server-side; client cannot self-authorize override without the coordinator role
conflicting_activity_id must reference a real record — validated in Supabase RLS policy
ui components
AlertDialog or custom AppDialog
Conflicting record detail rows (date, time, coordinator name)
AppButton — Cancel (secondary)
AppButton — Proceed anyway (destructive/warning style)

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Model the duplicate warning as a distinct cubit state (ProxyRegistrationDuplicateWarning) that carries the ConflictingActivityRecord. In the BlocListener, show the dialog via showDialog() when this state is received. Pass 'proceed' / 'cancel' results back to the cubit via explicit cubit methods (cubit.confirmOverride() / cubit.cancelOverride()) — avoid passing BuildContext into the cubit. Use WillPopScope or PopScope (Flutter 3.14+) on the dialog to ensure back-press is treated as cancel.

The override flag should be stored in the cubit's pending submission data so it is included automatically when confirmOverride() re-dispatches the service call.

Testing Requirements

Unit-test the cubit: verify DuplicateWarning state is emitted when validator returns conflict, verify override payload is set when user confirms, verify clean cancellation resets state to Idle without service call. Widget-test: stub cubit to emit DuplicateWarning state and assert dialog appears with correct conflict data; simulate Cancel tap and assert no service call; simulate Proceed tap and assert service called with overrideDuplicate: true. Test back-button dismissal behaves as Cancel. Test that non-duplicate path never shows dialog.

Component
Proxy Registration Screen
ui medium
Epic Risks (3)
medium impact medium prob technical

The 2-hour window duplicate detection logic requires querying existing proxy records with compound key matching (mentor + date + activity type within time range). If the query is too broad it produces false positives that frustrate coordinators; if too narrow it misses genuine duplicates that corrupt Bufdir data.

Mitigation & Contingency

Mitigation: Define the duplicate detection window as a configurable parameter from the start. Prototype the Supabase query with representative data covering edge cases (midnight boundaries, different activity types same day, same activity type different mentors) before finalising the implementation.

Contingency: If the detection produces excessive false positives in UAT, allow coordinators to explicitly acknowledge and bypass the duplicate warning with a reason field, preserving safety while reducing friction.

high impact medium prob scope

If the proxy registration form does not clearly distinguish between the acting coordinator and the attributed mentor, coordinators may submit records attributing activities to themselves, causing inaccurate Bufdir reporting and potential funding issues.

Mitigation & Contingency

Mitigation: Conduct UAT with at least one real coordinator via TestFlight before release. Use distinct visual treatment (different card colours, explicit 'Registering on behalf of:' label) and require the confirmation screen to show both identities prominently.

Contingency: Add a mandatory confirmation checkbox on the confirmation screen that explicitly names the attributed mentor, preventing accidental self-attribution from slipping through.

high impact medium prob security

Coordinators with multi-chapter access must select an active chapter context before the mentor list is filtered correctly. If chapter scope resolution fails or is bypassed, cross-org proxy registrations could occur, violating data isolation between chapters.

Mitigation & Contingency

Mitigation: Reuse the existing active-chapter-state and hierarchy-service components established by the org hierarchy feature. Add a guard that blocks entry to the proxy flow if no chapter context is active, prompting chapter selection first.

Contingency: If the chapter resolution service is unavailable, default to the most restrictive scope (no mentors visible) and surface a clear error message rather than showing an unfiltered mentor list.