Skip to content

Permissions

Every user has several attributes:

  1. access_level (Executive / Head / Manager / Lead / Employee) - Determines what you can see and do
  2. onboarding_template_id - Determines which onboarding checklist items apply
  3. scorecard_template_id - Determines which scorecard checklist items apply
  4. job_title - Free-text job title (synced from Google on login, editable on profile)
LevelDescriptionData Scope
ExecutiveFull access + adminAll data
HeadCross-team visibilityAll data
ManagerTeam-level accessOwn + squad data
LeadIndividual accessOwn data
EmployeeIndividual accessOwn data

Stored in the tool_permissions table, configurable via the Admin section (Executive only).

Each tool × access level combination has three permission flags:

  • can_view - Can see the tool and its data
  • can_update - Can modify data (create, edit, delete)
  • can_manage - Can configure the tool itself (edit templates, phases, etc.)

The people.manager_id column determines the “own + reports” scope for Managers:

  • own: Only the current user’s data (Lead, Employee)
  • own + direct reports: Own data + data from people where manager_id points to the current user (Manager)
  • all: All users’ data (Head, Executive)

Scoping is enforced in worker/middleware/permissions.ts via getScopedPersonIds(), which queries people WHERE manager_id = ? for the manager’s person ID.

  1. API middleware (worker/middleware/permissions.ts): Checks tool permissions before request processing
  2. Route handlers: Scope DB queries based on access level
  3. Frontend: useAuth() exposes canView(), canUpdate(), canManage() helpers
  4. Sidebar: Only shows tools the user has can_view for
  5. UI controls: Edit buttons hidden without can_update, config hidden without can_manage