BlueDXP Platform Architecture

Complete visual overview of the platform architecture, data flows, company-user linkage, and all the improvements made.

Platform Overview
Data Model
Auth & User Flow
Company Linkage
Freight Exchange
Branding Flow
Before vs After
Roles & Permissions

1 Platform Overview

How all the pieces of BlueDXP fit together — from the browser to the database.

System Architecture

graph TB subgraph Browser["Browser (Frontend)"] Login["login.html"] Signup["signup.html"] Portal["portal.html
Customer Portal"] Admin["admin.html
Command Center"] Settings["settings.html
Platform Settings"] Workspace["wajeeh-enterprise-master.html
Main Workspace"] FX["wajeeh-enterprise-master.html?fx=1
Freight Exchange (Loadboard tab)"] Dispatch["dispatch.html
Dispatch Center"] WH["warehouse-onboard.html
Warehouse Onboarding"] end subgraph API["Vercel Serverless API"] AuthAPI["api/auth.js
Login, Signup, JWT"] UsersAPI["api/users.js
User CRUD, Invites"] RFIAPI["api/rfi.js
Submissions + Exchange"] OrgHandler["organizations-handler.js
Org CRUD, Members"] WHHandler["warehouse-handler.js
Warehouse CRUD"] BillingH["billing-handler.js
Billing & Usage"] Guard["guard.js
JWT + RBAC Auth"] Roles["roles.js
10 Roles + Permissions"] end subgraph Data["PostgreSQL Database"] Users["users"] Orgs["organizations"] Sessions["sessions"] Submissions["submissions"] FreightL["freight_listings"] FreightB["freight_bids"] Warehouses["warehouses"] Billing["billing_accounts"] end subgraph Storage["External Services"] Blob["Vercel Blob
Logo Storage"] Resend["Resend
Email Service"] Anthropic["Anthropic
AI Engine"] end Login --> AuthAPI Signup --> AuthAPI Portal --> UsersAPI Admin --> UsersAPI Settings --> OrgHandler FX --> RFIAPI Dispatch --> UsersAPI WH --> WHHandler AuthAPI --> Guard UsersAPI --> Guard RFIAPI --> Guard Guard --> Roles AuthAPI --> Users AuthAPI --> Sessions AuthAPI --> Orgs UsersAPI --> Users OrgHandler --> Orgs OrgHandler --> Users RFIAPI --> Submissions RFIAPI --> FreightL RFIAPI --> FreightB WHHandler --> Warehouses BillingH --> Billing OrgHandler --> Blob AuthAPI --> Resend RFIAPI --> Anthropic

Frontend (HTML Pages)

12+ standalone HTML pages with inline CSS/JS. No framework — each page is self-contained with its own styling and logic.

Backend (Vercel Serverless)

Node.js API functions deployed on Vercel. Each file is an independent serverless function handling specific routes.

Database (PostgreSQL)

Vercel Postgres with 20+ tables covering users, orgs, submissions, freight exchange, warehouses, billing, and more.

Authentication (JWT)

15-minute access tokens + 30-day refresh tokens. MFA support, account lockout, session management, and anomaly detection.

2 Data Model (Entity Relationships)

All the major tables in your database and how they connect to each other. Green lines show the new organization linkage.

Complete Entity Relationship Diagram

erDiagram ORGANIZATIONS ||--o{ USERS : "has members" ORGANIZATIONS ||--o{ INVITATIONS : "sends invites" ORGANIZATIONS ||--o{ SUBMISSIONS : "owns" ORGANIZATIONS ||--o{ FREIGHT_LISTINGS : "posts" ORGANIZATIONS ||--o{ FREIGHT_BIDS : "places" ORGANIZATIONS ||--o{ WAREHOUSES : "operates" ORGANIZATIONS ||--o{ BILLING_ACCOUNTS : "pays via" ORGANIZATIONS ||--o{ STAKEHOLDERS : "manages" ORGANIZATIONS ||--o{ SLA_DEFINITIONS : "customizes" USERS ||--o{ SESSIONS : "authenticates" USERS ||--o{ API_KEYS : "has keys" USERS ||--o{ CONVERSATIONS : "chats" USERS ||--o{ AGENT_MEMORY : "AI learns" USERS ||--o{ SEARCH_HISTORY : "searches" USERS ||--o{ USAGE_TRACKING : "metered" SUBMISSIONS ||--o{ NOTES : "has notes" SUBMISSIONS ||--o{ AUDIT_LOG : "tracked" SUBMISSIONS ||--o{ EMAIL_THREADS : "emails" SUBMISSIONS ||--o{ SLA_TRACKING : "SLA tracked" FREIGHT_LISTINGS ||--o{ FREIGHT_BIDS : "receives bids" ORGANIZATIONS { text id PK text name text slug UK text logo_url text primary_color text secondary_color text website text industry text country jsonb settings } USERS { text id PK text email UK text name text role text status text organization_id FK text usage_tier bool mfa_enabled } SUBMISSIONS { text id PK text ref_id UK text type text status text organization_id FK text client_id jsonb data } FREIGHT_LISTINGS { text id PK text kind text status text poster_user_id text poster_org_id FK text poster_org_name jsonb lane real target_budget } FREIGHT_BIDS { text id PK text listing_id FK text bidder_user_id text bidder_org_id FK text bidder_org_name real amount text status } WAREHOUSES { text id PK text organization_id FK text name text operator text kind text status text country text city } BILLING_ACCOUNTS { text id PK text user_id FK text organization_id FK text tier_id text status text stripe_customer_id }
TablePurposeOrg Linked?Record Count Scope
organizationsCompany accounts (branding, settings)PrimaryPlatform-wide
usersUser accounts + authorganization_idPlatform-wide
submissionsRFIs, freight quotes, feedbackorganization_idOrg-scoped
freight_listingsLoad board: loads & capacityposter_org_idMarket-wide (visible)
freight_bidsBids on freight listingsbidder_org_idPer listing
warehousesWarehouse network profilesorganization_idOrg-scoped
billing_accountsStripe-ready billingorganization_idOrg-level
stakeholdersClient contacts for SLAsorganization_idOrg-scoped
sla_definitionsCustom SLA rulesorganization_idOrg-scoped
conversationsAI chat historyorganization_idPer user
sessionsLogin sessions + refresh tokensVia userPer user

3 Authentication & User Flow

How users sign up, log in, and get routed to the right part of the platform based on their role.

Login Flow

sequenceDiagram participant U as User participant B as Browser participant API as Auth API participant DB as PostgreSQL participant S as Browser Storage U->>B: Opens login.html U->>B: Enters email + password B->>API: POST /api/auth?action=login API->>DB: SELECT * FROM users WHERE email = ? API->>API: Verify password hash API->>API: Check lockout / MFA API->>DB: Create session + refresh token API->>DB: Fetch organization branding API-->>B: JWT token + user + org branding B->>S: sessionStorage: access token B->>S: sessionStorage: user data B->>S: localStorage: refresh token B->>S: localStorage: org branding alt Role = CUSTOMER or PARTNER B->>U: Redirect to /portal else Role = PLATFORM_ADMIN or OPS_MANAGER B->>U: Redirect to /admin else Other roles B->>U: Redirect to /app end

Signup Flow (with Company Self-Registration)

sequenceDiagram participant U as New User participant B as Browser participant API as Auth API participant DB as PostgreSQL alt Invitation-Based Signup U->>B: Opens signup.html?token=abc123 B->>API: GET /api/auth?action=lookup-invite API-->>B: Email, role, organization pre-filled U->>B: Enters name + password B->>API: POST /api/auth?action=signup API->>DB: Create user (active, linked to org) API->>DB: Mark invitation as accepted API-->>B: JWT + auto-login else Open Signup (Self-Registration) U->>B: Opens signup.html U->>B: Enters name, email, company, password B->>API: POST /api/auth?action=signup API->>DB: Create user (pending approval) API->>DB: Auto-create organization from company name API->>DB: Link user to new organization API-->>B: Success — awaiting admin approval end

User Lifecycle

1
Sign Up

Via invite or open registration with company name

2
Pending

Admin reviews (if open signup)

3
Active

Full access per role + org

4
Org Linked

All data scoped to their company

5
Working

Submit RFIs, bid on freight, manage warehouses

4 Company & Organization Linkage

How companies (organizations) connect to everything else in the platform. This is the core of multi-tenancy.

Organization is the Center of Everything

graph TB ORG["Organization
(Company Account)"] ORG --> U1["User 1
Platform Admin"] ORG --> U2["User 2
Operations Manager"] ORG --> U3["User 3
Customer"] ORG --> U4["User 4
Warehouse Manager"] ORG --> WH1["Warehouse A
Riyadh"] ORG --> WH2["Warehouse B
Jeddah"] ORG --> S1["Submission 1
Freight RFI"] ORG --> S2["Submission 2
Warehouse RFI"] ORG --> FL1["Freight Listing
Load: JA to Rotterdam"] FL1 --> FB1["Bid from Company B"] FL1 --> FB2["Bid from Company C"] ORG --> BA["Billing Account
Stripe / Crypto"] ORG --> BR["Branding
Logo, Colors, Favicon"] BR --> P1["Login Page"] BR --> P2["Portal"] BR --> P3["Workspace"] BR --> P4["Dispatch"] BR --> P5["Freight Exchange"]

Organization Management API

graph LR subgraph OrgActions["Organization API Actions"] A1["my-org
Get your org"] A2["get
Get org by ID"] A3["list
List all orgs"] A4["create
New org"] A5["update
Edit org"] A6["upload-logo
Logo upload"] A7["assign-user
Link user to org"] A8["members
List org members"] A9["remove-member
Remove from org"] A10["delete
Delete org"] end Client["Any Page"] -->|"POST /api/users?action=org-*"| OrgActions

How Users Join an Organization

A
Invited

Admin invites user with email + role + org

B
Signs Up

User clicks invite link and creates account

C
Auto-Linked

organization_id set from invitation

D
Sees Org Data

All queries filtered by their org

A
Self-Register

User signs up with company name

B
Org Created

System auto-creates organization

C
Pending

Admin approves the user

D
Active + Linked

User is active in their company

5 Freight Exchange Flow

How loads are posted, bids are placed, and deals are awarded — now with company context.

Freight Exchange Lifecycle

sequenceDiagram participant Shipper as Shipper (Company A) participant FX as Freight Exchange participant Carrier1 as Carrier (Company B) participant Carrier2 as Carrier (Company C) participant DB as Database Shipper->>FX: Post Load
"40ft FCL Jebel Ali → Rotterdam" FX->>DB: INSERT freight_listings
poster_org_id = Company A FX-->>Carrier1: Load appears on board
with Company A badge FX-->>Carrier2: Load appears on board
with Company A badge Carrier1->>FX: Place Bid ($2,450) FX->>DB: INSERT freight_bids
bidder_org_id = Company B Carrier2->>FX: Place Bid ($2,200) FX->>DB: INSERT freight_bids
bidder_org_id = Company C Shipper->>FX: Review bids
sees company names Shipper->>FX: Accept Company C's bid FX->>DB: UPDATE listing → awarded FX->>DB: UPDATE winning bid → accepted FX->>DB: UPDATE losing bids → rejected FX-->>Carrier2: Congratulations! Bid accepted FX-->>Carrier1: Sorry, another bid was accepted

Load Posting

Companies post loads with origin, destination, equipment, cargo type, DG class, incoterms, and budget. Company name now displayed on each listing.

Company Context Added

Bid Placement

Carriers bid on loads with amount, currency, and message. The bidder's company name is now stored and visible to the listing owner.

Company Context Added

Award & Close

Listing owner accepts a bid — the listing is marked "awarded", winning bid "accepted", and all other pending bids are auto-rejected.

Market Intelligence

AI agent assists with rate analysis, route optimization, DG classification, and market outlook via the built-in chat.

6 Branding Flow

How organization branding (logo, colors) flows from the database to every page the user sees.

Branding Data Flow

sequenceDiagram participant DB as PostgreSQL participant API as Auth API participant LS as localStorage participant PB as platform-branding.js participant Page as Any Page Note over DB: organizations table stores
logo_url, primary_color,
secondary_color, favicon_url API->>DB: Fetch org branding on login API-->>LS: Cache in bdxp_organization_branding Page->>PB: Page loads → script runs PB->>LS: Read cached branding PB->>Page: Apply CSS variables
--org-primary, --org-secondary PB->>Page: Update favicon PB->>Page: Update logo images PB->>Page: Update org name text PB->>API: Background refresh from API API->>DB: GET /api/auth?action=me API-->>PB: Fresh branding data PB->>LS: Update cache PB->>Page: Re-apply if changed

Pages with Branding Loader

PageFileBranding Applied
Loginlogin.htmlYes (built-in + loader)
Signupsignup.htmlYes (built-in)
Customer Portalportal.htmlYes (built-in + loader)
Settingssettings.htmlYes (loader added)
Admin / Command Centeradmin.htmlYes (loader added)
Freight Exchangewajeeh-enterprise-master.html?fx=1 (Loadboard tab)Yes (built-in to master shell)
Dispatch Centerdispatch.htmlYes (loader added)
Main Workspacewajeeh-enterprise-master.htmlPartial (large file, manual)

7 Before vs After (Gap Fixes)

Side-by-side comparison of what the platform looked like before and after the architecture improvements.

Before (Gap)
After (Fixed)

GAP 1: No Data Isolation

  • submissions had no organization_id
  • freight_listings had no company context
  • freight_bids had no company context
  • warehouses floated freely — no org link
  • billing was user-level only
  • Company A could see Company B's data

FIXED: Full Organization Scoping

  • organization_id on submissions, stakeholders, SLA defs
  • poster_org_id + poster_org_name on freight listings
  • bidder_org_id + bidder_org_name on freight bids
  • organization_id on warehouses
  • organization_id on billing_accounts
  • API queries now filter by org automatically

GAP 2: No Self-Registration

  • Only admins could create organizations
  • New users had to be manually invited
  • No company field on signup form
  • Customers couldn't onboard themselves

FIXED: Company Self-Registration

  • Signup form now has Company field
  • System auto-creates org from company name
  • Or links to existing org by slug match
  • User auto-linked to their company on signup

GAP 3: No Member Management

  • No way to list "users in my company"
  • No way to remove a member from org
  • No org-level permissions

FIXED: Organization Member Management

  • org-members API lists all org users
  • org-remove-member API removes users from org
  • New org:* permission categories in RBAC

GAP 4: No Branding on Most Pages

  • Branding only on login + portal
  • Dispatch had missing CSS/JS files
  • No shared branding loader
  • Each page styled independently

FIXED: Platform-Wide Branding

  • platform-branding.js added to all major pages
  • Missing flex-theme files created
  • CSS variables --org-primary, --org-secondary
  • Auto-refresh branding from API on page load

GAP 5: Freight Had No Company Context

  • Listings showed user IDs only
  • Bids showed user IDs only
  • No way to know which company posted a load
  • No company badges on cards

FIXED: Company Context Everywhere

  • Listings store poster_org_id + poster_org_name
  • Bids store bidder_org_id + bidder_org_name
  • Company badge displayed on each card
  • Companies compete, not just individual users

8 Roles & Permissions Matrix

The 10 roles in the platform and what each one can access. Higher level = more permissions.

Role Hierarchy

graph TB PA["Platform Admin
Level 100
Full access to everything"] OM["Operations Manager
Level 90
Manage ops, no user admin"] CM["Commercial Manager
Level 80
Sales, quotes, own queue"] WM["Warehouse Manager
Level 80
Warehouse ops, own queue"] SA["Support Agent
Level 70
Support tickets, compliance"] CO["Compliance Officer
Level 70
Compliance, escalations"] FI["Finance
Level 60
Revenue, billing, exports"] CU["Customer
Level 30
Own submissions, portal"] PR["Partner
Level 30
Own submissions, portal"] VW["Viewer
Level 10
Read-only, tester"] PA --> OM OM --> CM OM --> WM CM --> SA WM --> SA SA --> CO CO --> FI FI --> CU FI --> PR CU --> VW PR --> VW
PermissionPlatform AdminOps ManagerCommercialWarehouseSupportCustomerPartnerViewer
Manage Users+
Invite Users+
View All Submissions++
View Own Submissions+++++++
Create Submissions++++++
Manage Settings+
View Settings++
Manage Billing+
Security Audit+
AI Analyze+++++
AI Ask++++++++
Export CSV+++++
Portal Access++
Org Members++++
Org Manage Members++

Usage Tiers

TierPrice/moDaily AI TokensMonthly AI TokensAPI Requests/dayMax UsersDefault For
Free$010,000200,0001001Viewer
Standard$49100,0002,000,0001,0005Customer, Partner, Support, Compliance, Finance
Professional$199500,00010,000,0005,00025Ops Manager, Commercial, Warehouse
EnterpriseCustomUnlimitedUnlimitedUnlimitedUnlimitedPlatform Admin