Skip to main content

System Architecture

ForgeX is built on a modern microservices architecture with subdomain-based routing, providing true service isolation, independent scaling, and seamless single sign-on across all apps.


High-Level Architecture

🔍 Click diagram to expand
note

Legend: 🟢 Green = Live/Operational | 🟠 Orange = Planned for future phases


Service Overview

ForgeX consists of 4 core services, each with its own frontend, backend, and database:

Purpose: Authentication & App Launcher

AspectDetails
URLhttps://forge.precisionsiteservices.com
Port (Dev)3000
Status✅ Operational
TechReact, Firebase Hosting

Features:

  • Centralized Google OAuth entry point via SuperTokens
  • App tile selection interface
  • Role-based app visibility (users only see apps they have access to)
  • User profile display
  • Session management via HTTP-only cookies

Why it exists:

  • Single Sign-On (SSO): Sign in once, access all services
  • Security: Centralized auth reduces attack surface, SuperTokens handles session security
  • User Experience: Unified entry point for the entire platform

Database Isolation

Each service has its own dedicated PostgreSQL database, ensuring data isolation and independent scaling.

┌─────────────────────┐     ┌─────────────────────┐     ┌─────────────────────┐
│ bids_db │ │ projects_db │ │ field_db │
│ │ │ │ │ │
│ • 27 models │ │ • 6 models │ │ • 10 models │
│ • Bids, Scopes │ │ • Projects │ │ • Workers │
│ • 6 Item types │ │ • POs, Receipts │ │ • Timesheets │
│ • Pricing, Vars │ │ • Vendors │ │ • GPS logs │
│ • Audit logs │ │ • Approvals │ │ • Job logs │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘

Why Separate Databases?

BenefitDescription
Data IsolationService failures don't cascade across the platform
Independent ScalingScale databases based on service-specific load
SecurityLimit data access per service (least privilege)
Schema EvolutionChange schemas without affecting other services
Backup/RecoveryRestore services independently
warning

No direct database connections between services. All communication happens via REST APIs or Pub/Sub events.


Authentication Flow

ForgeX uses SuperTokens with Google Workspace OAuth for enterprise authentication and session management.

🔍 Click diagram to expand

Key Points

1
User visits Portal
2
Google OAuth via SuperTokens

SuperTokens handles OAuth flow with Google:

  • Only @precisionsiteservices.com emails allowed
  • Google handles password, 2FA, etc.
  • SuperTokens manages the entire authentication flow
3
Session Created

SuperTokens creates a secure session containing:

  • User ID, email, name, role
  • Session expiration (configurable, typically 24 hours)
  • Refresh token for seamless re-authentication

Session is stored as HTTP-only cookies on .precisionsiteservices.com

4
App Selection

User sees available apps based on their role:

  • ADMIN: All apps
  • ESTIMATOR: Bids
  • PM: Bids (read-only), Projects
  • OPS: Projects, Field
  • ACCOUNTING: Projects
  • FOREMAN: Field only
5
Cross-Subdomain Auth

SuperTokens session cookies are shared across all subdomains:

  • forge.precisionsiteservices.com
  • bids.precisionsiteservices.com
  • projects.precisionsiteservices.com
  • field.precisionsiteservices.com

No re-authentication needed! Seamless SSO via shared session cookies.

