Helix Platform Monorepo
Version: 1.0.0
Status: Foundation Complete - Ready for Service Implementation
Architecture: Microservices in Nx Monorepo with CLS & WorkOS RBAC
Overview
Helix is CleverChain's unified, multi-tenant microservices platform that serves as an "operating system" layer for all CleverChain products (CleverScreen, KIRA, VERA). This monorepo contains all backend microservices, shared libraries, database schemas, and infrastructure code.
Key Principles
The monorepo is a DEVELOPMENT structure.
Containers contain PRODUCTION artifacts.
- CLS Architecture: Continuation-Local Storage (nestjs-cls) for context throughout request lifecycle
- WorkOS RBAC: Roles managed by WorkOS, included in JWT tokens (NOT stored in our databases)
- 3-Tier Databases: Physical tenant isolation with jurisdiction-based database servers
- No Hardcoded Config: Service URLs and credentials from environment variables
Current State
✅ Phase 1,2,3: Foundation Complete
Infrastructure
- ✅ Nx monorepo structure
- ✅ Docker Compose configuration
- ✅ Terraform infrastructure modules
- ✅ TypeScript configuration with path aliases
- ✅ ESLint & Prettier setup
Database Schemas
- ✅ Tier 1 (Central DB): Platform metadata, NO PII, NO roles
- ✅ Tier 2 (Tenant DB): Shared tenant data WITH PII, physical isolation
- ✅ Tier 3 (Product DBs): Service-specific schemas (when services built)
Shared Libraries (14 libraries)
- ✅ Types - Platform type definitions
- ✅ Interfaces - Core interface shapes
- ✅ Middleware - 5 middleware with CLS (Auth, Tenant, Product, Logging, RateLimit)
- ✅ Guards - 4 guards with WorkOS RBAC (JwtAuth, Roles, Scopes, TenantAccess)
- ✅ Decorators - CLS extractors (CurrentUser, TenantId)
- ✅ Pipes - Validators (UUID, Pagination)
- ✅ Database - Centralized service for all 3 tiers
- ✅ Migrations - Unified migrators (Tenant & Product)
- ✅ Utils - Crypto, date, retry, circuit-breaker
- ✅ Constants - Error codes, defaults, rate limits
- ✅ Validators - Zod schemas (minimal shared)
- ✅ Filters - Exception handling (HTTP, Prisma)
- ✅ Prisma Central - Tier 1 client library
- ✅ Prisma Tenant - Tier 2 client library
🚧 Phase 4: Services (Next)
Microservices to be implemented:
- API Gateway
- Auth Service
- Tenant Service
- Admin Service
- File Service
- KIRA Service (AI assistant)
- VERA Service (report generation)
- CleverScreen Service (compliance screening)
Architecture Highlights
CLS (Continuation-Local Storage)
All context stored in CLS, not request object. Works everywhere:
- HTTP requests
- WebSocket connections
- Cron jobs
- Background workers
// Anywhere in your code
const auth = cls.get('auth');
const tenant = cls.get('tenant');
const product = cls.get('product');
WorkOS RBAC Integration
Roles and permissions from JWT tokens ONLY:
- No role storage in databases
- AuthenticationMiddleware validates JWT with JWKS
- Verifies sessions via WorkOS API
- session.organization_id determines tenant
// JWT payload
{
"sub": "user_01HXYZ",
"org_id": "org_01ABC",
"role": "tenant_admin",
"permissions": ["tenant:write", "user:read"]
}
3-Tier Database Architecture
Tier 1: Central DB
- Platform metadata
- NO PII (GDPR compliant)
- NO roles (WorkOS manages)
- Tenant-organization mapping
- Database credentials storage (Tier 2 & 3)
Tier 2: Tenant Databases
- One database per tenant:
tenant_{uuid}_shared - Full user profiles WITH PII
- Files, notifications, team settings
- Product access control
- Multi-jurisdiction support (UK, EU, US servers)
Tier 3: Product Databases
- One database per tenant-product:
tenant_{uuid}_{product} - Product-specific business data
- Service-owned schemas
- Independent evolution
Prerequisites
- Node.js: >= 18.0.0
- npm: >= 9.0.0
- Docker: For local development
- PostgreSQL: 14+ (for local dev)
- Redis: For caching
- WorkOS Account: For authentication
Getting Started
1. Clone & Install
git clone <repository-url>
cd HelixCore
npm install
2. Environment Setup
cp .env.example .env
# Edit .env with your values
Required environment variables:
# Central Database
CENTRAL_DATABASE_URL=postgresql://user:pass@localhost:5432/helix_central
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
# WorkOS
WORKOS_API_KEY=sk_your_api_key
WORKOS_CLIENT_ID=client_your_client_id
# Service URLs (for inter-service communication)
FILE_SERVICE_URL=http://file-service:3004
ADMIN_SERVICE_URL=http://admin-service:3003
3. Database Setup
# Initialize databases
./scripts/init-db.sh
# Generate Prisma clients
npm run prisma:generate:central
npm run prisma:generate:tenant
# Run migrations
cd prisma/central && npx prisma migrate deploy
cd prisma/tenant && npx prisma migrate deploy
4. Start Development
# Start infrastructure (PostgreSQL, Redis)
docker-compose up -d postgres redis
# Build shared libraries
npm run build
# Start a service (when implemented)
nx serve auth-service
Project Structure
HelixCore/
├── apps/ # Microservices (to be implemented)
│ └── .gitkeep
├── libs/shared/ # Shared libraries (14 libraries)
│ ├── constants/ # Error codes, defaults, rate limits
│ ├── database/ # DatabaseService (Tier 1/2/3 access)
│ ├── decorators/ # CLS extractors (CurrentUser, TenantId)
│ ├── filters/ # Exception filters
│ ├── guards/ # Auth guards (CLS-based)
│ ├── interfaces/ # Interface definitions
│ ├── middleware/ # 5 middleware with CLS
│ ├── migrations/ # Tenant & Product migrators
│ ├── pipes/ # Validation pipes
│ ├── types/ # Type definitions
│ ├── utils/ # Crypto, retry, circuit-breaker
│ └── validators/ # Zod schemas (minimal)
├── prisma/
│ ├── central/ # Tier 1: Central DB schema
│ │ ├── schema.prisma
│ │ └── migrations/
│ └── tenant/ # Tier 2: Tenant DB schema
│ ├── schema.prisma
│ └── migrations/
├── terraform/ # Infrastructure as Code
│ ├── global/ # Global resources
│ ├── environments/ # Per-environment config
│ └── modules/ # Reusable modules
├── scripts/ # Utility scripts
│ └── init-db.sh
├── project-context/ # Architecture documentation
├── docker-compose.yml # Local development
├── nx.json # Nx workspace config
├── tsconfig.base.json # TypeScript path aliases
└── package.json # Unified dependencies
Shared Libraries
Core Libraries
@helix/shared/types - Type definitions
import { UserRole, ServiceStatus, ProductType } from '@helix/shared/types';
@helix/shared/interfaces - Interface shapes
import { RequestContext, TenantBase, HealthCheckResponse } from '@helix/shared/interfaces';
@helix/shared/database - Database service (all 3 tiers)
import { DatabaseService } from '@helix/shared/database';
const tenant = await db.central().tenant.findUnique({ where: { id } });
const member = await db.tenant().teamMember.findFirst({ where: { workosUserId } });
const threads = await db.product().thread.findMany({ where: { createdBy } });
Middleware (CLS Architecture)
import {
AuthenticationMiddleware, // JWT validation with JWKS
TenantContextMiddleware, // Loads Tier 2 DB credentials
ProductContextMiddleware, // Loads Tier 3 DB credentials
RequestLoggingMiddleware, // UUID generation, timing
RateLimitMiddleware, // Role-based throttling
} from '@helix/shared/middleware';
Guards (WorkOS RBAC)
import {
JwtAuthGuard,
RolesGuard,
Roles,
ScopesGuard,
RequireScopes,
TenantAccessGuard,
} from '@helix/shared/guards';
@Roles('tenant_admin')
@RequireScopes('tenant:write')
@UseGuards(JwtAuthGuard, RolesGuard, ScopesGuard)
async updateTenant() {}
Decorators & Pipes
import { CurrentUser, TenantId } from '@helix/shared/decorators';
import { UuidValidationPipe, PaginationPipe } from '@helix/shared/pipes';
@Get()
async findAll(
@CurrentUser() auth: any,
@TenantId() tenantId: string,
@Query(PaginationPipe) pagination: PaginationParams,
) {
return this.service.findAll(tenantId, pagination);
}
Utilities
import {
encrypt,
decrypt,
retry,
CircuitBreaker,
getCurrentTimestamp,
} from '@helix/shared/utils';
Migrations
import { TenantMigrator, ProductMigrator } from '@helix/shared/migrations';
// Deploy: migrate all tenant databases
await tenantMigrator.migrateAll();
// Provision: migrate single tenant
await tenantMigrator.migrateOne(tenantId);
Database Access Pattern
Tier 1: Central DB (Static Connection)
const tenant = await db.central().tenant.findUnique({
where: { workosOrganizationId: orgId },
include: { tenantDatabase: true }
});
Tier 2: Tenant DB (Dynamic per Tenant)
// Context from CLS (set by TenantContextMiddleware)
const member = await db.tenant().teamMember.findFirst({
where: { workosUserId: userId }
});
const hasAccess = await db.tenant().userProductAccess.findFirst({
where: {
teamMember: { workosUserId: userId },
productType: 'kira',
revokedAt: null
}
});
Tier 3: Product DB (Dynamic per Product)
// Context from CLS (set by ProductContextMiddleware)
// Product client registered during service bootstrap
const threads = await db.product<KiraPrismaClient>().thread.findMany({
where: { createdBy: userId }
});
Available Commands
Development
# Install dependencies
npm install
# Build all libraries
npm run build
# Build specific library
nx build shared-database
# Lint all code
npm run lint
# Format code
npm run format
Database
# Generate Prisma clients
npm run prisma:generate:central
npm run prisma:generate:tenant
# Run Central DB migrations
cd prisma/central && npx prisma migrate deploy
# Migrate all tenant databases (deployment)
npm run migrate:tenants
# Migrate all product databases (deployment)
npm run migrate:products
# Migrate specific tenant (provisioning)
npm run migrate:tenant -- --tenant-id=abc123
Docker
# Start infrastructure
docker-compose up -d
# Stop infrastructure
docker-compose down
# View logs
docker-compose logs -f
Architecture Decisions
Why CLS?
Traditional request object attachment only works in HTTP context. CLS works everywhere:
- ✅ HTTP controllers
- ✅ WebSocket gateways
- ✅ Cron jobs
- ✅ Background workers
- ✅ Any async context
Why WorkOS for RBAC?
Single source of truth for roles and permissions:
- ✅ No role synchronization between systems
- ✅ Roles in signed JWT tokens (tamper-proof)
- ✅ No database queries for authorization
- ✅ Faster permission checks
- ✅ Enterprise SSO integration
Why 3-Tier Databases?
Physical tenant isolation with performance:
- Tier 1: Fast tenant selection (minimal data, no PII)
- Tier 2: Physical PII isolation per tenant
- Tier 3: Product autonomy and independent evolution
Why Separate Database Credentials?
Multi-jurisdiction compliance:
- UK tenants → UK database servers
- EU tenants → EU database servers
- US tenants → US database servers
Separate host, port, username, password fields (not encrypted blob) for:
- ✅ Credential rotation
- ✅ Different servers per tier
- ✅ Future-proof jurisdiction support
WorkOS Integration
JWT Validation Flow
- Extract JWT from Authorization header
- Verify signature with JWKS (cached indefinitely, rotates every 5 years)
- Decode claims - role, permissions, org_id, session_id
- Validate session via WorkOS API (cached 30 min)
- Get user data from WorkOS API (cached 30 min, NO PII in JWT)
- Store in CLS - auth, session, user
Organization Switching
WorkOS handles organization switching:
- User switches org in WorkOS UI
- New session created with different
organization_id - Our middleware reads
session.organization_id - TenantContextMiddleware finds tenant by
workosOrganizationId - User now in different tenant context
Multi-Tenant Database Strategy
Provisioning Flow
New Tenant:
- Create
Tenantrecord in Central DB - Provision Tier 2 database on chosen jurisdiction server
- Store credentials in
TenantDatabase(host, port, name, username, password) - Run Tier 2 migrations via
TenantMigrator - User created in Tier 2
TeamMembertable
New Product:
- Create
TenantProductrecord - Provision Tier 3 database on product-specific server
- Store credentials in
ProductDatabase - Run Tier 3 migrations via
ProductMigrator - Grant user access via
UserProductAccess(zero-trust, explicit grants)
Migration Strategy
Like Laravel's php artisan tenants:migrate:
# Deploy (all databases)
npm run migrate:central # Tier 1 (once)
npm run migrate:tenants # Tier 2 (all tenants)
npm run migrate:products # Tier 3 (all products)
# Provision (single database)
await tenantMigrator.migrateOne(tenantId);
await productMigrator.migrateOne(productId);
Service Communication
Services communicate via environment-configured URLs:
Local (Docker Compose):
kira-service:
environment:
- FILE_SERVICE_URL=http://file-service:3004
Production (ECS/Terraform):
environment = [
{
name = "FILE_SERVICE_URL"
value = "http://file-service.helix.local:3004"
}
]
In Code:
const fileServiceUrl = process.env.FILE_SERVICE_URL;
// NO hardcoded ports or URLs
Security Model
Authentication
- ✅ WorkOS JWT with JWKS signature verification
- ✅ Session validation (prevents token reuse after logout)
- ✅ User data from WorkOS API (always fresh)
- ✅ Comprehensive caching (performance without security compromise)
Authorization
- ✅ Roles from JWT tokens (NO database storage)
- ✅ Scopes from JWT tokens (NO database queries)
- ✅ TenantMember verification (access control)
- ✅ UserProductAccess (explicit product grants)
Tenant Isolation
- ✅ Physical database separation
- ✅ Middleware verifies membership
- ✅ Guards enforce context exists
- ✅ No cross-tenant data leakage
Documentation
Core Documents
Quick Reference
- Docker: See Docker Setup
- Prisma: See Database & Prisma
Contributing
Code Standards
- TypeScript strict mode
- No
anytypes - CLS for context (not req.user)
- WorkOS for roles (no database storage)
- Environment variables for config
- Service-specific validators in services
Before Committing
npm run lint
npm run format
npm run test
Next Steps
- Implement core services (HLX-6 through HLX-13)
- Set up GitHub Actions CI/CD
- Deploy to AWS ECS via Terraform
- Configure WorkOS production environment
Support
- Architecture Questions: See Architecture
- Implementation Standards: See Development Guidelines
- Jira: Track work in HLX project
- Team: CleverChain Platform Team
License
Proprietary - CleverChain Limited
Last Updated: 2025-10-22
Foundation Status: ✅ Complete
Next Phase: Microservice Implementation