> ## Documentation Index
> Fetch the complete documentation index at: https://docs.equa.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication and Permissions

> Session-based auth, Google OAuth, magic links, and cascading RBAC model

# Authentication and Permissions

> **Source:** `equa-server/modules/auth/src/`

## Authentication Methods

Equa supports three authentication methods, all resulting in a server-side session.

### 1. Password Login

Source: `equa-server/modules/auth/src/authentication.ts`

* Password hashing: `bcryptjs` (10 rounds)
* Two-factor authentication: Supported via `twoFactorToken`
* Email verification: Required before login
* Temporary passwords: Supported via `checkTempPassword()`
* On success: `session.user = result.user.id` (line 72)

### 2. Google OAuth

Source: `equa-server/modules/auth/src/google-auth.ts`, `equa-server/modules/api/src/server.ts`

* Supports both ID tokens and access tokens
* Validates email verification status
* Checks audience (`aud`) matches client ID
* Validates `g_csrf_token` cookie/body consistency in API middleware before Google auth endpoint execution
* Auto-registration: Creates user if email not found (random password assigned)
* On success: `session.user = user.id` (line 88)

### 3. Magic Links

Source: `equa-server/modules/auth/src/magic-link.ts`

> **Note:** `magic-link.ts` is currently an untracked file in the equa-server repo. It imports a `MagicLinks` entity from `persistence` that has not yet been added to `schema.ts`. This feature is in development but not yet integrated into the database schema.

| Property         | Value                                                  |
| ---------------- | ------------------------------------------------------ |
| Token            | 32-byte random hex                                     |
| Expiry           | 15 minutes (`MAGIC_LINK_EXPIRY_MINUTES`)               |
| Anti-enumeration | Generates token even if user doesn't exist             |
| Dev mode         | Returns token in response when `EMAIL_TRANSPORTER=dev` |

Functions:

* `sendMagicLink()` -- Creates magic link record and sends email
* `verifyMagicLink()` -- Validates token, checks expiry, marks as used
* `magicLinkLogin()` -- Creates session after verification
* `cleanupExpiredMagicLinks()` -- Cleanup for expired links

## Session Management

Source: `equa-server/modules/auth/src/sessions.ts`

| Property           | Value                                                   |
| ------------------ | ------------------------------------------------------- |
| Library            | `express-session`                                       |
| Store              | Custom `TypeORMSessionStore` (Sessions entity)          |
| Secret             | `API_SESSION_SECRET` env var                            |
| Max age            | `API_SESSION_MAX_AGE` (default: 604,800,000ms / 7 days) |
| SameSite           | `lax`                                                   |
| HttpOnly           | `true`                                                  |
| Cookie secure      | When SSL enabled                                        |
| Proxy              | `true`                                                  |
| Rolling            | `true` (extends session on each request)                |
| Resave             | `false`                                                 |
| Save uninitialized | `false`                                                 |

Sessions are persisted in the `sessions` table with columns: `id`, `expires` (indexed), `user` (indexed), `json`.

## Authorization Model (RBAC)

Source: `equa-server/modules/auth/src/authorization.ts`, `equa-server/docs/cascading-permission.puml`

### Entities

```mermaid theme={null}
erDiagram
    Users ||--o{ GlobalRolesUsers : "has global role"
    Users ||--o{ Members : "is member of org"
    Members ||--o{ MembersRoles : "has role in org"
    MembersRoles }o--|| Roles : "assigned role"
    Roles ||--o{ PermissionsRoles : "grants"
    PermissionsRoles }o--|| Permissions : "permission"
    Organizations ||--o{ OrganizationsRoles : "has roles"
    OrganizationsRoles }o--|| Roles : "role"
```

### Permission Check Flow

1. Endpoint declares `requires?: PermissionCheck` property
2. vineyard-lawn calls the permission check function before the handler
3. Check verifies:
   * User is logged in (`requireLoggedInSync()`)
   * User has required role/permission for the target organization
