Skip to main content

Access Control Model

Status: DRAFT Owner: Engineering Last Review: 2026-02-21 Applicable Standards: SOC 2 (CC6.1, CC6.2, CC6.3) / GDPR (Art. 25, Art. 32)

1. Purpose

This document describes the access control model that governs who can view, edit, and manage data within the Equa platform. It covers role-based access control (RBAC), the cascading permission model for organization hierarchies, data room access, agent permission controls, unauthenticated guest chat access, and frontend enforcement.

2. Scope

ComponentIn ScopeNotes
equa-serverYesAuthorization module, permission checks, role management
equa-webYesFrontend route guards, permission HOC, UI-level gating
equabot-gatewayPartialAgent permission proxy that checks tool permissions
PostgreSQLYesRole/permission/member junction tables

3. RBAC Overview

Source: equa-server/modules/auth/src/authorization.ts, equa-server/modules/common/src/permissions.ts, equa-server/modules/common/src/roles.ts Equa implements role-based access control (RBAC) with the following characteristics:
  • Permissions are granted through roles, not directly to users
  • Roles are assigned to members within the context of an organization
  • A user can hold different roles in different organizations
  • Global roles exist for site-level administration
  • Permissions cascade through organization hierarchies

4. Permission Definitions

Source: equa-server/modules/common/src/permissions.ts

4.1 Built-In Permissions (14)

PermissionUUIDScope
viewOrganizationBuilt-inRead organization details
viewCapTableBuilt-inRead cap table, shareholdings, security types
viewDocumentsBuilt-inRead data room files and directories
viewMembersBuilt-inRead member list and profiles
editOrganizationDetailsBuilt-inModify organization settings
editCapTableBuilt-inCreate/modify shareholdings, issue equity
editDocumentsBuilt-inUpload, rename, delete files in data room
editMembersBuilt-inAdd/remove members, change titles
deleteDocumentsBuilt-inPermanently remove files
signingBuilt-inSign documents and agreements
fullVotingBuilt-inVote on all resolutions
partialVotingBuilt-inVote on subset of resolutions
editBillingBuilt-inManage subscription and payment methods
viewIncentivePlanBuilt-inRead ESOP/incentive plan details
editIncentivePlanBuilt-inCreate/modify incentive plans

4.2 Custom Permissions

Organizations can define custom roles with any combination of the built-in permissions via the Roles entity:
FieldTypePurpose
idUUIDRole identifier
namestringDisplay name
descriptionstringRole description
ownerUUID (nullable)Organization that owns this role
isSharedbooleanIf true, role is available across organizations
Source: equa-server/modules/persistence/src/schema.ts (Roles entity)

5. Built-In Roles

Source: equa-server/modules/common/src/roles.ts
RoleTypical PermissionsUse Case
adminAll permissionsOrganization administrator
auditorAll view permissionsExternal auditor with read-only access
directorView + edit org, cap table, documentsBoard member
guestviewOrganization onlyMinimal access visitor
investorView org, cap table, documentsEquity holder viewing their position
legalView + edit documents, signingLegal counsel
partnerView + edit org, cap table, membersOperating partner
presidentAll permissionsCorporate officer
secretaryView + edit org, documents, signingCorporate secretary
treasurerView + edit org, cap table, billingFinancial officer
signatoryView org, documents, signingDocument signatory
memberAnnualView org, cap table, documentsAnnual meeting participant
memberReadView org, cap tableRead-only member
holderView org, cap tableEquity holder (minimal)

6. Cascading Permission Model

Source: equa-server/docs/cascading-permission.puml, equa-server/modules/api/src/site/authorization.ts The Equa platform supports nested organization hierarchies (parent-child relationships). When a user views a parent organization, their effective permissions are calculated by combining direct and indirect permissions.

6.1 Algorithm

  • Direct permissions: The union of all permissions granted by roles assigned to the user in the target organization
  • Indirect permissions: The intersection of permission sets from all child organizations where the user is a member (the user must have the permission in every child org for it to be indirect)
  • Effective permissions: The union of direct and indirect permissions

6.2 Key Function

getUserDirectAndIndirectPermissions() in equa-server/modules/api/src/site/authorization.ts implements this algorithm. Endpoint handlers call requirePermissions() which wraps the endpoint with a permission check before the handler executes.

7. Permission Enforcement

7.1 Backend Enforcement

Source: equa-server/modules/auth/src/authorization.ts Every API endpoint declares its required permissions. The vineyard-lawn framework calls the permission check function before the handler:
FunctionPurpose
requirePermissions()Wraps endpoints with permission checks
canWriteSite()Checks site-level write permissions
canReadSite()Checks site-level read permissions
defineRelationalAuthorizationEndpoints()Applies permission checks to endpoint arrays
requireLoggedInSync()Verifies user is authenticated
Failure returns HTTP 403 Forbidden.

7.2 Frontend Enforcement

Source: equa-web/src/shared/hocs/with-permissions.tsx, equa-web/src/app/components/routes/routes.tsx
MechanismImplementationPurpose
Route guardsprotected: boolean on route definitionsRedirect unauthenticated users to login
Permission HOCwithPermissions([BuiltInPermission.viewDocuments])Hide/show components based on org permissions
Admin requirementisSiteAdmin route requirementGate admin pages
Email verificationuserIsEmailVerified(user) checkBlock unverified users from protected routes
Frontend enforcement is a UX convenience only. All security-critical checks are enforced server-side. A user bypassing frontend guards will still be blocked by the backend permission checks.

8. Data Room Access Control

Source: equa-server/modules/persistence/src/schema.ts (DataRoomsMembers entity) Data rooms provide document storage with per-member access control, separate from the general permission system.

