> ## 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.

# Security Architecture

> Authentication, encryption, session management, network security, and infrastructure controls

# Security Architecture

> **Status:** DRAFT
> **Owner:** Engineering
> **Last Review:** 2026-05-03
> **Applicable Standards:** SOC 2 (CC6, CC7) / GDPR (Art. 32) / SEC (data protection)

***

## 1. Purpose

This document describes the security controls protecting the Equa platform -- the technical mechanisms that safeguard user credentials, financial data, equity records, and organizational documents. It covers authentication, encryption, session management, network hardening, input validation, and infrastructure security.

## 2. Scope

| Component        | In Scope | Notes                                                                                                        |
| ---------------- | -------- | ------------------------------------------------------------------------------------------------------------ |
| equa-server      | Yes      | Backend API, authentication, authorization, data persistence                                                 |
| equa-web         | Yes      | Frontend SPA, input validation, file upload controls                                                         |
| PostgreSQL       | Yes      | Session store, credential storage, audit logs                                                                |
| AWS S3           | Yes      | Document storage, access control                                                                             |
| Railway          | Yes      | Current interim app/API edge and managed service configuration                                               |
| Google Cloud Run | Yes      | Legacy backend deploy path still present in repo automation                                                  |
| equabot-gateway  | Partial  | Gateway HTTP authentication and CORS posture are in scope; broader gateway security is documented separately |

## 3. Authentication

For the full technical implementation, see [Authentication and Permissions](/architecture/auth-and-permissions).

### 3.1 Authentication Methods

The platform supports three authentication methods, all resulting in a server-side session stored in PostgreSQL.

| Method         | Source File                                                                            | Key Properties                                                                                                                                                         |
| -------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Password Login | `equa-server/modules/auth/src/authentication.ts`                                       | bcryptjs 10 salt rounds, email verification required, 2FA support                                                                                                      |
| Google OAuth   | `equa-server/modules/auth/src/google-auth.ts`, `equa-server/modules/api/src/server.ts` | ID token + access token verification, audience (`aud`) validation, CSRF via `g_csrf_token` cookie/body check, auto-registration                                        |
| Magic Links    | `equa-server/modules/auth/src/magic-link.ts`                                           | 32-byte random hex token, 15-minute expiry, anti-enumeration (generates token even for nonexistent emails); implementation exists but schema integration is incomplete |

### 3.2 Two-Factor Authentication

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

