Skip to main content

Security Architecture

Status: DRAFT Owner: Engineering Last Review: 2026-02-22 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

ComponentIn ScopeNotes
equa-serverYesBackend API, authentication, authorization, data persistence
equa-webYesFrontend SPA, input validation, file upload controls
PostgreSQLYesSession store, credential storage, audit logs
AWS S3YesDocument storage, access control
Google Cloud RunYesProduction deployment, container isolation
RailwayYesSecondary deployment target
equabot-gatewayPartialGateway 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.

3.1 Authentication Methods

The platform supports three authentication methods, all resulting in a server-side session stored in PostgreSQL.
MethodSource FileKey Properties
Password Loginequa-server/modules/auth/src/authentication.tsbcryptjs 10 salt rounds, email verification required, 2FA support
Google OAuthequa-server/modules/auth/src/google-auth.ts, equa-server/modules/api/src/server.tsID token + access token verification, audience (aud) validation, CSRF via g_csrf_token cookie/body check, auto-registration
Magic Linksequa-server/modules/auth/src/magic-link.ts32-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
PropertyValue
AlgorithmTOTP (Time-based One-Time Password)
Secret StorageAES-256-CTR encrypted (see Encryption)
User FieldsUsers.twoFactorSecret (encrypted), Users.twoFactorEnabled (boolean)
StatusOptional — 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

ControlImplementationSource
Registration rate limitingREGISTRATION_IP_LIMIT env var (default: 20 registrations per IP)equa-server/modules/referral/src/referral.ts
Domain blacklistdomain_blacklists table blocks registration from specified email domainsequa-server/modules/persistence/src/schema.ts
Email blacklistemail_blacklists table blocks specific email addressesequa-server/modules/persistence/src/schema.ts
reCAPTCHARequired on signup form using frontend site key (CAPTCHA_SITE_KEY)equa-web/src/modules/auth/components/sign-up-form.tsx
Temporary passwordsTempPasswords entity with bcrypt-hashed temporary passwordsequa-server/modules/persistence/src/schema.ts
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.

4. Encryption

4.1 Current Implementation

Source: equa-server/modules/auth/src/lib/encryption.ts
PropertyValue
AlgorithmAES-256-CTR
Key SourceTWO_FACTOR_PRIVATE_KEY env var (32-byte hex string)
IV16 random bytes per encryption operation
Storage Formativ:encryptedContent (hex-encoded)
ClassAesKey with encrypt() and decrypt() methods
Encrypted fields:
EntityFieldPurpose
UserstwoFactorSecretTOTP shared secret for 2FA

4.2 Password Hashing

PropertyValue
Algorithmbcryptjs
Salt Rounds10
Stored InUsers.passwordHash, TempPasswords.passwordHash

4.3 Encryption Gaps

The following sensitive fields are stored in plaintext in PostgreSQL:
EntityFieldRisk
GoogleDriveConnectionsaccessTokenOAuth token enables Google Drive access
GoogleDriveConnectionsrefreshTokenLong-lived token enables persistent access
BankAccountsaccountNumberFinancial account identifier
TaxIdsvalueContains EIN or SSN
Recommendation: Extend the AesKey encryption to these fields using a dedicated encryption key separate from the 2FA key.

5. Session Management

Source: equa-server/modules/auth/src/sessions.ts
PropertyValue
Libraryexpress-session
StoreCustom TypeORMSessionStore (persisted in sessions table)
SecretAPI_SESSION_SECRET env var
Max AgeAPI_SESSION_MAX_AGE (runtime default in sessions.ts: 7 days; current service bootstrap config: 2,520,000ms / ~42 minutes)
Rollingtrue — session expiry resets on each request
Cookie SecureEnabled when API_SSL is set
Proxy Trusttrust proxy: 1
Resavefalse
Save Uninitializedfalse

5.1 Session Storage Schema

Source: equa-server/modules/persistence/src/schema.ts (Sessions entity)
ColumnTypeNotes
idstring (PK)Session identifier
expiresDate (indexed)Expiration timestamp
userUUID (indexed, nullable)Linked user
jsontextSerialized 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

