OA Portal Architecture

Architecture Overview

OA Portal Ecosystem Architecture

Three Portals. Two Databases. One Admin.

The OA portal ecosystem consists of three separate applications, each serving a different audience. A Client Portal for business owners, an Employee Portal for OA internal staff, and an Admin Portal that Brad uses to orchestrate both systems.

All four AI brains (Sterling, Claude, ChatGPT 5.5, reconciliation) converged on the same core architecture: two completely separate D1 databases, managed auth via Clerk, tenant-scoped client data, and one admin orchestrator bridging both systems.

👤
Client Portal
client.outsourceaccess.com
What business owners see. VA performance dashboards, industry research, satisfaction history, billing, and owner-only feedback. Each client only sees their own data via tenant-scoped middleware.
🏢
Employee Portal
server.outsourceaccess.com
What OA staff sees, organized by role. AMs see their client portfolio. OMs see team performance. TLs see their VA assignments. VAs see daily tasks. Payroll, HR, benefits data lives here exclusively.
⚙️
Admin Portal
admin.outsourceaccess.com
Brad's orchestrator. Not a third database... it's a bridge with dual D1 bindings. Create client accounts, manage employee roles, push content to either portal, view cross-system analytics.
Core Architecture Principles
🔒
Physical Database Separation
Employee DB and Client DB are completely separate D1 databases. A breach of the client surface physically cannot reach payroll, health insurance, or HR data.
🏗
Tenant-Scoped Client Data
One shared client database with company_id on every table. Every query goes through TenantScopedDB middleware. Cross-client data leaks are structurally impossible.
🔐
Managed Auth via Clerk
Free up to 10K MAU, SOC 2 certified. JWT-based identity. Authentication is not authorization... server-side enforcement on every request.
📐
Two Products, Not Two User Types
Client Portal and Employee Portal have different navigation, data sources, permission models, and evolution trajectories. They're separate products operated by the same company.
🌐
Proper Subdomain Routing
Each portal gets its own subdomain on outsourceaccess.com. No pages.dev URLs for production. Cloudflare Workers handle routing.
Full Architecture Decision Document The detailed four-brain consensus analysis (Sterling, Claude, ChatGPT 5.5, reconciliation) with code patterns, test scenarios, and enforcement mechanics is at oa-portal-architecture.pages.dev.
Visual Architecture Diagram
Authentication Layer
Clerk (Managed Auth)
Free up to 10K MAU | SOC 2 Certified
JWT tokens, email/password, SSO
▼   JWT Tokens   ▼
Application Layer (Cloudflare Workers)
Client Worker
client.outsourceaccess.com
Business owner dashboards
Employee Worker
server.outsourceaccess.com
OA staff by role (AM/OM/TL/VA)
Admin Worker
admin.outsourceaccess.com
Orchestrator (Brad only)
▼   D1 Bindings   ▼
Data Layer (Cloudflare D1)
oa-client-db
Shared tenant architecture
company_id on every table
VA performance, CSAT, billing, resources
oa-employee-db
Internal OA data only
Physically isolated from clients
Payroll, HR, benefits, team structure
▲   API Integrations   ▲
External Data Sources
HubSpot CRM
Client records, contacts
Time Doctor
VA time tracking
CSAT Surveys
Client satisfaction
Zoho Recruit
Hiring pipeline
Billing/Stripe
Invoicing, payments
Connection Map
Client Worker binds to oa-client-db only. Cannot access employee data at any layer.
Employee Worker binds to oa-employee-db only. Cannot access client data at any layer.
Admin Worker has dual bindings: BINDING_CLIENT to oa-client-db and BINDING_EMPLOYEE to oa-employee-db. Routes: /api/admin/client/* hits client DB, /api/admin/employee/* hits employee DB.
Clerk handles all authentication. JWTs are verified server-side on every request. The JWT contains the user's role and company_id. Workers extract identity from the signed token, never from browser-sent parameters.
Admin Worker Is a Bridge, Not a Data Store The admin portal does NOT have its own database. It orchestrates both existing databases through dual D1 bindings. This keeps the data model clean: two databases, three access points.
Client Portal (client.outsourceaccess.com)

What Business Owners See

Each OA client company gets a login where the business owner (and optionally their team) can view their VA's performance, satisfaction scores, industry resources, billing history, and submit feedback. Every client only sees their own data, enforced by TenantScopedDB middleware.

Dashboard Sections
VA Performance
Hours logged, tasks completed, productivity metrics from Time Doctor. Visual charts and trends over time.
Satisfaction History
CSAT scores over time, feedback history, trend analysis. Proactive alerts if scores dip below threshold.
Industry Research
Sterling-generated industry intelligence, competitor insights, and strategic advisory documents tailored to the client's vertical.
Billing & Invoicing
Current plan, payment history, invoice downloads. Integration with Stripe for transparent billing.
Owner Feedback
Submit feedback, rate VA performance, request changes. Feedback flows to the AM and triggers internal workflows.
Resources & Guides
OA Playbook access, onboarding guides, best practices for working with VAs. Curated content library.
Current State
URLStatusWhat It IsPassword
clients.outsourceaccess.com Demo Current deployed project (SSV hardcoded demo data) Custom email/password auth
client.outsourceaccess.com No DNS Desired singular subdomain (needs CNAME record) --
oa-ecosystem.pages.dev/client-demo Demo Active Armor Pest Control static mockup oademo2026 (on main ecosystem page)
oa-client-demo.pages.dev Demo Acme Roofing & Construction static mockup None (static page)
DNS Action Required Brad wants client.outsourceaccess.com (singular). Currently only clients.outsourceaccess.com (plural) has a CNAME record. Need to add the singular CNAME on OA Cloudflare account.
Employee Portal (server.outsourceaccess.com)

Internal OA Staff Dashboard

Role-based views for OA's ~500 staff. Each role sees exactly what they need: AMs see their client portfolio, OMs see team performance, TLs see their VAs, and VAs see daily tasks and time tracking. Sensitive HR, payroll, and benefits data lives exclusively in the employee database.

Role-Based Views
Account Manager (AM)
Client-facing strategic advisory
  • Client portfolio overview with health scores
  • CSAT trends and satisfaction alerts
  • Client feedback and action items
  • Strategic advisory document access
  • Upsell/cross-sell opportunity tracking
Operations Manager (OM)
Oversees TLs and client ops
  • Team performance dashboards
  • TL accountability tracking
  • Client escalation queue
  • Resource allocation and capacity
  • Quality assurance metrics
Team Leader (TL)
Manages VAs directly
  • VA assignment management
  • Daily check-in tracking
  • Time Doctor summaries per VA
  • Weekly update submission forms
  • Performance coaching notes
Virtual Assistant (VA)
Day-to-day task execution
  • Daily task assignments
  • Time tracking integration
  • Client-specific SOPs and playbooks
  • Communication logs
  • Training resources
CEO / Executive (Brad)
Full visibility across all roles
  • Company-wide KPI dashboard
  • Revenue and retention metrics
  • Employee performance rankings
  • Client health overview
  • Payroll and financial summaries
Current State
URLStatusWhat It IsNotes
server.outsourceaccess.com Demo CNAME points to same project as clients.* Same oa-client-dashboards project
oa-ceo-dashboard.pages.dev Live CEO business intelligence dashboard (standalone) Password: OA2026
ceo-financial-dashboard.pages.dev Live CEO financial dashboard (standalone) Password: OA2026
Employee Portal Needs Its Own Worker Currently server.outsourceaccess.com points to the same Cloudflare Pages project as clients.outsourceaccess.com. Per the architecture decision, it needs a separate Worker with its own D1 binding to the employee database.
Admin Portal (admin.outsourceaccess.com)

Brad's Orchestrator

The admin portal is NOT a third database. It's a single Worker with dual D1 bindings that lets Brad (and authorized OA admins) manage both the client and employee systems from one interface. Think of it as the control room.

Admin Capabilities
Client Management
Create new client companies, invite client users, assign VAs to clients, manage client billing plans. Routes through /api/admin/client/*
Employee Management
Manage OA staff accounts, assign roles (AM/OM/TL/VA), update permissions, HR data. Routes through /api/admin/employee/*
Content Publishing
Push industry research, resources, and strategic advisory docs to client portals. Publish internal communications to employee portal.
Cross-System Analytics
View data from both databases in unified reports. Client health vs employee performance correlations. Revenue analytics.
Routing Architecture
// Admin Worker routing
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname.startsWith('/api/admin/client/'))
      return handleClientRoute(request, env.BINDING_CLIENT);
    if (url.pathname.startsWith('/api/admin/employee/'))
      return handleEmployeeRoute(request, env.BINDING_EMPLOYEE);
  }
};
Current State
URLStatusNotes
admin.outsourceaccess.com No DNS Needs CNAME record + dedicated Worker
oa-client-dashboards.pages.dev/admin/ Demo Current admin route on shared project (basic user management UI)
Data Sources & Integrations

Every data source that feeds into the portal ecosystem, mapped to which portal(s) consume it and how data flows.

HubSpot CRM
Master client records, contacts, deal stages, company properties, engagement history, and lifecycle data. Account ID: 40014162. API key in Keychain.
Client Portal Employee Portal Admin Portal
Time Doctor
VA time tracking, productivity metrics, screenshot monitoring, task logs. 306 users, company ID XbgGwywYQgAcv3jl. Feeds both client-facing performance and internal TL oversight.
Client Portal Employee Portal
CSAT Surveys
Client satisfaction scores, feedback forms, trend data. Triggered periodically and after key milestones. Results visible to both clients and AMs.
Client Portal Employee Portal
Stripe / Billing
Invoice generation, payment processing, subscription management. Clients see their billing history, admin manages plans and pricing. Live keys in Keychain.
Client Portal Admin Portal
Clerk (Auth Provider)
User authentication, session management, JWT token issuance. Handles login/signup, password resets, SSO, and MFA. Free up to 10K MAU, SOC 2 certified.
Client Portal Employee Portal Admin Portal
Zoho Recruit
Hiring pipeline, candidate tracking, VA recruitment workflow. Org ID 884118196. Internal-only data feeding HR and team allocation dashboards.
Employee Portal Admin Portal
Data Flow Patterns
➡️
HubSpot → Client DB (sync)
Client company records, VA assignments, and contact info sync from HubSpot into oa-client-db. HubSpot remains the source of truth for CRM data. Scheduled sync via Workers Cron.
➡️
Time Doctor → Both DBs (API pull)
Productivity data pulled via Time Doctor API. Client-facing summary goes to oa-client-db. Detailed per-VA breakdown goes to oa-employee-db for TL/OM review.
➡️
CSAT → Client DB (webhook)
Survey responses land in oa-client-db tagged by company_id. Visible to the client on their dashboard and to the AM on the employee portal.
➡️
Stripe → Client DB (webhook)
Payment events (invoice paid, subscription updated) flow into oa-client-db. Clients see billing status. Admin manages plan changes.
Authentication & Permissions

Authentication Is Not Authorization

Clerk handles authentication (who are you?). The Workers handle authorization (what can you see?). Separate logins don't prevent data leaks... server-side enforcement on every request, with identity derived from cryptographically signed JWTs, is what prevents leaks.

Clerk Setup
Provider: Clerk (clerk.com) - Free up to 10K MAU, SOC 2 Type 2 certified
Auth Methods: Email/password (primary), Google SSO (optional), MFA (optional)
Token Format: JWT with claims: user_id, role, company_id (for client users), org_id (for employees)
Session: Short-lived access tokens (5 min) + long-lived refresh tokens (30 days)
Verification: Every Worker verifies JWT signature server-side before processing any request. Identity extracted from token, never from browser parameters.
Permission Matrix
RolePortalCan SeeCan Edit
Client Owner Client Own company VA perf, CSAT, billing, resources Feedback, settings
Account Manager Employee Assigned clients' data, CSAT, strategic docs Client notes, advisory docs
Operations Manager Employee All TLs under them, team metrics, escalations Team assignments, escalation responses
Team Leader Employee Assigned VAs, time tracking, daily check-ins VA notes, weekly updates
Virtual Assistant Employee Own tasks, time logs, SOPs Task status, time entries
CEO / Admin Admin Everything across both databases Everything (user creation, role changes, content push)
TenantScopedDB Middleware
// Every client DB query is scoped automatically
class TenantScopedDB {
  constructor(db, companyId) {
    this.db = db;
    this.companyId = companyId;
  }
  query(sql, ...params) {
    // Automatically injects WHERE company_id = ?
    const scoped = injectTenantScope(sql, this.companyId);
    return this.db.prepare(scoped).bind(...params, this.companyId).all();
  }
}
Developers never write raw queries. The middleware intercepts every database call and injects the company_id filter. Cross-client data leaks become structurally impossible at the code level.
User Creation & Onboarding Flows
Client User Creation Flow
1

Brad/Admin Creates Client Company

In admin portal, creates a new company record in oa-client-db with company name, industry, plan tier, assigned AM.

2

Admin Invites Client Owner

Enters client owner's email. Clerk sends an invitation email with a secure signup link to client.outsourceaccess.com.

3

Client Owner Completes Signup

Client clicks link, sets password via Clerk. Their Clerk user is automatically linked to their company_id in the client DB.

4

Client Accesses Dashboard

On login, JWT contains their company_id. All queries are automatically scoped. They only see their own VA performance, CSAT, billing.

Employee User Creation Flow
1

HR/Admin Creates Employee Record

In admin portal, creates employee in oa-employee-db with name, role (AM/OM/TL/VA), reporting structure, start date.

2

Admin Assigns Role & Permissions

Sets the employee's role which determines their view on server.outsourceaccess.com. Assigns to specific clients/teams as needed.

3

Clerk Invitation Sent

Employee receives signup email. Creates account via Clerk. Their Clerk user is linked to their employee record and role.

4

Employee Logs In

JWT contains role and org_id. Employee portal renders the appropriate role-based view automatically. AMs see clients, TLs see VAs, etc.

Admin Access Flow
1

Brad Logs In

Brad authenticates at admin.outsourceaccess.com via Clerk. His JWT contains role: "admin" with full privileges.

2

Admin Worker Validates

Worker verifies JWT, checks admin role. If not admin, returns 403. No client or regular employee can access admin routes.

3

Dual Database Access

Admin Worker has BINDING_CLIENT and BINDING_EMPLOYEE. Brad can query, create, update, and delete records in either database from one interface.

All URLs & Login Status

Every URL in the OA portal ecosystem with current deployment status, login credentials, and purpose.

Production Subdomains (outsourceaccess.com)
URLDNSStatusPurposeAuth
client.outsourceaccess.com Missing Planned Client-facing portal (singular, preferred) Clerk (planned)
clients.outsourceaccess.com Active Demo Currently deployed, SSV demo data Custom email/password (PBKDF2)
server.outsourceaccess.com Active Demo Points to same project as clients.* Same as clients.*
admin.outsourceaccess.com Missing Planned Brad's admin orchestrator Clerk (planned)
Cloudflare Pages (pages.dev)
URLAccountStatusPurposePassword
oa-client-dashboards.pages.dev OA Team Demo Main portal project (login + dashboard + admin routes) Custom email/password
oa-portal-architecture.pages.dev Brad Personal Reference Four-brain architecture decision document None
oa-ceo-dashboard.pages.dev Brad Personal Live CEO business intelligence dashboard OA2026
ceo-financial-dashboard.pages.dev Brad Personal Live CEO financial dashboard OA2026
oa-client-demo.pages.dev Brad Personal Demo Acme Roofing & Construction static mockup None (static page)
oa-dash-directory.pages.dev OA Team Live This page (master architecture map) None
Related Pages (NOT Part of Portal Project)
URLStatusPurposePassword
oa-ecosystem.pages.dev Live Strategic planning tool for managers (NOT a portal dashboard) OA2026
oa-ecosystem.pages.dev/client-demo Demo Active Armor Pest Control static mockup (lives under ecosystem) oademo2026 (ecosystem gate)
capcon-dashboard.pages.dev External Built by Alva (Philippines team) using Claude co-work, not Sterling Unknown
Cloudflare Account Note Portal infrastructure (oa-client-dashboards, oa-dash-directory) lives on the OA Team Cloudflare account (79bf9918...). Standalone dashboards and research pages live on Brad's personal account (f80e8ac3...).
Gap Analysis: Current vs Target
Architecture Gaps
Critical Single Project Serves Both Portals
Currently clients.outsourceaccess.com and server.outsourceaccess.com both point to the same Cloudflare Pages project (oa-client-dashboards) with one D1 database. The architecture requires separate Workers with separate D1 bindings.
Critical No Auth Provider (Clerk Not Integrated)
Current auth is custom PBKDF2 email/password with session cookies. Architecture calls for Clerk-managed auth with JWT tokens. Clerk needs to be set up with proper organizations and role claims.
Critical No Second Database (Employee DB)
Only one D1 database exists (oa-client-dashboards-db). Architecture requires a separate oa-employee-db for payroll, HR, benefits, and team structure data. Physical separation is the security guarantee.
Medium DNS Records Missing
client.outsourceaccess.com (singular) and admin.outsourceaccess.com have no CNAME records. Need to be created on OA Cloudflare.
Medium Hardcoded Demo Data
The current deployed dashboard at clients.outsourceaccess.com has "Support Services of Virginia" hardcoded. Needs to be replaced with dynamic data pulled from D1 based on the authenticated user's company_id.
Enhancement No External Data Integrations
HubSpot, Time Doctor, CSAT, and Stripe are not yet connected. Architecture calls for Workers Cron jobs that sync data from these sources into the respective D1 databases.
Build Roadmap

Sequenced build plan based on the four-brain architecture consensus. Each phase can be built and deployed independently.

1
Foundation: Auth + Databases
Estimated: ~15 min Sterling build
☐ Set up Clerk account with OA organization
☐ Create oa-employee-db D1 database on OA Cloudflare
☐ Design and deploy schema for both D1 databases
☐ Add CNAME: client.outsourceaccess.com
☐ Add CNAME: admin.outsourceaccess.com
2
Client Portal: Dynamic Dashboard
Estimated: ~30 min Sterling build
☐ Convert client dashboard from hardcoded to dynamic (D1 queries with tenant scope)
☐ Integrate Clerk auth (replace custom PBKDF2)
☐ Build TenantScopedDB middleware
☐ Wire up client.outsourceaccess.com (singular) as primary domain
☐ Seed test client data for demo
3
Employee Portal: Role-Based Views
Estimated: ~45 min Sterling build
☐ Create separate Employee Worker with oa-employee-db binding
☐ Build role-based view rendering (AM/OM/TL/VA/CEO views)
☐ Integrate Clerk with role claims
☐ Wire up server.outsourceaccess.com to new Worker
☐ Seed test employee data
4
Admin Portal: Orchestrator
Estimated: ~30 min Sterling build
☐ Create Admin Worker with dual D1 bindings
☐ Build client company creation + user invitation flow
☐ Build employee management + role assignment
☐ Wire up admin.outsourceaccess.com
☐ Content publishing pipeline (push to either portal)
5
Data Integrations
Estimated: ~20 min per integration
☐ HubSpot sync (client records, contacts, deal stages)
☐ Time Doctor sync (VA productivity data)
☐ CSAT survey integration (satisfaction scores)
☐ Stripe integration (billing, invoicing)
☐ Zoho Recruit integration (hiring pipeline)
Sterling Build Time vs Human Build Time Total estimated Sterling build: ~2-3 hours across all phases. Human developer equivalent: $30-50K and 6-10 weeks. Each phase is independently deployable... Brad can review and approve phase by phase.