Security Overview
GospeLib follows a defense-in-depth strategy with multiple independent security layers. A failure in any single layer does not grant an attacker unrestricted access to user data or platform resources. Within the gateway perimeter, the architecture adopts a zero-trust posture: every request carries verified identity claims, every route enforces entitlement checks, and every data store is unreachable from the public internet.
Security Model
The security architecture is organized into three concentric layers:
┌─────────────────────────────────────────────────────┐
│ Network Boundary │
│ TLS termination, CORS allowlist, no public data │
│ endpoints │
│ ┌───────────────────────────────────────────────┐ │
│ │ Identity & Access │ │
│ │ Clerk JWT validation, X-User-Id injection, │ │
│ │ webhook signature verification │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Authorization & Entitlements │ │ │
│ │ │ Plan-gated routes, per-tier rate │ │ │
│ │ │ limits, O(1) Redis entitlement checks │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Outermost layer -- Network Boundary. The API gateway is the sole public endpoint. All backend services and data stores (PostgreSQL, FalkorDB, Redis) have no public endpoints. TLS 1.3 encrypts all external traffic; Phase 3 adds mTLS for inter-service communication.
Middle layer -- Identity & Access. Every request to the gateway must carry a valid Clerk JWT. The gateway validates the JWT signature against cached JWKS keys, extracts user claims, and injects trusted headers (X-User-Id, X-User-Plan) before forwarding to downstream services. Downstream services trust these headers because they are unreachable outside the gateway.
Innermost layer -- Authorization & Entitlements. Gateway middleware gates each route by the required entitlement (e.g., ai_features, interlinear_hebrew_greek). Entitlements are cached in Redis with O(1) lookup per request, avoiding hot-path calls to the billing service. Rate limits are enforced per plan tier.
Security Layers in Detail
Authentication Flow
Covers the full authentication lifecycle: Clerk OAuth sign-in, JWT issuance (15-minute access tokens, 30-day refresh tokens), gateway JWKS validation, header injection, and Clerk webhook sync that keeps the PostgreSQL gl_users table current. The auth service is a thin Go wrapper around Clerk, designed so that swapping the auth provider later changes only the wrapper -- nothing downstream.
Entitlements & Authorization
Defines the three plan tiers (Reader/Scholar/Academic), maps features to entitlements, and documents how the gateway enforces access control. The billing service pushes entitlement data to Redis; the gateway performs a single GET per request to check access. Stripe webhook integration handles subscription changes with idempotent event processing.
Secrets & Network Policy
Describes secret management (AWS Secrets Manager in Phase 1, External Secrets Operator in Phase 2, HashiCorp Vault in Phase 3), environment variable naming conventions, network topology, CORS policy, webhook signature verification for both Clerk and Stripe, data encryption at rest and in transit, PII redaction in logs, and GitHub Actions OIDC authentication.
Key Invariants
These properties hold across all phases of the platform:
| Invariant | Enforcement |
|---|---|
| No secret in git, ever | .env.example has placeholders; .env.local is git-ignored |
| Gateway is the only public endpoint | Network policy; data stores have no public DNS |
| Every API request has a verified identity | JWT validation middleware on all non-public routes |
| Entitlement checks are O(1) | Redis cache with 60-second TTL, refreshed by billing service |
| Webhooks are signature-verified | Clerk and Stripe SDKs verify HMAC signatures before processing |
| Webhook processing is idempotent | Event IDs checked against gl_stripe_events / dedup tables |
| PII never appears in logs | Structured logging middleware redacts sensitive fields |
Phase Progression
Security capabilities evolve across deployment phases:
| Capability | Phase 1 | Phase 2 | Phase 3 |
|---|---|---|---|
| Authentication | Clerk SaaS | Clerk SaaS (paid tier) | Option: custom auth behind wrapper |
| Secret storage | AWS Secrets Manager | + External Secrets Operator | + HashiCorp Vault (dynamic credentials) |
| Network encryption | TLS 1.3 (external) | TLS 1.3 (external) | + mTLS (inter-service) |
| Encryption at rest | AWS managed keys | AWS managed keys | Customer-managed keys (CMK) |
Threat Model Summary
| Threat | Mitigation |
|---|---|
| Stolen JWT | 15-minute expiry; refresh tokens in secure storage (Keychain/SecureStore); sessions revocable via Clerk |
| Forged webhook | HMAC signature verification on every Clerk and Stripe webhook |
| Replay attack on webhook | Idempotency keys prevent duplicate processing |
| Unauthorized feature access | Gateway entitlement middleware returns 403 before reaching downstream services |
| Credential leak in CI | GitHub Actions uses OIDC (no long-lived AWS credentials); secrets are per-environment |
| Internal service impersonation | Services only accept requests with gateway-injected headers; not publicly routable |
| Data exfiltration | Data stores have no public endpoints; GDPR export/deletion endpoints for user self-service |