EnvironmentPlatformConfiguration
ProductionGoogle Cloud Runequa-server/cloudbuild.yaml — Docker image built and deployed
SecondaryRailwayequa-server/railway.toml — nixpacks builder with health check
Health CheckBothGET /health returns status and timestamp

6.2 SSL/TLS

PropertyValue
ToggleAPI_SSL env var
Key PathSSL_PRIVATE_KEY_PATH
Cert PathSSL_PUBLIC_KEY_PATH
Cookie SecuritySecure 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
ControlCurrent State
Auth methodsToken/password modes with timing-safe comparison, trusted proxy handling, and optional Tailscale-aware behavior
CORS headersAccess-Control-Allow-Origin: * is set on gateway HTTP handlers
Endpoint rate limiterRateLimiter utility exists in equabot-gateway/src/gateway/rate-limit.ts but is not wired to HTTP handlers

6.5 Security Headers Gap

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.

6.6 Rate Limiting Gap

There is no API-wide rate limiting. The only rate limiting exists at the agent level:
LimitDefaultEnv Var
Tool calls per minute30AGENT_MAX_TOOL_CALLS_PER_MINUTE
Write operations per minute10AGENT_MAX_WRITE_OPS_PER_MINUTE
Destructive operations per hour5AGENT_MAX_DESTRUCTIVE_PER_HOUR
Source: equa-server/modules/agent/src/security/guardrails.tsRecommendation: Implement API-wide rate limiting (e.g., express-rate-limit) on authentication endpoints and write operations.

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.
FieldValidation Rule
EmailIsEmail (class-validator)
Password4-128 characters (Length(4, 128)) with regex guard ^[\\w\\-_@.\~!#%^&*()+=?<>,[\\]]+`
Username2-32 characters, [a-z0-9-_]+
UUIDIsUUID for UUID-typed fields
2FA tokenNumeric 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

ControlValueSource
Allowed extensions.jpg, .jpeg, .png, .gif, .webp, .pdf, .doc, .docx, .xls, .xlsx, .csv, .txt, .mdequa-web/src/modules/landing/pages/landing-page.tsx
Max file size10 MB (AWS_S3_UPLOAD_SIZE_LIMIT_MB)equa-server env config
Max files per upload5Frontend validation
Upload methodmultipart/form-data via axios with withCredentials: trueequa-web/src/service/lib/http-client.ts

8. Secret Scanning

RepositorySecret ScanningTool
equabot-gatewayYesdetect-secrets in CI (.github/workflows/ci.yml)
equa-serverNoNot configured
equa-webNoNot configured
Recommendation: Add detect-secrets scanning to equa-server and equa-web CI pipelines, matching the equabot-gateway configuration.

9. Environment Variables (Security-Relevant)

VariablePurposeRequired
API_SESSION_SECRETSession cookie signingYes
TWO_FACTOR_PRIVATE_KEYAES-256-CTR key for 2FA secretsYes (if 2FA enabled)
GOOGLE_OAUTH_CLIENT_IDGoogle OAuth audience validationYes (if Google auth enabled)
API_SSLEnable SSL/TLSProduction
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYS3 file storage credentialsYes
MS_AUTH_CLIENT_ID / MS_AUTH_SECRETMicrosoft integration OAuthIf Microsoft enabled
GOOGLE_DRIVE_CLIENT_ID / GOOGLE_DRIVE_CLIENT_SECRETGoogle Drive integrationIf Drive enabled
CAPTCHA_SITE_KEYreCAPTCHA validationYes
REGISTRATION_IP_LIMITMax registrations per IP (default: 20)Optional

10. Regulatory References

StandardRequirementCurrent Status
SOC 2 CC6.1Logical access security over protected informationPartially implemented (RBAC exists, gaps in rate limiting)
SOC 2 CC6.6Security measures against threats outside system boundariesGap (no security headers, no API rate limiting)
SOC 2 CC7.2Monitoring of system components for anomaliesGap (no APM/alerting beyond health check)
GDPR Art. 32Appropriate technical and organizational security measuresPartially implemented (encryption limited to 2FA secrets)

11. Revision History

DateVersionAuthorChanges
2026-02-210.1Agent (Phase 5 Session A)Initial draft from code analysis
2026-02-220.2AgentAccuracy pass: corrected validation/session/auth references, clarified gateway scope, added reCAPTCHA backend gap note