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 actionregistered = 2— User created an accountjoined = 3— User accepted and joined the organizationbounced = 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 inroles/utility.ts lines 35–126):
Backend-only permissions (4 additional, in
common/src/permissions.ts, not exposed in frontend role UI):
fullVoting— Full voting rightspartialVoting— Partial voting rightswriteSite— Write access to organization sitereadSite— Read access to organization site
6.2 Permission Enforcement
Permission checks are implemented inapi/src/site/authorization.ts as guard functions:
canViewMember,canEditMembers,canViewMembers,canViewSomeMemberscanViewOrganization,canEditOrganizationcanViewCapTable,canEditCapTablecanViewDocuments,canEditDocuments,canDeleteDocuments- And others for billing, incentive plans, signing, governing docs
requires property. The guard checks the requesting user’s roles → permissions before allowing the request.
6.3 Invitation Flow
- Admin calls
POST /organization/:organization/member/invitewith member IDs - Server queries members by organization + IDs, deduplicates by email
- For each unique email: creates
Invitationrecord (status:invited), sends email viacommonNotificationTemplates.organizationInvitation - When invitee registers: status updates to
registered - When invitee accepts and joins: status updates to
joined - If email bounces: status updates to
bounced
organizations/src/invitations.ts lines 30–64
6.4 Member Limits
Organizations have amemberLimit 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 GlobalRolesUsersassigns 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