Skip to content

Security

Gremia implements a zero-trust security model with defense in depth. This page covers the security mechanisms across all three components.

Security Architecture

graph TB
    subgraph Builder["Builder (Web)"]
        JWT1[JWT Auth]
        MFA[MFA / TOTP]
        ZOD[Zod Validation]
    end

    subgraph Cloud["Cloud (Orchestrator)"]
        JWT2[JWT Verification]
        ENC[AES-256-GCM Encryption]
        AUDIT[Audit Logging]
        RLS[Row-Level Security]
        RL[Rate Limiting]
    end

    subgraph Shell["Shell (Desktop)"]
        MTLS[mTLS Client Cert]
        SESS[Session Key Exchange]
        CERT[Cert Rotation]
    end

    Builder -->|HTTPS + JWT| Cloud
    Shell -->|WSS + mTLS + AES-256-GCM| Cloud

Authentication

JWT Tokens

All API requests require a valid JWT token in the Authorization: Bearer header.

  • Algorithm: Configurable (default HS256)
  • Issued by: Supabase Auth
  • Claims: sub (user ID), email, team_id, exp (expiration)
  • Verification: Server-side via python-jose

Multi-Factor Authentication (MFA)

MFA is supported via TOTP (Time-Based One-Time Password):

  1. User enrolls via Settings > Security > Enable MFA
  2. Scans QR code with an authenticator app (Google Authenticator, Authy, etc.)
  3. On subsequent logins, a 6-digit code is required after password entry

Enterprise requirement

For Enterprise plans, MFA can be made mandatory for all team members via organization security policies.

mTLS Certificate Rotation

Shell-to-Cloud communication uses mutual TLS for identity verification:

sequenceDiagram
    participant S as Shell
    participant C as Cloud

    S->>S: Generate EC P-256 key pair
    S->>S: Create CSR (CN=shell-{id})
    S->>C: POST /api/v1/certs/sign (CSR + JWT)
    C->>C: Sign CSR with CA cert (24h validity)
    C->>C: Record serial in DB (revocation tracking)
    C-->>S: certificate_pem + ca_certificate_pem
    S->>S: Store cert material
    Note over S: Rotation loop every 5 min
    S->>S: Check: expires in < 1 hour?
    S->>C: Renew CSR

Parameters

Parameter Value
Key algorithm EC P-256 (ECDSA)
Certificate validity 24 hours
Renewal window 1 hour before expiry
Check interval 5 minutes
Max retry failures 5
Retry backoff Exponential (2^n seconds)

Revocation

Certificates can be revoked by serial number. The Cloud checks the revocation list during WebSocket handshake via the X-Client-Cert header (set by Nginx).

Encryption

At Rest — AES-256-GCM

Sensitive data stored in the database is encrypted with AES-256-GCM:

  • Manifest content — Encrypted before storage
  • Audit details — Encrypted to prevent data leakage
  • Consent records — Protected per GDPR requirements

Implementation details:

  • Encryption keys are versioned (v0 = previous, v1 = current)
  • Key registration happens at application startup
  • Re-encryption uses the latest key version

In Transit — TLS 1.3

Channel Protocol Details
Builder to Cloud HTTPS (TLS 1.3) Standard REST API
Shell to Cloud WSS (TLS 1.3) + AES-256-GCM Tunnel messages double-encrypted
Cloud to Supabase TLS 1.3 Database connections

Session Key Exchange

After WebSocket handshake, the Cloud generates an ephemeral AES-256 session key:

  1. Cloud generates 32 random bytes
  2. Key is base64-encoded and sent to Shell
  3. Both sides use the key for all subsequent messages
  4. Key is discarded on disconnect

Each message is encrypted as an EncryptedEnvelope:

{
  "iv": "base64-encoded-12-byte-nonce",
  "ciphertext": "base64-encoded-aes-256-gcm-ciphertext"
}

Key Rotation

Encryption Key Rotation (90-day cycle)

Encryption keys should be rotated every 90 days:

  1. Admin generates a new key (min 32 hex characters)
  2. Calls POST /api/v1/admin/rotate-key with the new key
  3. The system:
  4. Registers the new key as the active version
  5. Demotes the current key to "previous"
  6. Re-encrypts all sensitive rows in batches
  7. Audit entry records who rotated, when, and how many rows
# Generate a new key
NEW_KEY=$(openssl rand -hex 32)

# Rotate
curl -X POST https://api.gremia.io/api/v1/admin/rotate-key \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"new_key\": \"$NEW_KEY\"}"

Certificate Rotation (24-hour cycle)

Client certificates auto-rotate every 24 hours as described above. No manual intervention is required.

Rate Limiting

The API implements per-endpoint rate limiting:

Endpoint Limit Window
/api/v1/chat 60 requests 1 minute
/api/v1/certs/sign 10 requests 1 minute
/api/v1/tunnel/ws 5 connections 1 minute
All other endpoints 120 requests 1 minute

Exceeding the limit returns HTTP 429 (Too Many Requests) or WebSocket close code 4029.

Audit Logging

Every security-relevant action is recorded in the audit log:

Field Description
actor_id User who performed the action
action Action type (login, key_rotation, consent_grant, etc.)
resource_type What was acted upon
detail Human-readable description
result success, failure, or denied
timestamp UTC timestamp

Audit entries are flushed periodically in batches for performance. The flush interval is configurable.

No PII in audit logs

Audit log detail fields must never contain personally identifiable information (email, name, IP address). Use opaque IDs only.

Input Validation

All external input is validated before processing:

Layer Validation
Builder (TypeScript) Zod schemas for manifests, chat messages
Cloud (Python) Pydantic v2 models for all request bodies
Shell (Rust) serde + type system for tunnel messages
Database Parameterized queries only (no string interpolation)

Security Checklist

  • [x] AES-256-GCM encryption at rest
  • [x] TLS 1.3 for all network communication
  • [x] mTLS with 24-hour certificate rotation
  • [x] JWT authentication with configurable algorithms
  • [x] MFA support (TOTP)
  • [x] Rate limiting on all endpoints
  • [x] Audit logging for all security events
  • [x] Input validation at every layer
  • [x] Parameterized queries (no SQL injection)
  • [x] No secrets in source code (env vars only)
  • [x] No PII in logs or audit details
  • [x] CORS with explicit origin allowlist
  • [x] Request ID tracking for traceability
  • [x] GZip compression for responses