4. If check fails, returns 403 Forbidden

### Key Authorization Functions

Source: `equa-server/modules/auth/src/authorization.ts`

| Function                                   | Lines | Purpose                                      |
| ------------------------------------------ | ----- | -------------------------------------------- |
| `requirePermissions()`                     | 21-26 | Wraps endpoints with permission checks       |
| `canWriteSite()`                           | 43-47 | Checks site-level write permissions          |
| `canReadSite()`                            | 49-50 | Checks site-level read permissions           |
| `defineRelationalAuthorizationEndpoints()` | 33-36 | Applies permission checks to endpoint arrays |

### Cascading Permission Model

Source: `equa-server/docs/cascading-permission.puml`

The cascading permission model supports nested organizations with permission inheritance:

* **Direct permissions:** User has a role directly assigned in the organization
* **Indirect permissions:** User inherits permissions from a parent organization
* **Union:** For read operations, permissions from parent and child are combined
* **Intersection:** For write operations, only overlapping permissions apply

### Role Tables

| Table                 | Purpose                                | Key Columns                                      |
| --------------------- | -------------------------------------- | ------------------------------------------------ |
| `roles`               | Role definitions                       | `id`, `name`, `description`, `owner`, `isShared` |
| `permissions`         | Permission definitions                 | `id`, `name`                                     |
| `permissions_roles`   | Role-to-permission mapping             | `permission`, `role`                             |
| `members_roles`       | Member-to-role assignment (org-scoped) | `member`, `role`                                 |
| `organizations_roles` | Organization-to-role binding           | `organization`, `role`                           |
| `global_roles_users`  | Global role assignment                 | `user`, `role` (GlobalRole enum)                 |

## Permission Enumeration

> **Source:** Confluence KnowledgeBase — [Equa App Permissions](https://equa.atlassian.net/wiki/spaces/KNOWLEDGEB/pages/35618920/Equa+App+Permissions) (by Christopher Johnson)

### Organization Permissions (15)

| Permission                | Description                                           |
| ------------------------- | ----------------------------------------------------- |
| View Organization         | View organization details and dashboard               |
| View Cap Table            | View capitalization table, shareholdings, securities  |
| View Governing Documents  | View agreements, operating agreements                 |
| View Members              | View team member list and details                     |
| View Self                 | View own holdings and member page (may be deprecated) |
| View Documents            | View data room documents                              |
| View Incentive Plan       | View ESOP plans, option pools, vesting schedules      |
| Edit Members              | Add, invite, modify, remove team members              |
| Edit Documents            | Upload, modify, delete data room documents            |
| Edit Organization Details | Modify organization settings, securities, legends     |
| Edit Cap Table            | Create/modify shareholdings, transfers, certificates  |
| Edit Incentive Plan       | Create/modify ESOP plans, pools, grant options        |
| Delete Documents          | Remove documents from data rooms                      |
| Signing                   | Digital signature capability for agreements           |
| Edit Billing              | Manage subscriptions, payment profiles, billing       |

### Site Permissions (2, for site admins only)

| Permission | Description                                                |
| ---------- | ---------------------------------------------------------- |
| Write Site | Full site-level write access (admin operations)            |
| Read Site  | Full site-level read access (admin view all organizations) |

The authorization module maps these to endpoint-level checks:

* `requirePermissions()` — generic permission check
* `canWriteSite()` / `canReadSite()` — site-level admin access
* `canEditCapTable`, `canViewOrganization`, `canEditMembers`, `canEditOrganizationBilling`, etc. — organization-level checks used in endpoint definitions

## Security Notes

* No explicit rate limiting middleware found in the codebase
* Registration IP limit: `REGISTRATION_IP_LIMIT` (default: 20; applied in `modules/referral/src/referral.ts`)
* Domain blacklist: `domain_blacklists` table
* Email blacklist: `email_blacklists` table
* Email verification required before login
* Two-factor authentication supported but optional