8.1 DataRoomsMembers Entity

ColumnTypePurpose
dataRoomNamestring (PK)Data room identifier
memberUUID (PK)Member granted access
permissionUUID (PK)Permission level for this member in this data room
This is a composite primary key — the combination of data room, member, and permission is unique. A member can have multiple permission levels in the same data room.

8.2 Directory-Level Access

Data rooms use a virtual file system (DirectoryItems entity) scoped to organizations:
ColumnTypePurpose
organizationUUID (PK)Organization scope
parentPathstring (PK)Parent directory path
namestring (PK)Item name
fileUUID (nullable)Reference to Files entity
typesmallintFile or folder
All file operations require the appropriate document permission (viewDocuments, editDocuments, deleteDocuments).

9. Global Roles

Source: equa-server/modules/persistence/src/schema.ts (GlobalRolesUsers entity) For site-level administration, users can be assigned global roles that operate outside the organization context:
ColumnTypePurpose
userUUID (PK)User with global role
roleint (PK)GlobalRole enum value
Global roles grant site-wide privileges (e.g., managing all organizations, accessing admin panel). The isSiteAdmin check in the frontend route guard uses this.

10. Agent Permission Proxy

Source: equa-server/modules/agent/src/security/permission-proxy.ts The AI agent (Equanaut) operates within the same permission model as human users. The permission proxy ensures agents can only execute tools that the owning user has permission for:
PropertyValue
Cache TTL60 seconds
ResolutionSQL query joining permissions -> permissions_roles -> members_roles -> members
MethodscheckToolPermission(), checkMultiplePermissions(), getUserPermissions(), hasOrganizationAccess(), getUserRole()
Each agent tool declares its required permissions. Before execution, the proxy verifies the user has the necessary permissions in the target organization.

10.1 Unauthenticated Chat Access (Guest Mode)

Source: equa-web/src/modules/equanaut/services/api/chat/messages.ts, equa-web/src/modules/equanaut/index.tsx, equa-web/src/modules/equanaut/services/api/config.ts As of spec 042 (Guest Access to Equanaut Sidebar), the Equanaut regular-chat path is accessible to unauthenticated (guest) users. This path operates entirely outside the permission proxy described in Section 10.
PropertyValue
Trigger<EquanautToggle /> rendered in the guest header (header.tsx)
Chat modeRegular chat only (useChat); agent mode (useAgentChat) requires an authenticated user with an organization
EndpointPOST /equanaut-api/api/chat
AuthenticationNone — no Authorization header, no session cookie, no credentials: 'include'
Backend auth checkNone — the route handler processes the request without verifying identity
Tool executionNot available — the guest chat path never invokes the agent tool pipeline or the permission proxy
Organization dataNot accessible — userContext is undefined for guests; the system prompt contains only static platform knowledge
Data exposureNone — responses are generated from the static Equanaut system prompt (platform feature descriptions, navigation help, terminology); no user data, organization data, or cap table information is returned
What guest chat can do:
  • Answer general questions about the Equa platform, features, and navigation
  • Explain equity terminology (vesting, cap tables, option pools, etc.)
  • Provide onboarding guidance for new visitors
What guest chat cannot do:
  • Execute agent tools (blocked at the frontend; useAgentChat is never selected without a user and organization)
  • Access organization data, member lists, documents, or cap tables
  • Perform any write operations on the platform
  • View or modify any authenticated user’s information
Rate limiting: Rate limiting for the unauthenticated chat endpoint is not yet implemented. This was scoped as tasks T004 and T005 in spec 042 and deferred to a future sprint. Until implemented, the endpoint is theoretically vulnerable to abuse (high-volume requests from unauthenticated clients). The practical risk is limited because the endpoint only returns AI-generated text with no data exposure, but cost and availability concerns apply.
This section requires security review sign-off. The unauthenticated endpoint should be re-evaluated when rate limiting (spec 042, T004/T005) is implemented.

11. Access Control Gaps

GapRiskRecommendation
No session concurrency limitA compromised account could have unlimited active sessionsImplement max active sessions per user with oldest-session eviction
No IP-based session bindingSessions are not tied to originating IPConsider optional IP binding for high-security organizations
No permission audit logPermission grants/revocations are not logged to the audit trailLog all role assignment changes to EventLogs
Shared roles have no approval workflowisShared=true roles are available across organizations without reviewAdd approval workflow for shared role creation
No time-limited role assignmentsRoles are permanent until manually removedSupport role expiration dates for temporary access (e.g., auditor access)
No rate limiting on unauthenticated chat endpointGuest Equanaut chat (/equanaut-api/api/chat) has no request throttling; vulnerable to cost/availability abuseImplement per-IP rate limiting (spec 042, tasks T004/T005)

12. Regulatory References

StandardRequirementCurrent Status
SOC 2 CC6.1Logical access security over protected information assetsImplemented — RBAC with 14 permissions, role-based enforcement
SOC 2 CC6.2Prior to issuing system credentials, registered and authorizedImplemented — email verification + optional 2FA required
SOC 2 CC6.3Access to protected information is removed when no longer requiredPartial — soft delete on members, but no automated access review
GDPR Art. 25Data protection by design and by defaultImplemented — permission-based access, minimal default access (guest role)
GDPR Art. 32Appropriate technical measures for data securityImplemented — RBAC, encryption (limited), session management

13. Revision History

DateVersionAuthorChanges
2026-02-210.1Agent (Phase 5 Session A)Initial draft from code analysis
2026-02-220.2Agent (Spec 042)Added Section 10.1 (Unauthenticated Chat Access) and rate-limiting gap; pending security review