Contact Chapter Repository
Component Detail
Description
Data access layer for the contact_chapters junction table in Supabase, providing CRUD operations for contact-to-chapter many-to-many relationships. Implements RLS-aware queries so coordinators only retrieve affiliations visible within their organization.
contact-chapter-repository
Summaries
This repository is the authoritative gateway to the data that defines which contacts belong to which chapters — a foundational relationship that underpins membership reporting, coordinator assignments, activity attribution, and duplicate detection across the entire platform. By encapsulating all access to this junction table in a single, RLS-aware component, the organization ensures that data visibility rules are enforced consistently regardless of which feature or workflow triggers a query. This reduces the risk of data leakage between organizations and gives compliance stakeholders confidence that membership data is accessed only by those authorized to see it.
The Contact Chapter Repository is a medium-complexity shared data component operating across both mobile and backend execution contexts, making it a foundational dependency for several higher-order components including the Multi-Chapter Membership Service and the Duplicate Activity Detection Service. Its delivery is on the critical path — work on those dependent services cannot be integration-tested until this repository is stable and verified against the Supabase schema. Testing must cover RLS policy behavior, which requires a multi-tenant test environment with distinct organization contexts. The countChaptersForContact method is particularly critical for the 5-chapter enforcement rule and must be tested under concurrent insert scenarios to validate it as a reliable constraint check.
This repository wraps the Supabase client for the contact_chapters junction table, translating between Flutter domain types (ContactChapter) and raw Supabase row data. All queries must respect Row Level Security policies — queries should not use service-role keys on the mobile client path, relying instead on the authenticated user's JWT so Supabase enforces org-scoped visibility automatically. The contactChapterExists() method should use a count query with .limit(1) rather than fetching full rows to minimize payload. countChaptersForContact() is used as a guard in the service layer and must be accurate under concurrent load — consider whether the enforcement should be moved to a Supabase database function with a row-level lock for production safety.
The repository is shared across three consuming services, so interface changes must be backward-compatible or coordinated across all consumers simultaneously.
Responsibilities
- Insert and delete rows in the contact_chapters junction table
- Query all chapters for a given contact_id
- Query all contacts for a given chapter_id
- Count affiliations per contact to enforce maximum limit
Interfaces
insertContactChapter(String contactId, String chapterId) → Future<void>
deleteContactChapter(String contactId, String chapterId) → Future<void>
fetchChaptersForContact(String contactId) → Future<List<ContactChapter>>
fetchContactsForChapter(String chapterId) → Future<List<ContactChapter>>
countChaptersForContact(String contactId) → Future<int>
contactChapterExists(String contactId, String chapterId) → Future<bool>
Relationships
Dependencies (1)
Components this component depends on
Dependents (2)
Components that depend on this component
Related Data Entities (2)
Data entities managed by this component