Services Directory
Location: src/services/
Purpose: Server-side data access layer that wraps Supabase queries and access control. Returns the standardized QueryResponse shape ({ message, error, data }) defined in src/types/common.ts.
Structure
services/
├── accessCheck/ # Route + permission gating
│ ├── accessCheck.ts # Returns QueryResponse with current permissionKeys for a (team, campaign?) scope
│ ├── getRoutePermissions.ts # Cached snapshot loader (unstable_cache, tagged permissions-${userId})
│ └── requireAccess.ts # Server-side guard; redirect()s to /no-access on failure
│
├── campaign/ # Campaign data services
│ ├── checkIfAlreadyActiveRate.ts
│ ├── checkInviteToken.ts
│ ├── fetchRateRecordEdit.ts
│ ├── fetch_campaign_circulator_view.ts
│ ├── fetch_campaign_format_view.ts
│ ├── fetch_rate_campaigns.ts
│ ├── fetch_transaction_campaigns.ts
│ ├── fetch_turn_in_campaigns.ts
│ ├── getAllCampaigns.ts
│ ├── getCampaignBySlug.ts
│ ├── getCampaigns.ts
│ ├── getCampaignsForUser.ts
│ ├── getCampaignSlugSuperAdmin.ts
│ └── getUniqueColumns.ts
│
├── credentials/
│ └── fetchCredentialsRecordEdit.ts
│
├── dashboards/ # Configurable per-campaign dashboards
│ ├── fetchDashboardList.ts
│ └── fetchDashboardRecord.ts
│
├── permission-sets/ # "Responsibilities" (permission-set bundles)
│ ├── fetchCampaignPermissionSets.ts
│ ├── fetchPermissionAllSets.ts
│ ├── fetchPermissionSetEdit.ts
│ └── fetchTeamPermissionSets.ts
│
├── permissions/ # Permission keys + roles
│ ├── fetchPermissionKeyEdit.ts
│ ├── fetchPermissionKeysList.ts
│ ├── fetchRoleEdit.ts
│ ├── fetchRoles.ts
│ ├── fetchRolesForTeam.ts
│ └── regionsForTeam.ts
│
├── petitions/ # Petition + signature workflow data
│ ├── createNewPetition.ts
│ ├── getDefaultCountyByUser.ts
│ ├── getLastestValueByUserInPetitions.ts
│ ├── getPetitionById.ts
│ ├── getPetitionFormatById.ts
│ ├── getPetitionFormatForEdit.ts
│ ├── getPetitionsFormatForCampaign.ts
│ ├── getPetitionsForUser.ts
│ ├── getPreviousBlockListOfPetition.ts
│ ├── getPreviousSelectedFormat.ts
│ ├── getRecentCirculators.ts
│ └── getSessionBasedTurnInDate.ts
│
├── regions/
│ └── fetchRegionRecordEdit.ts
│
├── roles/
│ └── getUserRoleHierarchyLevelForTeam.ts # Cached lookup of roles.hierarchy_level for the current user in a team
│
├── teams/ # Team / sub-team / member services
│ ├── checkMemberToken.ts
│ ├── fetchSubTeams.ts
│ ├── fetchTeamMatrixAssignments.ts
│ ├── fetchTeamMembersWithSearch.ts # Excludes the calling user; supports name/email search
│ ├── getMemberToken.ts
│ ├── getSubTeamById.ts
│ ├── getSubTeamForEdit.ts
│ ├── getTeamBasicsForAdminInvite.ts
│ ├── getTeamById.ts
│ ├── getTeamForEdit.ts
│ ├── getTeamMemberForEdit.ts
│ └── getUserTeams.ts
│
├── transactions/
│ ├── fetchCirculatorUsers.ts
│ └── fetchTransactionRecordEdit.ts
│
├── turnInRecord/
│ └── fetchTurnInRecordEdit.ts
│
└── user/
├── getAuthUser.ts
├── getUserByEmailClient.ts
└── getUserList.ts
Service Characteristics
- Server-only: services are imported by Server Components, Route Handlers, and Server Actions. They use the SSR Supabase client from
src/lib/supabase/server.ts. QueryResponsereturn shape:{ message: string; error: boolean; data: any }.- Caching where it matters:
accessCheck/getRoutePermissions.tsandroles/getUserRoleHierarchyLevelForTeam.tsuseunstable_cachewithrevalidate: 3600and per-user tags so a singlerevalidateTagcall invalidates everything.
- Access-control bedrock:
accessCheck/is the canonical place to ask "does this user have access to this team/campaign and these permission keys?". Seecomplex-logic/access-controlfor usage.