Register repositories and query objects via Riverpod providers
epic-multi-chapter-membership-handling-data-layer-task-009 — Expose ContactChapterRepository, CrossChapterActivityQuery, and DuplicateWarningEventLogger as Riverpod providers so that the service layer can consume them via dependency injection. Use Provider or AsyncNotifierProvider as appropriate. Wire each provider to the supabase-contact-chapter-adapter (217) provider from the foundation epic. Ensure providers are scoped correctly for multi-org tenant isolation.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Use `riverpod_annotation` if the project already uses code generation; otherwise declare providers manually to stay consistent with the existing codebase style. The adapter provider from the foundation epic (217) should be a `Provider
Avoid `StateNotifierProvider` here — these are stateless data-access objects, so plain `Provider` is appropriate. Add a `// coverage:ignore` annotation only for provider declarations that are purely wiring with no conditional logic.
Testing Requirements
Unit tests: use `ProviderContainer` with override for `supabaseContactChapterAdapterProvider` injecting a mock. Assert that each of the three providers resolves to the correct concrete type and that dependencies are wired in the expected order. Test that provider reads on an unauthenticated container surface an error rather than a null instance. Integration test: spin up a real Riverpod container against a local Supabase test instance and verify round-trip read through each provider.
Aim for 100% provider registration coverage and at least one positive and one error-path assertion per provider.
The Cross-Chapter Activity Query must avoid N+1 fetches across chapters. If naively implemented as a per-chapter loop, it will cause severe performance degradation for contacts affiliated with 5 chapters on poor mobile connections.
Mitigation & Contingency
Mitigation: Design the query as a single PostgREST join of contact_chapters and activities on contact_id from the start. Add a query performance test with 5 affiliations and 100+ activities to the integration test suite and enforce a maximum execution time threshold.
Contingency: If a performance regression is detected post-merge, introduce a Supabase RPC function (stored procedure) to move the join server-side, bypassing any client-side N+1 pattern.
If the Duplicate Warning Event Logger write fails silently (network error, RLS denial), audit entries will be missing from the Bufdir compliance record without the user being aware.
Mitigation & Contingency
Mitigation: Implement the logger with a local fallback queue: if the Supabase write fails, persist the event locally and retry on next launch. Log all failures to a verbose output channel.
Contingency: Add a reconciliation job that compares locally queued events to Supabase entries and re-submits any gaps. Provide a data export of the local queue for manual audit if reconciliation fails.
Two coordinators simultaneously adding the 5th chapter affiliation for the same contact could bypass the maximum enforcement check if both reads occur before either write completes.
Mitigation & Contingency
Mitigation: Enforce the 5-affiliation maximum as a database-level constraint (CHECK + trigger or RPC with a FOR UPDATE lock) rather than relying solely on application-layer validation.
Contingency: If a constraint violation is detected in production, run a corrective query to end the most recently created excess affiliation and notify the relevant coordinator.