| Property       | Value                                                                   |
| -------------- | ----------------------------------------------------------------------- |
| Algorithm      | TOTP (Time-based One-Time Password)                                     |
| Secret Storage | AES-256-CTR encrypted (see [Encryption](#4-encryption))                 |
| User Fields    | `Users.twoFactorSecret` (encrypted), `Users.twoFactorEnabled` (boolean) |
| Status         | Optional -- users can enable/disable                                    |

### 3.3 Email Verification

Email verification is required before a user can log in. The `EmailVerifications` entity stores a verification code linked to the user's UUID.

Source: `equa-server/modules/persistence/src/schema.ts` (EmailVerifications entity)

### 3.4 Anti-Abuse Controls

| Control                    | Implementation                                                             | Source                                                  |
| -------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- |
| Registration rate limiting | `REGISTRATION_IP_LIMIT` env var (default: 20 registrations per IP)         | `equa-server/modules/referral/src/referral.ts`          |
| Domain blacklist           | `domain_blacklists` table blocks registration from specified email domains | `equa-server/modules/persistence/src/schema.ts`         |
| Email blacklist            | `email_blacklists` table blocks specific email addresses                   | `equa-server/modules/persistence/src/schema.ts`         |
| reCAPTCHA                  | Required on signup form using frontend site key (`CAPTCHA_SITE_KEY`)       | `equa-web/src/modules/auth/components/sign-up-form.tsx` |
| Temporary passwords        | `TempPasswords` entity with bcrypt-hashed temporary passwords              | `equa-server/modules/persistence/src/schema.ts`         |

<Warning>
  reCAPTCHA validation is currently frontend-only. No server-side verification endpoint was found in `equa-server` for validating reCAPTCHA tokens with Google.

  **Recommendation:** Add backend token verification for signup to prevent direct API bypass of frontend checks.
</Warning>

## 4. Encryption

### 4.1 Current Implementation

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

| Property       | Value                                                 |
| -------------- | ----------------------------------------------------- |
| Algorithm      | AES-256-CTR                                           |
| Key Source     | `TWO_FACTOR_PRIVATE_KEY` env var (32-byte hex string) |
| IV             | 16 random bytes per encryption operation              |
| Storage Format | `iv:encryptedContent` (hex-encoded)                   |
| Class          | `AesKey` with `encrypt()` and `decrypt()` methods     |

**Encrypted fields:**

| Entity | Field             | Purpose                    |
| ------ | ----------------- | -------------------------- |
| Users  | `twoFactorSecret` | TOTP shared secret for 2FA |

### 4.2 Password Hashing

| Property    | Value                                              |
| ----------- | -------------------------------------------------- |
| Algorithm   | bcryptjs                                           |
| Salt Rounds | 10                                                 |
| Stored In   | `Users.passwordHash`, `TempPasswords.passwordHash` |

### 4.3 Encryption Gaps

<Warning>
  The following sensitive fields are stored in plaintext in PostgreSQL:

  | Entity                 | Field           | Risk                                       |
  | ---------------------- | --------------- | ------------------------------------------ |
  | GoogleDriveConnections | `accessToken`   | OAuth token enables Google Drive access    |
  | GoogleDriveConnections | `refreshToken`  | Long-lived token enables persistent access |
  | BankAccounts           | `accountNumber` | Financial account identifier               |
  | TaxIds                 | `value`         | Contains EIN or SSN                        |

  **Recommendation:** Extend the `AesKey` encryption to these fields using a dedicated encryption key separate from the 2FA key.
</Warning>

## 5. Session Management

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

| Property           | Value                                                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| Library            | `express-session`                                                                                                              |
| Store              | Custom `TypeORMSessionStore` (persisted in `sessions` table)                                                                   |
| Secret             | `API_SESSION_SECRET` env var                                                                                                   |
| Max Age            | `API_SESSION_MAX_AGE` (runtime default in `sessions.ts`: 7 days; current service bootstrap config: 2,520,000ms / \~42 minutes) |
| Rolling            | `true` -- session expiry resets on each request                                                                                |
| Cookie Secure      | Enabled when `API_SSL` is set                                                                                                  |
| Proxy Trust        | `trust proxy: 1`                                                                                                               |
| Resave             | `false`                                                                                                                        |
| Save Uninitialized | `false`                                                                                                                        |

### 5.1 Session Storage Schema

Source: `equa-server/modules/persistence/src/schema.ts` (Sessions entity)

| Column    | Type                     | Notes                   |
| --------- | ------------------------ | ----------------------- |
| `id`      | string (PK)              | Session identifier      |
| `expires` | Date (indexed)           | Expiration timestamp    |
| `user`    | UUID (indexed, nullable) | Linked user             |
| `json`    | text                     | Serialized session data |

### 5.2 Session Cleanup

Source: `equa-server/modules/auth/src/lib/session-cleaning.ts`

A cron job periodically removes expired session records from the database based on the `expires` column.

## 6. Network and Infrastructure Security

### 6.1 Deployment

| Environment                | Platform                              | Configuration                                                                                                                                                                             |
| -------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Current interim app edge   | Railway-backed nginx + backend target | `equa-web/nginx.conf` proxies `/api/` to `https://equa-server-so-production.up.railway.app/`; `equa-web/railway.toml` and `equa-server/railway.toml` define managed service health checks |
| Legacy backend deploy path | Google Cloud Run                      | `equa-server/cloudbuild.yaml` remains in repo as a legacy deploy path for `equa-server`                                                                                                   |
| Health Check               | Managed platform + app route          | `GET /health` returns status and timestamp; Railway service configs also define health check paths                                                                                        |

### 6.2 SSL/TLS

| Property        | Value                            |
| --------------- | -------------------------------- |
| Toggle          | `API_SSL` env var                |
| Key Path        | `SSL_PRIVATE_KEY_PATH`           |
| Cert Path       | `SSL_PUBLIC_KEY_PATH`            |
| Cookie Security | Secure flag set when SSL enabled |

### 6.3 CORS

CORS is enabled via the `vineyard-lawn` middleware in `equa-server/modules/api/src/server.ts`. The specific allowed origins are configured at the application level.

### 6.4 Gateway HTTP Authentication and CORS

Source: `equabot-gateway/src/gateway/auth.ts`, `equabot-gateway/src/gateway/channels-http.ts`, `equabot-gateway/src/gateway/config-http.ts`, `equabot-gateway/src/gateway/task-stack-http.ts`

| Control               | Current State                                                                                                   |
| --------------------- | --------------------------------------------------------------------------------------------------------------- |
| Auth methods          | Token/password modes with timing-safe comparison, trusted proxy handling, and optional Tailscale-aware behavior |
| CORS headers          | `Access-Control-Allow-Origin: *` is set on gateway HTTP handlers                                                |
| Endpoint rate limiter | `RateLimiter` utility exists in `equabot-gateway/src/gateway/rate-limit.ts` but is not wired to HTTP handlers   |

### 6.5 Security Headers Gap

<Warning>
  No security headers middleware (such as `helmet`) is configured. The following headers are not set:

  * `Strict-Transport-Security` (HSTS)
  * `X-Content-Type-Options`
  * `X-Frame-Options`
  * `Content-Security-Policy`
  * `X-XSS-Protection`
  * `Referrer-Policy`

  **Recommendation:** Add `helmet` middleware to `equa-server/modules/api/src/server.ts` with production-appropriate defaults.
</Warning>

### 6.6 Rate Limiting Gap

<Warning>
  There is no API-wide rate limiting. The only rate limiting exists at the agent level:

  | Limit                           | Default | Env Var                           |
  | ------------------------------- | ------- | --------------------------------- |
  | Tool calls per minute           | 30      | `AGENT_MAX_TOOL_CALLS_PER_MINUTE` |
  | Write operations per minute     | 10      | `AGENT_MAX_WRITE_OPS_PER_MINUTE`  |
  | Destructive operations per hour | 5       | `AGENT_MAX_DESTRUCTIVE_PER_HOUR`  |

  Source: `equa-server/modules/agent/src/security/guardrails.ts`

  **Recommendation:** Implement API-wide rate limiting (e.g., `express-rate-limit`) on authentication endpoints and write operations.
</Warning>

## 7. Input Validation

### 7.1 Backend Validation

Source: `equa-server` primarily uses `class-validator` decorators for backend request DTO validation. `vineyard-lawn` is used for endpoint wiring and request flow.

| Field     | Validation Rule                                                                               |
| --------- | --------------------------------------------------------------------------------------------- |
| Email     | `IsEmail` (`class-validator`)                                                                 |
| Password  | 4-128 characters (`Length(4, 128)`) with regex guard `^[\\w\\-_@.\`\~!#$%^&*()+=?<>,[\\]]+$\` |
| Username  | 2-32 characters, `[a-z0-9-_]+`                                                                |
| UUID      | `IsUUID` for UUID-typed fields                                                                |
| 2FA token | Numeric TOTP verification in `two-factor.ts`                                                  |

Validation for file names, URLs, phone numbers, and Ethereum addresses is also present in frontend validators (`equa-web/src/shared/helpers/field-validators.ts`) and should not be treated as equivalent to backend enforcement without endpoint-specific confirmation.

### 7.2 Frontend Validation

Source: `equa-web/src/shared/helpers/field-validators.ts`

Frontend validation mirrors backend rules using the same `validator` library and custom regex patterns. React's default JSX escaping provides baseline XSS protection.

### 7.3 File Upload Validation

| Control              | Value                                                                             | Source                                                |
| -------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------- |
| Allowed extensions   | `.jpg, .jpeg, .png, .gif, .webp, .pdf, .doc, .docx, .xls, .xlsx, .csv, .txt, .md` | `equa-web/src/modules/landing/pages/landing-page.tsx` |
| Max file size        | 10 MB (`AWS_S3_UPLOAD_SIZE_LIMIT_MB`)                                             | `equa-server` env config                              |
| Max files per upload | 5                                                                                 | Frontend validation                                   |
| Upload method        | multipart/form-data via axios with `withCredentials: true`                        | `equa-web/src/service/lib/http-client.ts`             |

## 8. Secret Scanning

| Repository      | Secret Scanning | Tool                                                |
| --------------- | --------------- | --------------------------------------------------- |
| equabot-gateway | Yes             | `detect-secrets` in CI (`.github/workflows/ci.yml`) |
| equa-server     | **No**          | Not configured                                      |
| equa-web        | **No**          | Not configured                                      |

<Warning>
  **Recommendation:** Add `detect-secrets` scanning to equa-server and equa-web CI pipelines, matching the equabot-gateway configuration.
</Warning>

## 9. Environment Variables (Security-Relevant)

| Variable                                                | Purpose                                | Required                     |
| ------------------------------------------------------- | -------------------------------------- | ---------------------------- |
| `API_SESSION_SECRET`                                    | Session cookie signing                 | Yes                          |
| `TWO_FACTOR_PRIVATE_KEY`                                | AES-256-CTR key for 2FA secrets        | Yes (if 2FA enabled)         |
| `GOOGLE_OAUTH_CLIENT_ID`                                | Google OAuth audience validation       | Yes (if Google auth enabled) |
| `API_SSL`                                               | Enable SSL/TLS                         | Production                   |
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`           | S3 file storage credentials            | Yes                          |
| `MS_AUTH_CLIENT_ID` / `MS_AUTH_SECRET`                  | Microsoft integration OAuth            | If Microsoft enabled         |
| `GOOGLE_DRIVE_CLIENT_ID` / `GOOGLE_DRIVE_CLIENT_SECRET` | Google Drive integration               | If Drive enabled             |
| `CAPTCHA_SITE_KEY`                                      | reCAPTCHA validation                   | Yes                          |
| `REGISTRATION_IP_LIMIT`                                 | Max registrations per IP (default: 20) | Optional                     |

## 10. Regulatory References

| Standard     | Requirement                                                 | Current Status                                             |
| ------------ | ----------------------------------------------------------- | ---------------------------------------------------------- |
| SOC 2 CC6.1  | Logical access security over protected information          | Partially implemented (RBAC exists, gaps in rate limiting) |
| SOC 2 CC6.6  | Security measures against threats outside system boundaries | Gap (no security headers, no API rate limiting)            |
| SOC 2 CC7.2  | Monitoring of system components for anomalies               | Gap (no APM/alerting beyond health check)                  |
| GDPR Art. 32 | Appropriate technical and organizational security measures  | Partially implemented (encryption limited to 2FA secrets)  |

## 11. Revision History

| Date       | Version | Author                    | Changes                                                                                                                |
| ---------- | ------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| 2026-02-21 | 0.1     | Agent (Phase 5 Session A) | Initial draft from code analysis                                                                                       |
| 2026-02-22 | 0.2     | Agent                     | Accuracy pass: corrected validation/session/auth references, clarified gateway scope, added reCAPTCHA backend gap note |
