Skip to Content
StandardsSecurity & Privacy

Security & Privacy

Security at Frequency is not a bolt-on — it’s built into the architecture through classification systems, automated quality gates, and middleware that runs on every request.

PII Classification

Every schema field that contains personal data must be classified using the x-pii extension. This enables automated compliance reporting, encryption policies, and data retention enforcement.

Classification Levels

Highly Sensitive

Level 4

Data that could cause severe harm if exposed. Requires encryption at rest and in transit. Strict access controls and audit logging.

Examples: SSN, financial account numbers, health records, passwords

Sensitive

Level 3

Personally identifiable information. Requires encryption at rest. Subject to GDPR/CCPA data subject requests.

Examples: Email address, phone number, mailing address, date of birth

Quasi-Identifiable

Level 2

Data that could identify a person when combined with other data. Requires anonymization in analytics and exports.

Examples: IP address, device ID, browser fingerprint, zip code

None

Level 1

Non-personal data. No special handling required.

Examples: Product names, public settings, aggregate counts

PII Schema Extension

{ "customer_email": { "type": "string", "format": "email", "x-pii": { "level": "sensitive", "category": "email", "retention": "2 years", "encryption": "at-rest", "anonymization": "hash", "gdprField": true, "ccpaField": true } } }

Available Categories

email, name, ssn, financial, health, address, phone, dob, ip_address, device_id, biometric

API Security Tiers

See API Standards for full details on the three-tier model:

TierPathAuthRate Limit
Internal/api/internal/*Service role keyNone
Authenticated/api/v1/*User session100 req/min
Public/api/public/*None10 req/min

Middleware Security

Every request passes through security middleware:

Content Security Policy (CSP)

The middleware configures a strict CSP that prevents XSS, clickjacking, and data injection:

addSecurityHeaders(response); // Sets: // Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-...'; ... // Strict-Transport-Security: max-age=31536000; includeSubDomains; preload // X-Frame-Options: DENY // X-Content-Type-Options: nosniff // Referrer-Policy: strict-origin-when-cross-origin

Request Tracing

Every request gets a UUID for end-to-end tracing:

addRequestId(request); // Adds: x-request-id header // Available in: logs, error reports, API responses

Maintenance Mode

Emergency circuit breaker for the entire application:

MAINTENANCE_MODE=true MAINTENANCE_BYPASS_KEY=secret-key-for-admins

Quality Gates

Automated security checks run on every change through the AI Drivers system.

VALIDITUS — Security Gate (Blocking)

This gate blocks merges if violations are found:

CheckThresholdWhat It Catches
Critical findings0 allowedHardcoded secrets, SQL injection
High findings0 allowedMissing RLS policies, XSS vectors
Medium findings≤3 allowedMissing input validation, verbose errors

Triggers: Any change to security-related code, x-pii fields, RLS policies, or auth logic.

GATED — Code Review Gate (Blocking)

Required human approvals before merge:

Change TypeApprovals Required
Documentation only1
Small changes1
Architecture changes2

Checklist: Code quality, type safety, testing, performance, security.

Environment Variables

Secrets Management

# ✅ CORRECT — use environment variables const key = process.env.SUPABASE_SERVICE_ROLE_KEY; # ❌ WRONG — never hardcode secrets const key = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';

Required Variables

VariableScopePurpose
NEXT_PUBLIC_SUPABASE_URLClient + ServerSupabase project URL
NEXT_PUBLIC_SUPABASE_ANON_KEYClient + ServerPublic API key
SUPABASE_SERVICE_ROLE_KEYServer onlyAdmin access (never expose to client)

Optional Variables

VariableScopePurpose
NEXT_PUBLIC_GA_IDClientGoogle Analytics
FLAGS_SECRETServerVercel feature flags
MAINTENANCE_MODEServerEnable maintenance page
MAINTENANCE_BYPASS_KEYServerBypass maintenance mode
LOG_LEVELServerServer logging level
NEXT_PUBLIC_LOG_LEVELClientClient logging level

Logging

import { logger, createLogger } from '@/core/lib/logger'; // General logging logger.info('Operation completed', { userId, action: 'invoice_created' }); logger.error('Operation failed', new Error('reason'), { requestId }); // Scoped logger const authLogger = createLogger({ context: 'auth' }); authLogger.warn('Failed login attempt', { email, ip });

Rules:

  • Never log PII at info level — use debug with appropriate guards
  • Always include requestId in error logs
  • Log level controlled via environment variables

Security Checklist

Before every PR, verify:

  • No hardcoded secrets or API keys
  • All user input validated with Zod
  • PII fields have x-pii classification
  • API routes use appropriate security tier
  • RLS policies cover new tables
  • Error messages don’t expose internal details
  • CORS configured for the correct origins
  • Rate limiting applied to public endpoints
Last updated on