Security Features

  • SuperTokens Session Management: Self-hosted authentication core with secure session handling and automatic token rotation
  • HTTP-Only Cookies: Prevents XSS attacks (JavaScript can't access session tokens - sAccessToken, sRefreshToken)
  • SameSite Cookie Policy: CSRF protection built-in
  • Session Expiration: Sessions expire after 24 hours with automatic refresh token rotation
  • Domain Restriction: Only @precisionsiteservices.com emails allowed via Google Workspace OAuth
  • Self-Hosted: Full control over authentication infrastructure (no third-party access to session data)
  • No JWT in Frontend: All authentication handled via secure HTTP-only cookies, not localStorage or sessionStorage

Subdomain Routing

ForgeX uses subdomain-based routing, an industry-standard pattern used by companies like Stripe, GitHub, and Netlify.

Production URLs

SubdomainServicePurpose
forge.*PortalAuthentication & app launcher
bids.*BidsBid management
projects.*ProjectsProject management (Phase 2)
field.*FieldField operations (Phase 3)

Why Subdomains?

True Service Isolation

Each service has its own URL, frontend bundle, and backend. No shared code at runtime (only build-time via packages/shared).

Independent Deployment

Deploy services independently without affecting others. Update Bids Service without touching Projects or Field.

Shared Authentication

SuperTokens session cookies work across subdomains on the same parent domain (.precisionsiteservices.com).

Security (XSS Isolation)

XSS vulnerability in one service doesn't compromise others (different origins).

Scalability

Scale services independently based on load:

  • Bids Service: 5 Cloud Run instances
  • Projects Service: 2 instances
  • Field Service: 3 instances (mobile-heavy)
Future-Proof

Easy to add new services:

  • reporting.precisionsiteservices.com - Analytics dashboard
  • admin.precisionsiteservices.com - Admin panel
  • api.precisionsiteservices.com - Public API gateway

Local Development

Docker Compose orchestrates all services locally, simulating the production environment:

services:
# Databases
bids-db: # PostgreSQL for Bids Service
projects-db: # PostgreSQL for Projects Service
field-db: # PostgreSQL for Field Service

# Frontends (React)
portal: # Port 3000
bids-frontend: # Port 3001
projects-frontend: # Port 3002
field-frontend: # Port 3003

# Backends (Node.js/Express)
bids-backend: # Port 5001
projects-backend: # Port 5002
field-backend: # Port 5003

Local URLs

ServiceURL
Portalhttp://localhost:3000
Bids (Frontend)http://localhost:3001
Bids (API)http://localhost:5001/api
Projects (Frontend)http://localhost:3002
Field (Frontend)http://localhost:3003
note

Local vs. Production: Local uses localhost ports instead of subdomains. SuperTokens session cookies are set on localhost for local development.


Production Deployment

ForgeX is deployed on Google Cloud Platform (GCP) with a fully managed infrastructure.

Platform: Firebase Hosting (Google CDN)

Workflow:

# Build production bundle
npm run build

# Deploy to Firebase
firebase deploy --only hosting:bids

Features:

  • Global CDN distribution (low latency worldwide)
  • Automatic SSL certificates
  • HTTP/2 and Brotli compression
  • Atomic deployments (zero downtime)
  • Rollback to previous versions

Static Assets:

  • HTML, CSS, JS bundles
  • Images, fonts, icons
  • Service worker (for PWA features)

Role-Based Access Control (RBAC)

ForgeX implements fine-grained role-based access control at both the service and resource levels.

Roles

RoleBids ServiceProjects ServiceField Service
ADMINFull accessFull accessFull access
ESTIMATORFull access (no delete bids)Read-only-
PMRead-onlyApprove POs, view costsApprove timesheets
OPS-Create/manage POs-
ACCOUNTING-Reconcile, view costs-
FOREMAN--Clock in/out, view crew

Permission Model

// Middleware checks role before allowing actions
if (action === "DELETE_BID" && user.role !== "ADMIN") {
return res.status(403).json({ error: "Forbidden: Admin only" });
}

if (action === "APPROVE_PO" && !["ADMIN", "PM"].includes(user.role)) {
return res.status(403).json({ error: "Forbidden: PM or Admin required" });
}

Audit Logging

All actions are logged to the AuditLog table:

{
userId: "user-123",
action: "UPDATE_BID",
resourceType: "Bid",
resourceId: "bid-456",
changes: { status: "DRAFT" → "SUBMITTED" },
timestamp: "2025-01-29T12:34:56Z"
}

Tech Stack Summary

  • Framework: React 18 with TypeScript
  • Styling: Tailwind CSS
  • UI Library: shadcn/ui (Radix UI primitives)
  • State Management: Zustand (global state), React Query (server state)
  • Routing: React Router v6
  • Forms: React Hook Form + Zod validation
  • HTTP Client: Axios
  • Build Tool: Vite

Next Steps


note

This architecture supports Phase 1 (Bids Service). Phase 2/3 features are planned and subject to change.