Skip to main content

SPEC 012 — Team Members and Roles


1. Feature Purpose

Team Members and Roles is the authorization backbone of the Equa platform. Every organization has members (people associated with the org), roles (named permission groups), and a permission system that gates access to cap table, documents, billing, and all other features. This module handles inviting new members, managing their profiles, creating custom roles, assigning permissions, and enforcing access control across every API endpoint.

2. Current State (Verified)

2.1 Backend

2.2 Frontend


3. Data Model

Members

Source: schema.ts lines 892–922

Roles

Source: schema.ts lines 1305–1321

MembersRoles (Join Table)

Source: schema.ts lines 1296–1303

OrganizationsRoles (Join Table)

Source: schema.ts lines 1323–1330

Permissions

Source: schema.ts lines 1332–1339

PermissionsRoles (Join Table)

Source: schema.ts lines 1341–1348

GlobalRolesUsers

Source: schema.ts lines 1353–1360

Invitations

Source: schema.ts lines 326–341 InviteStatus enum (common/src/types.ts lines 60–65):
  • invited = 1 — Email sent, awaiting action
  • registered = 2 — User created an account
  • joined = 3 — User accepted and joined the organization
  • bounced = 4 — Email delivery failed

MemberLimits

Source: schema.ts lines 883–889

Relationships


4. API Endpoints

Member Endpoints

Source: organization-endpoints.ts lines 132–236

Role Endpoints

Source: organization-endpoints.ts lines 274–304

Request/Response Schemas


5. Frontend Components

Team Members Pages

Team Members Components

Roles Pages

Roles Components

Routes

Member Form Fields


6. Business Rules and Validation

6.1 Permissions System

Frontend permissions (15 named, defined in roles/utility.ts lines 35–126): Backend-only permissions (4 additional, in common/src/permissions.ts, not exposed in frontend role UI):
  • fullVoting — Full voting rights
  • partialVoting — Partial voting rights
  • writeSite — Write access to organization site
  • readSite — Read access to organization site

6.2 Permission Enforcement

Permission checks are implemented in api/src/site/authorization.ts as guard functions:
  • canViewMember, canEditMembers, canViewMembers, canViewSomeMembers
  • canViewOrganization, canEditOrganization
  • canViewCapTable, canEditCapTable
  • canViewDocuments, canEditDocuments, canDeleteDocuments
  • And others for billing, incentive plans, signing, governing docs
Each endpoint declares its guard via the requires property. The guard checks the requesting user’s roles → permissions before allowing the request.

6.3 Invitation Flow

  1. Admin calls POST /organization/:organization/member/invite with member IDs
  2. Server queries members by organization + IDs, deduplicates by email
  3. For each unique email: creates Invitation record (status: invited), sends email via commonNotificationTemplates.organizationInvitation
  4. When invitee registers: status updates to registered
  5. When invitee accepts and joins: status updates to joined
  6. If email bounces: status updates to bounced
Source: organizations/src/invitations.ts lines 30–64

6.4 Member Limits

Organizations have a memberLimit set by their subscription plan. The GET /organization/:organization/structure/member/limit endpoint returns the current limit. The frontend displays a MemberLimitError component when the limit is reached. Source: equa-web/src/shared/errors/member-limit-error.tsx

6.5 Role Assignment Rules

  • Roles are scoped to an organization via OrganizationsRoles
  • Members are assigned to roles via MembersRoles (many-to-many)
  • A member can have multiple roles; permissions are the union of all assigned roles’ permissions
  • Roles can be shared (isShared = true) across organizations
  • GlobalRolesUsers assigns platform-wide roles (admin) using integer role levels, separate from org-level RBAC

7. Acceptance Criteria

  • Organization owner can create, edit, and delete custom roles with any combination of the 15 permissions
  • Members can be assigned multiple roles; effective permissions are the union of all roles
  • New members can be invited by email; invitation creates a record and sends an email notification
  • Invitation status progresses through invited → registered → joined (or bounced)
  • Member form captures all 9 editable fields (fullName, email, phone, title, dateOfBirth, address, user, roles, types)
  • Member limit is enforced: adding members beyond the limit shows the MemberLimitError
  • Permission guards on all 16 endpoints correctly deny access when the requesting user lacks the required permission
  • Deleting a member removes their role assignments
  • The 4 backend-only permissions (fullVoting, partialVoting, writeSite, readSite) do not appear in the frontend role editor
  • Role deletion removes all PermissionsRoles and MembersRoles join records for that role

8. Risks and Edge Cases


9. Dependencies