Documentation Index
Fetch the complete documentation index at: https://docs-terra.withunify.org/llms.txt
Use this file to discover all available pages before exploring further.
Terra is built with security as a foundational principle. This document outlines our security architecture, threat model, and practices to ensure government-grade compliance and enterprise readiness.
π‘οΈ Table of Contents
- Security Architecture
- Threat Model
- Authentication & Authorization
- Data Protection
- Audit & Compliance
- Vulnerability Reporting
- Security Best Practices
ποΈ Security Architecture
Defense-in-Depth Strategy
Terra implements multiple layers of security controls:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 1: Network & Infrastructure β
β β’ CloudFlare DDoS protection β
β β’ TLS 1.3 encryption in transit β
β β’ Geographic access controls (optional) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 2: Application Security β
β β’ CSP headers (Content Security Policy) β
β β’ HSTS (HTTP Strict Transport Security) β
β β’ XSS protection via DOMPurify β
β β’ CSRF protection via Next.js β
β β’ Rate limiting on public endpoints β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 3: Authentication & Authorization β
β β’ WorkOS SSO with MFA support β
β β’ Role-Based Access Control (RBAC) β
β β’ Session encryption (JWT with secure cookies) β
β β’ Row-Level Security (RLS) in database β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 4: Data Security β
β β’ Encryption at rest (AES-256) β
β β’ Encrypted submission data (sensitive fields) β
β β’ PII redaction in logs β
β β’ Secure file storage with signed URLs β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 5: Monitoring & Audit β
β β’ Comprehensive audit logging β
β β’ Real-time security event monitoring (Sentry) β
β β’ Access logs with IP tracking β
β β’ Automated vulnerability scanning β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Security Components
Middleware Security (src/middleware.ts)
- Purpose: First line of defense for all HTTP requests
- Controls:
- CSP header injection with nonce-based script execution
- Role-based route protection (admin vs. user)
- Session decryption and validation
- Multi-tenant domain routing
- Redirect validation (prevents open redirects)
- Fail-Secure: Defaults deny access, requires explicit session
Auth Guards (src/lib/auth-guards.ts)
requireAdmin() - Blocks non-admin users
checkFormAccess() - Verifies form ownership/team membership
verifySubmissionAccess() - Ensures submission ownership
Security Utilities (src/lib/security/)
- Integration Validator - Prevents XSS in third-party integration IDs
- Submission Guard - Verifies resource ownership for sensitive operations
- Path Sanitization - Prevents path traversal in file operations
π― Threat Model
Assets Protected
| Asset | Sensitivity | Protection Mechanisms |
|---|
| User Credentials | CRITICAL | WorkOS SSO, encrypted sessions, MFA support |
| Submission Data | HIGH | Encryption at rest, RLS policies, access controls |
| Form Configurations | MEDIUM | RBAC, audit logging, version control |
| API Keys | CRITICAL | Environment variables, never logged, rotation support |
| File Uploads | MEDIUM | Signed URLs, type validation, size limits, access controls |
| Audit Logs | HIGH | Tamper-evident, retention policies, admin-only access |
Threat Actors
1. External Attackers (Untrusted)
- Goal: Data theft, service disruption, unauthorized access
- Mitigations:
- Rate limiting on public endpoints
- DDoS protection (CloudFlare)
- Input validation on all server actions
- CSP to prevent XSS
- SQL injection prevention (parameterized queries via Supabase)
2. Malicious Insiders (Low-Privilege Users)
- Goal: Privilege escalation, access other usersβ data
- Mitigations:
- RBAC enforcement in middleware
- Row-level security in database
- Submission ownership verification
- Audit logging of all actions
- Fail-secure auth guards
3. Compromised Accounts (Legitimate Users)
- Goal: Abuse stolen credentials
- Mitigations:
- Session expiration (configurable)
- MFA enforcement (WorkOS)
- Anomaly detection in audit logs
- IP tracking and geo-blocking (optional)
4. Supply Chain Attacks (Dependencies)
- Goal: Inject malicious code via npm packages
- Mitigations:
- Automated dependency scanning (npm audit, Snyk)
- Lock files (pnpm-lock.yaml)
- Regular security updates
- Minimal dependency footprint
Attack Vectors & Mitigations
| Attack Vector | Risk Level | Mitigation Status |
|---|
| SQL Injection | HIGH | β
Mitigated - Supabase client uses parameterized queries |
| XSS (Cross-Site Scripting) | HIGH | β
Mitigated - DOMPurify + CSP + input validation |
| CSRF (Cross-Site Request Forgery) | MEDIUM | β
Mitigated - Next.js built-in protection |
| Path Traversal | MEDIUM | β
Mitigated - Path sanitization in file operations |
| Privilege Escalation | HIGH | β
Mitigated - RBAC + RLS + auth guards |
| Session Hijacking | MEDIUM | β
Mitigated - Encrypted cookies + HTTPS only |
| Data Exposure via API | HIGH | β
Mitigated - Auth guards + submission ownership checks |
| Rate Limit Bypass | LOW | β οΈ In Progress - Adding rate limiting |
| Account Enumeration | LOW | β
Mitigated - Generic error messages |
| Open Redirect | LOW | β
Mitigated - Redirect validation in middleware |
π Authentication & Authorization
Authentication Flow (WorkOS SSO)
1. User visits /login
β
2. Redirected to WorkOS Auth0 (OAuth 2.0)
β
3. User authenticates (email/password + MFA if enabled)
β
4. WorkOS callback with authorization code
β
5. Terra exchanges code for user profile + tokens
β
6. Session created (encrypted JWT in HTTP-only cookie)
β
7. User redirected to dashboard or portal based on role
Role-Based Access Control (RBAC)
| Role | Permissions | Routes |
|---|
| super_admin | Full system access, can manage all forms/users | All routes |
| admin | Manage forms, view submissions, configure settings | /forms, /applications, /settings |
| user | Limited access (reserved for future use) | /portal |
| applicant | View own submissions only | /portal |
Authorization Enforcement
Middleware-Level (Route Protection)
// src/middleware.ts
// Runs on EVERY request before page render
if (isAdminRoute && !hasAdminAccess(userRole)) {
redirect("/portal"); // Deny access
}
Action-Level (Resource Protection)
// src/app/actions/*.ts
// Runs on EVERY server action before execution
const auth = await checkFormAccess(formId);
if (!auth.success) {
return { success: false, error: "Unauthorized" };
}
Database-Level (Row-Level Security)
-- Supabase RLS policies ensure even direct DB queries are filtered
CREATE POLICY "Users can only view their own submissions"
ON submissions FOR SELECT
USING (user_id = auth.uid());
π Data Protection
Encryption
In Transit
- TLS 1.3 for all HTTPS connections
- Certificate pinning (optional for high-security deployments)
- No downgrade attacks - HSTS enforced
At Rest
- Database: AES-256 encryption (Supabase managed)
- File Storage: AES-256 encryption (Supabase Storage)
- Sensitive Fields: Additional application-level encryption for:
- Bank account numbers
- Routing numbers
- Social security numbers
- Plaid access tokens
- Memory: Secrets loaded from environment variables, never hardcoded
- Logs: PII automatically redacted by logger (
src/lib/logger.ts)
Data Classification
| Data Type | Classification | Encryption | Retention |
|---|
| User Credentials | CRITICAL | WorkOS managed | Until account deletion |
| Submission Data | HIGH | At rest (AES-256) | Configurable (default: indefinite) |
| Audit Logs | MEDIUM | At rest (AES-256) | 2 years (compliance) |
| Form Schemas | LOW | At rest (AES-256) | Indefinite |
| File Uploads | MEDIUM | At rest (AES-256) | Linked to submission |
PII Handling
Terra follows GDPR/CCPA principles:
- Data Minimization - Only collect necessary data
- Purpose Limitation - Data used only for stated purpose
- Storage Limitation - Configurable retention policies
- Integrity & Confidentiality - Encryption + access controls
- Right to Erasure - Users can delete their data
PII Redaction in Logs:
// src/lib/logger.ts automatically redacts:
- Emails
- Phone numbers
- SSNs
- Credit card numbers
- API keys / tokens
- Passwords
π Audit & Compliance
Audit Logging
Every mutation operation is logged:
// Example: Form published
logFormAudit("publish", formId, userId, userEmail, userRole, {
form_title: "Application Form",
});
Audit Log Schema:
- Who:
user_id, user_email, user_role
- What:
action_type (create, update, delete, etc.)
- Which:
entity_type, entity_id
- When:
created_at (UTC timestamp)
- Where:
ip_address, user_agent
- Why:
metadata (context)
- Changes:
changes (before/after diff)
Audit Log Retention: 2 years minimum (configurable via migration 079)
Compliance Frameworks
SOC 2 Type II (System and Organization Controls)
- β
CC6.1 - Logical access controls (RBAC, RLS)
- β
CC6.6 - Audit logging and monitoring
- β
CC6.7 - Encryption at rest and in transit
- β
CC7.2 - Change management (audit logs + version control)
- β
A.9 - Access control (authentication, authorization)
- β
A.10 - Cryptography (TLS, AES-256)
- β
A.12 - Operations security (logging, monitoring)
- β
A.14 - System acquisition and development (secure SDLC)
GDPR (General Data Protection Regulation)
- β
Article 25 - Privacy by design and default
- β
Article 32 - Security of processing (encryption)
- β
Article 33 - Breach notification (monitoring + alerts)
- β
Article 35 - Data protection impact assessment (threat model)
HIPAA (Health Insurance Portability and Accountability Act)
- β οΈ Not HIPAA-certified - Additional BAA required for PHI
- β
Technical safeguards in place (encryption, access controls)
- β
Audit controls (comprehensive logging)
Compliance Reporting
Automated compliance reports available:
- User access logs (who accessed what, when)
- Form modification history (version control)
- Submission exports (with audit trail)
- Security event summary (failed logins, access denied)
π¨ Vulnerability Reporting
Responsible Disclosure Policy
We take security vulnerabilities seriously. If you discover a security issue:
DO:
- β
Report privately via GitHub Security Advisories
- β
Provide detailed reproduction steps
- β
Allow 90 days for remediation before public disclosure
- β
Work with us to verify the fix
DONβT:
- β Publicly disclose before weβve had a chance to fix
- β Exploit vulnerabilities beyond proof-of-concept
- β Access or modify other usersβ data
- β Perform DOS/DDOS attacks
Reporting Channels
-
GitHub Security Advisory (Preferred)
-
Email: security@withunify.org (if GitHub unavailable)
- Use PGP key: [Link to public key]
- Include: Description, impact, reproduction steps
Response Timeline
| Severity | Initial Response | Fix Timeline | Disclosure |
|---|
| Critical | 24 hours | 7 days | After fix + 14 days |
| High | 48 hours | 30 days | After fix + 30 days |
| Medium | 5 days | 60 days | After fix + 60 days |
| Low | 10 days | 90 days | After fix + 90 days |
Security Bounty
Currently no formal bug bounty program, but we recognize security researchers:
- Public acknowledgment (with permission)
- Swag/merchandise for significant findings
- Potential monetary reward for critical vulnerabilities (case-by-case)
π§ Security Best Practices (For Developers)
Code Review Checklist
Before submitting a PR, verify:
Secure Coding Patterns
β
GOOD: Server Action with Auth
export async function updateForm(formId: string, data: FormData) {
// 1. Auth guard
const auth = await checkFormAccess(formId);
if (!auth.success) return { success: false, error: auth.error };
// 2. Input validation
const validated = formSchema.safeParse(data);
if (!validated.success) return { success: false, error: "Invalid input" };
// 3. Database operation
const { error } = await supabaseAdmin
.from("forms")
.update(validated.data)
.eq("id", formId);
// 4. Audit logging
await logFormAudit("update", formId, auth.session.user.id, ...);
return { success: true };
}
β BAD: Missing Auth / Validation
export async function updateForm(formId: string, data: any) {
// NO auth check - anyone can update any form!
// NO input validation - SQL injection risk!
const { error } = await supabaseAdmin
.from("forms")
.update(data) // Unsafe!
.eq("id", formId);
return { success: !error };
}
Security Testing
Run security checks locally:
# Type safety
pnpm --dir apps/terra tsc --noEmit
# Linting (includes security rules)
pnpm --dir apps/terra lint
# Dependency vulnerabilities
npm audit
# Unit tests (includes security tests)
pnpm --dir apps/terra test
# E2E tests
pnpm --dir apps/terra test:e2e
π
Security Update Policy
- Critical vulnerabilities: Patched within 7 days
- High vulnerabilities: Patched within 30 days
- Dependency updates: Monthly review, quarterly updates
- Security audits: Quarterly internal review, annual external audit
π Additional Resources
Last Updated: 2026-01-08
Security Contact: security@withunify.org
Version: 1.0