This document provides a detailed breakdown of the TradeOps platform architecture, network security design, and deployment configuration.
TradeOps is designed around a strict separation of concerns, partitioning public-facing features from sensitive back-office management interfaces. The platform consists of two principal environments: the Public Surface and the Private Surface.
The platform utilizes a split deployment architecture where public and administrative routing domains are physically separated at the hosting layer.
PUBLIC SERVICE (Internet-facing) PRIVATE SERVICE (VPN Mesh only)
┌───────────────────────────────────┐ ┌───────────────────────────────────┐
│ Vercel Project A: Public Website │ │ Vercel Project B: Admin Dashboard │
│ domain: yourdomain.com │ │ domain: admin.yourdomain.com │
└─────────────────┬─────────────────┘ └─────────────────┬─────────────────┘
│ HTTPS POST │ HTTPS API Calls
▼ ▼
┌───────────────────────────────────┐ ┌───────────────────────────────────┐
│ Railway Service A: Public API │ │ Railway Service B: Admin API │
│ APP_MODE = public │ │ APP_MODE = admin + Tailscale Node │
│ (Admin endpoints return 404) │ │ (Full routes, unreachable publicly)│
└─────────────────┬─────────────────┘ └─────────────────┬─────────────────┘
│ │
└────────────────────────┬────────────────────────┘
▼
┌───────────────────────────────────┐
│ Neon Serverless PostgreSQL │
│ (Single Shared DB) │
└───────────────────────────────────┘
A single, unified backend repository (Python 3.11 with FastAPI) is deployed for both the public and admin backend instances. Route exposure is controlled via the APP_MODE environment variable at startup:
APP_MODE=public: Only public routes are registered in the FastAPI application (e.g.,/health,/api/contact). Administrative routes (e.g.,/auth/*,/sales/*,/invoices/*) are completely omitted from the router stack. Attempts to hit these endpoints return an HTTP404 Not Foundrather than401 Unauthorizedor403 Forbidden, masking the administrative surface area from web scanners.APP_MODE=admin: The full suite of API endpoints is registered. The instance is deployed inside a private network, and access is restricted to authenticated VPN clients.
Rather than securing the admin dashboard and API behind a standard web login wall exposed to the public internet, TradeOps relies on network-level access control via a Tailscale VPN mesh.
- No Public Ingress: The Railway instance running the administrative backend does not expose a public domain or port to the internet. The backend runs as a Tailscale sidecar container, enrolling itself directly into the private Tailscale network.
- Access Control: Only enrolled devices (e.g., the Client's desktop/laptop devices) configured with active Tailscale authentication can resolve and route traffic to the admin API or admin frontend. Non-enrolled devices experience connection timeouts.
- Defense Against Brute-Forcing: Because the login page is invisible to the public internet, the threat of credential stuffing, DDoS, and brute-force attacks against administrative interfaces is eliminated.
The database configuration supports a migration path from cloud-hosted PostgreSQL (Neon) to an on-premise PostgreSQL instance situated on a physical Linux PC inside the Client's office.
Standard broadband ISP services assign dynamic IP addresses that cycle periodically. This makes traditional IP whitelisting impractical for connecting the cloud backend (Railway) to the local database.
TradeOps overcomes this constraint by utilizing Tailscale:
- The local Linux server runs a persistent Tailscale daemon, assigning it a permanent IP address within the
100.64.0.0/10overlay range (e.g.,100.64.12.34). - The database daemon is configured to listen on all interfaces (
0.0.0.0) but is protected by firewall rules that restrict traffic on port5432strictly to the100.64.0.0/10private range. - The backend
DATABASE_URLis set using the permanent overlay IP:postgresql+asyncpg://user:password@100.64.12.34:5432/tradeops. - When the ISP dynamic IP rotates, the Tailscale mesh routes the traffic seamlessly across the new path. No configuration updates are required on the backend.
For a list of design decisions, refer to the following records:
- ADR-01: PostgreSQL as Primary Database: Neon PostgreSQL acts as the single source of truth for transactional data. Google Sheets is treated strictly as a write-only, non-blocking synchronization target.
- ADR-02: Stateless JWT Authentication: Implemented via in-memory access tokens (lifetime 30 minutes) and HTTP-only, secure cookies for refresh tokens (lifetime 7 days).
- ADR-03: Asynchronous Google Sheets Synchronization: To prevent slow network calls (200–800ms) to the Sheets API from blocking the main request-response cycle, updates are dispatched to background worker threads.
- ADR-04: reportlab for PDF Generation: PDF rendering is executed in pure Python, removing headless browser execution (such as Puppeteer/Chromium) from the server runtime environment.
- ADR-05: Server-Side Computed Payment Status: The payment status of invoices is derived dynamically using database constraints and server calculations, preventing data drift.
- ADR-06: Cache-First GSTIN Lookup: External business registry API calls are mitigated via a local PostgreSQL cache with a 30-day expiration window.