Role-Based Access Control
Role-Based Access Control (RBAC)
ForestWatch implements a comprehensive Role-Based Access Control system that operates at two levels: Team Accounts and Projects.
Team Account Roles
Team accounts use the roles table with a hierarchy system. Lower hierarchy numbers indicate higher privileges.
| Role | Hierarchy | Description |
|---|---|---|
owner | 1 | Full control over the account |
manager | 2 | Can manage members and settings |
member | 3 | Basic access |
Hierarchy Rules
- Users can only manage members with a higher hierarchy number (lower privilege)
- Owners can manage all roles
- Managers can manage Members but not other Managers or Owners
Team Account Permissions
The app_permissions enum defines all team-level permissions (40+ total).
Complete Team Account Permissions Matrix
| Permission | Owner | Manager | Member |
|---|---|---|---|
| Account & Roles | |||
roles.manage | ✓ | - | - |
billing.view | ✓ | - | - |
billing.manage | ✓ | - | - |
settings.view | ✓ | ✓ | ✓ |
settings.manage | ✓ | ✓ | - |
members.view | ✓ | ✓ | ✓ |
members.manage | ✓ | ✓ | - |
invites.manage | ✓ | ✓ | - |
| Projects | |||
projects.view | ✓ | ✓ | ✓ |
projects.create | ✓ | ✓ | - |
projects.edit | ✓ | ✓ | - |
projects.delete | ✓ | - | - |
projects.manage | ✓ | ✓ | ✓ |
| Notifications & Alerts | |||
notifications.view | ✓ | ✓ | ✓ |
notifications.manage | ✓ | ✓ | - |
alerts.view | ✓ | ✓ | ✓ |
alerts.create | ✓ | ✓ | - |
alerts.edit | ✓ | ✓ | - |
alerts.delete | ✓ | - | - |
| Documents | |||
documents.view | ✓ | ✓ | ✓ |
documents.create | ✓ | ✓ | ✓ |
documents.edit | ✓ | ✓ | - |
documents.delete | ✓ | - | - |
| Tasks (Work Orders) | |||
tasks.view | ✓ | ✓ | ✓ |
tasks.create | ✓ | ✓ | ✓ |
tasks.edit | ✓ | ✓ | ✓ |
tasks.delete | ✓ | - | - |
tasks.approve | ✓ | ✓ | - |
tasks.assign | ✓ | ✓ | - |
| Crews | |||
crews.view | ✓ | ✓ | ✓ |
crews.manage | ✓ | ✓ | - |
| Profile | |||
profile.view | ✓ | ✓ | ✓ |
profile.edit | ✓ | ✓ | - |
| Templates | |||
templates.asset_types.view | ✓ | ✓ | ✓ |
templates.asset_types.manage | ✓ | ✓ | - |
templates.catalog.view | ✓ | ✓ | ✓ |
templates.catalog.manage | ✓ | ✓ | - |
templates.forms.view | ✓ | ✓ | ✓ |
templates.forms.manage | ✓ | ✓ | - |
| Other | |||
qr_reader.use | ✓ | ✓ | ✓ |
usage.view | ✓ | ✓ | - |
Project Roles
Projects use the project_role enum with 10 roles for forest management scenarios.
| Role | Description |
|---|---|
owner | Project creator with full permissions |
admin | Administrator (almost everything except billing.manage) |
manager | Project manager - manages members, tasks, and settings |
executor | Field executor - creates/edits assets, tasks, inspections |
investor | Investor - read access to financial and compliance data |
auditor | Auditor - read access plus create inspections for compliance |
technical | Technical advisor - updates assets, documents, inspections |
marketing | Marketing - access to public-facing information and documents |
member | Standard member with basic view and form fill access |
viewer | Read-only access |
Project Permissions
The project_permissions enum defines all project-level permissions (47 total).
Complete Project Permissions Matrix
| Permission | owner | admin | manager | executor | investor | auditor | technical | marketing | member | viewer |
|---|---|---|---|---|---|---|---|---|---|---|
| Assets | ||||||||||
assets.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
assets.create | ✓ | ✓ | ✓ | ✓ | - | - | - | - | - | - |
assets.edit | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | - | - | - |
assets.delete | ✓ | ✓ | - | - | - | - | - | - | - | - |
| Asset Profile | ||||||||||
assets.profile.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
assets.profile.edit | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | - | - | - |
| Asset Forms | ||||||||||
assets.forms.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ |
assets.forms.fill | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | - | ✓ | - |
| Asset Tasks | ||||||||||
assets.tasks.view | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ | - | ✓ | ✓ |
assets.tasks.create | ✓ | ✓ | ✓ | ✓ | - | - | - | - | - | - |
assets.tasks.edit | ✓ | ✓ | ✓ | ✓ | - | - | - | - | - | - |
assets.tasks.delete | ✓ | ✓ | - | - | - | - | - | - | - | - |
assets.tasks.approve | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
assets.tasks.assign | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
| Asset Inspections | ||||||||||
assets.inspections.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ |
assets.inspections.create | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ | - | - | - |
assets.inspections.edit | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | - | - | - |
assets.inspections.delete | ✓ | ✓ | - | - | - | - | - | - | - | - |
assets.inspections.approve | ✓ | ✓ | ✓ | - | - | ✓ | - | - | - | - |
| Notifications | ||||||||||
notifications.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
notifications.manage | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
| Alerts | ||||||||||
alerts.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
alerts.create | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ | - | - | - |
alerts.edit | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | - | - | - |
alerts.delete | ✓ | ✓ | - | - | - | - | - | - | - | - |
| Documents | ||||||||||
documents.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
documents.create | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | ✓ | ✓ | - |
documents.edit | ✓ | ✓ | ✓ | ✓ | - | - | ✓ | ✓ | - | - |
documents.delete | ✓ | ✓ | - | - | - | - | - | - | - | - |
| QR Reader | ||||||||||
qr_reader.use | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ | - | ✓ | - |
| Tasks | ||||||||||
tasks.view | ✓ | ✓ | ✓ | ✓ | - | ✓ | ✓ | - | ✓ | ✓ |
tasks.create | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
tasks.edit | ✓ | ✓ | ✓ | ✓ | - | - | - | - | - | - |
tasks.delete | ✓ | ✓ | - | - | - | - | - | - | - | - |
tasks.approve | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
tasks.assign | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
| Crews | ||||||||||
crews.view | ✓ | ✓ | ✓ | ✓ | - | - | - | - | ✓ | - |
crews.manage | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
| Profile | ||||||||||
profile.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
profile.edit | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
| Members | ||||||||||
members.view | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
members.manage | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
members.invite | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
| Settings | ||||||||||
settings.view | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
settings.manage | ✓ | ✓ | - | - | - | - | - | - | - | - |
| Billing | ||||||||||
billing.view | ✓ | ✓ | - | - | ✓ | ✓ | - | - | - | - |
billing.manage | ✓ | - | - | - | - | - | - | - | - | - |
Permission Helper Functions
ForestWatch provides SQL functions for permission verification at the database level.
Team Account Permission Check
-- Check if user has a specific team permission
SELECT public.has_team_permission(
'account-uuid'::uuid,
'projects.create'::app_permissions
);
-- Get all permissions for current user on a team
SELECT * FROM public.get_user_team_permissions('account-uuid'::uuid);Project Permission Check
-- Check if user has a specific project permission
SELECT public.has_project_permission(
'project-uuid'::uuid,
'assets.create'::project_permissions
);
-- Get all permissions for current user on a project
SELECT * FROM public.get_user_project_permissions('project-uuid'::uuid);Other Helper Functions
-- Check if user has a role on an account (role is optional)
public.has_role_on_account(account_id, role?)
-- Check if user is the primary owner of the account
public.is_account_owner(account_id)
-- Check if user can perform actions on another member
public.can_action_account_member(account_id, target_user_id)TypeScript Usage
Permission types are auto-generated and available via @kit/supabase/database:
import type { Database } from '@kit/supabase/database';
// Team account permissions
type AppPermission = Database['public']['Enums']['app_permissions'];
// Project permissions
type ProjectPermission = Database['public']['Enums']['project_permissions'];
// Project roles
type ProjectRole = Database['public']['Enums']['project_role'];Using @fw/permissions Package
The @fw/permissions package provides React hooks and server utilities for permission checking.
Client-Side Permission Check
import { useTeamPermission } from '@fw/permissions/hooks';
function CreateProjectButton({ accountId }) {
const { hasPermission, isLoading } = useTeamPermission(accountId, 'projects.create');
if (isLoading) return <Spinner />;
if (!hasPermission) return null;
return <Button>Create Project</Button>;
}Server-Side Permission Check
import { checkTeamPermission } from '@fw/permissions/server';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
async function TeamSettingsPage({ params }) {
const client = getSupabaseServerClient();
const canManage = await checkTeamPermission(client, params.accountId, 'settings.manage');
if (!canManage) return <AccessDenied />;
return <SettingsForm />;
}Declarative Permission Guard
import { PermissionGuard } from '@fw/permissions/components';
<PermissionGuard accountId={accountId} teamPermission="billing.manage">
<BillingSettings />
</PermissionGuard>See the technical documentation for complete API reference.
Inherited Access
Team owners and managers automatically inherit project access:
- Team Owner → Project Owner permissions on all team projects
- Team Manager → Project Manager permissions on all team projects
This inheritance is handled by the has_project_permission function.
Row-Level Security (RLS)
All tables use RLS policies to enforce access control at the database level:
- Users only see data they have access to
- Write operations are restricted based on permissions
- Related data inherits parent permissions
- Project-level access is controlled by
projects_membershipstable