Pathfinder Docs

Documentation Preview

Organization Modules & Tier System

Source: `docs/product/features/ORGANIZATION_MODULES.md`View on GitHub

Organization Modules & Tier System

Overview

This feature implements a modular access control system for the CRM. Organizations can have different subscription tiers that determine which CRM modules they can access. Administrators can also customize module access on a per-organization basis.

Date Implemented

December 23, 2025

Subscription Tiers

TierDefault ModulesDescription
BasicClients, IntakeEssential client management features
StandardClients, Intake, Resources, ReferralsFull CRM features with resource library
PremiumClients, Intake, Resources, Referrals, ReportsAdvanced features with analytics
EnterpriseClients, Intake, Resources, Referrals, ReportsFull platform access with priority support

Available Modules

ModuleDescriptionRoute
ClientsClient and household management/clients
IntakeClient intake forms and assessments/intake
ResourcesResource library and program management/resources
ReferralsReferral tracking and coordination/referrals
ReportsAnalytics and reporting dashboards/access-crm/reports
InsightsMap-first analytics hub — resource coverage, demand, data quality (gated by Reports module)/insights
Resource NavigatorEmbedded Resource Navigator theme and messaging customization/resource-navigator

How It Works

1. Tier-Based Access (Default)

When an organization is created, it's assigned a tier. By default, the organization has access to all modules included in that tier.

2. Custom Module Overrides

Administrators can override the default modules for an organization by:

  1. Go to Admin Panel > Organizations
  2. Click "Modules" on any organization card
  3. Enable "Custom modules" checkbox
  4. Toggle individual modules on/off
  5. Save changes

3. Access Control Flow


### 4. Resource Navigator Module Activation

Resource Navigator customization is module-gated per organization:
1. Range Lab admin enables `chatbot` in **Admin Panel > Organizations > Modules**.
2. Org admins can then access `/resource-navigator`.
3. If disabled, org admins see a locked page; Range Lab admins can still access for setup/testing.
User Request → Middleware → Module Check → Page Access
                  ↓
           Profile Lookup
                  ↓
           Role Check
                  ↓
     If org-scoped user:
           ↓
     Organization Module Check
           ↓
     Allow/Deny Access

Database Schema

Organizations Table Updates

ALTER TABLE organizations 
ADD COLUMN tier TEXT DEFAULT 'basic',
ADD COLUMN enabled_modules TEXT[] DEFAULT ARRAY[]::TEXT[];

-- Constraint for valid tiers
ALTER TABLE organizations 
ADD CONSTRAINT organizations_tier_check 
CHECK (tier IN ('basic', 'standard', 'premium', 'enterprise'));

Database Function

CREATE OR REPLACE FUNCTION has_module_access(
  p_org_id UUID,
  p_module_name TEXT
) RETURNS BOOLEAN

Key Files

Configuration

  • lib/modules.ts - Module and tier definitions, helper functions

Server Helpers

  • lib/supabase-server.ts - Server-side module access checks

API

  • app/api/user/modules/route.ts - Returns user's enabled modules

Components

  • app/components/ModuleContext.tsx - React context for module access
  • app/components/CRMSidebar.tsx - Conditionally shows modules in navigation

Middleware

  • middleware.ts - Route-level module access protection

Admin Interface

  • app/(crm)/admin/components/OrganizationModulesModal.tsx - Module management UI
  • app/(crm)/admin/organizations/AdminOrganizationsClient.tsx - Organization list with tier badges

Access Control Bypass

The following users bypass module checks:

  • Admin users (role === 'admin')
  • System-wide staff (role === 'staff' && !org_id)

Usage Examples

Check Module Access in Server Components

import { canAccessModule } from '@/lib/supabase-server'

export default async function ResourcesPage() {
  const hasAccess = await canAccessModule('resources')
  
  if (!hasAccess) {
    redirect('/unauthorized?reason=module_not_enabled')
  }
  
  // ... render page
}

Check Module Access in Client Components

import { useModules } from '@/app/components/ModuleContext'

function MyComponent() {
  const { hasModule, isLoading } = useModules()
  
  if (isLoading) return <Loading />
  
  if (!hasModule('resources')) {
    return <UpgradePrompt />
  }
  
  return <ResourcesList />
}

Get Enabled Modules

import { getEnabledModules } from '@/lib/modules'

// Get modules for an organization
const modules = getEnabledModules(org.tier, org.enabled_modules)
// Returns: ['clients', 'intake', 'resources', 'referrals']

Migration Guide

To apply this feature to an existing database:

  1. Run the migration:
psql -U your_user -d your_database -f database/migrations/DATABASE_MIGRATION_ORGANIZATION_MODULES.sql
  1. Existing organizations will default to 'basic' tier
  2. Update organization tiers as needed through Admin Panel

Security Considerations

  1. Defense in Depth: Module access is checked at multiple layers:

    • Middleware (route-level)
    • Page components (server-side)
    • Navigation (client-side, UI only)
  2. Server-Side Authority: The client-side ModuleContext is for UI purposes only. Actual access control is enforced server-side.

  3. API Protection: API routes should also check module access for org-scoped users.

Future Enhancements

  • Module usage analytics
  • Module trial periods
  • Automatic tier upgrades based on usage
  • Module feature flags within modules
  • Billing integration for tier changes

Use links in each imported doc to open its source.