Architecture reference

System Architecture

How secureFlows is deployed and connected in production: clients and automation tools on the left, edge protection and the Render Docker stack in the center, encrypted storage and external services on the right. Use this diagram when you need infrastructure detail — for a component overview see System Components; for the product-level view (hosted login, session vault, admin console), see Platform Architecture.

How to read this diagram

Traffic flows left to right. Browsers, mobile apps, and the JS SDK call the Session API over HTTPS. Cloudflare terminates TLS and applies WAF rules before traffic reaches Nginx on Render. Spring Boot handles session and management APIs, envelope encryption, and role checks before anything touches PostgreSQL. Backups land in Backblaze B2 as ciphertext; Firebase Auth and Paddle sit behind the API — integrators never talk to them directly.

Phase 1 (workspace setup) happens in the dashboard only — no application code. Phase 2 (runtime) is Session API usage with a sessionToken. The legend at the bottom lists integration rules that are architectural, not optional style choices.

Clients Browser / Web App React / Flutter Web sessionToken — memory only ❌ no localStorage ❌ no identity in body Mobile / Native Flutter iOS / Android sessionToken — memory only POST logout (non-browser) JS SDK secureflows-js (npm) Wraps session API calls Handles 410 → redirect n8n / Make / Zapier Automation / AI agents ai-safe endpoints only Edge ☁ Cloudflare WAF + DDoS TLS termination Host header → block Render bypass Rate limiting Server — Render (Docker) Gateway / Nginx Nginx (port 8080) Reverse proxy → Spring Boot · serves Flutter UI ⚙ Spring Boot API (port 8081) Session API (ai-safe) GET /api/v1/sessions POST /sessions/set/{key} GET /sessions/get/{key} DELETE /sessions/delete/{key} POST /sessions/revoke POST /auth/callback GET /auth/logout Identity from token only ❌ no userId in body Management API POST /workspaces GET/PATCH /workspaces POST/GET /applications POST/GET /invites GET /users GET /audit/events GET /audit/api-access OWNER / ADMIN only USER JWT required 🔑 Envelope Encryption Workspace-level keys Payload encrypted before write Decrypted on read (in memory) DB stores ciphertext only Admin reads → API layer + audit 👥 Token + Role Hierarchy Firebase → SESSION JWT tokenRevision → instant revocation OWNER → ADMIN → USER → ANON SUPPORT: DB-only provisioning 410 = token expired, data intact Caffeine cache (in-process) Storage 🐘 PostgreSQL (Render) Primary DB Sessions (ciphertext payload) Workspace billing Audit log · API access log Users · Applications Flyway migrations 💾 Backblaze B2 Encrypted Backups Daily cron (Render) pg_dump → ciphertext only B2 lifecycle rules per prefix 🔥 Firebase Auth Identity Provider Internal only — not exposed revokeRefreshTokens on logout email → best-effort audit display Devs / users never see Firebase 💳 Paddle (MoR) Billing · Free / Base / Pro 🔒 HTTPS 🔒 proxy_pass encrypted write/read daily backup verify token revoke refresh Legend & Key Security Rules HTTPS (browser) Encrypted data flow Internal / Firebase (hidden from clients) Admin / billing (optional) ❌ Never userId / workspaceId in request body ❌ Never sessionToken in localStorage / cookies ❌ Never fetch/XHR for browser logout (use top-level redirect) ❌ Never decode JWT client-side / revoke on normal sign-out ✅ 410 = token expired, session DATA is intact → re-login renews token ✅ DB stores ciphertext only — raw disk access yields nothing readable ✅ Isolation cross-tenant access architecturally impossible (not just policy) ✅ Billing 429 = too many concurrent sessions · 413 = payload size exceeded Phase 1 (admin setup): dashboard only — no code. Phase 2 (runtime): Session API only. Firebase is an internal detail — never exposed to developers or end users.
Production topology — clients, edge, Render (Nginx + Spring Boot), storage, and internal services. Zoom or scroll horizontally on narrow screens.

What each zone represents