Global WatchGlobal Watch Docs
Features

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.

RoleHierarchyDescription
owner1Full control over the account
manager2Can manage members and settings
member3Basic 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

PermissionOwnerManagerMember
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.

RoleDescription
ownerProject creator with full permissions
adminAdministrator (almost everything except billing.manage)
managerProject manager - manages members, tasks, and settings
executorField executor - creates/edits assets, tasks, inspections
investorInvestor - read access to financial and compliance data
auditorAuditor - read access plus create inspections for compliance
technicalTechnical advisor - updates assets, documents, inspections
marketingMarketing - access to public-facing information and documents
memberStandard member with basic view and form fill access
viewerRead-only access

Project Permissions

The project_permissions enum defines all project-level permissions (47 total).

Complete Project Permissions Matrix

Permissionowneradminmanagerexecutorinvestorauditortechnicalmarketingmemberviewer
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_memberships table
  • Members - Member management guide
  • Projects - Project access and permissions

On this page