Skip to content

Overview

The Teros platform is a Turborepo monorepo that connects three groups of users — engineering candidates, hiring companies, and Teros internal staff — through a single shared backend.

platform/
├── apps/
│ ├── api/ NestJS — single backend, RBAC enforced per request
│ ├── pool/ Next.js — candidate-facing app
│ ├── ops/ Next.js — internal app (companies + Teros staff)
│ └── debug/ Next.js — internal diagnostic tools
├── packages/
│ ├── database/ Prisma schema, migrations, generated client
│ ├── auth-config/ Shared WorkOS / route-protection helpers
│ ├── api-types/ Cross-app DTO / response types
│ ├── candidate-fields/ Shared candidate field metadata
│ ├── llm/ Shared LLM provider wiring
│ ├── ui/ Shared shadcn/ui components
│ ├── eslint-config/ Shared ESLint config
│ └── typescript-config/ Shared tsconfig bases
└── apps/docs/ ← you are here
  • apps/pool — Candidates sign up, complete onboarding, edit their profile, browse open positions, apply, and track applications.
  • apps/ops — Company admins and members manage their hiring pipeline; Teros staff operate the platform with elevated privileges (cross-company access, candidate management, invoicing, audit).
  • apps/api — A single NestJS backend serving both frontends. All authorization decisions are enforced here at the request boundary.
┌──────────────┐ ┌──────────────┐
│ Pool (Next) │ │ Ops (Next) │
└──────┬───────┘ └──────┬───────┘
│ │
│ WorkOS AuthKit JWT │
▼ ▼
┌─────────────────────────────┐
│ apps/api (NestJS) │
│ WorkOSGuard → RolesGuard │
│ → Controller → Service │
└─────────────┬───────────────┘
┌────────────┐
│ Postgres │
│ (Prisma) │
└────────────┘
  1. The frontend obtains a WorkOS-issued JWT via AuthKit.
  2. Every protected API call carries that token in Authorization: Bearer ....
  3. WorkOSGuard verifies the token and decorates request.auth with { sub, orgId, roles, ... }.
  4. RolesGuard reads the controller’s @Roles(...) metadata and rejects requests without the required role.
  5. Controllers stay thin — they only do routing, DTO validation, and response shaping. Business logic lives in services.
  6. Services own the data plane and reach Postgres through the generated Prisma client in @repo/database.
  • Identity & roles live in WorkOS — no local password / signup flow.
  • A local WorkOsUser record is synced on user.created / user.updated webhooks for relational integrity with Prisma.
  • Organization membership is mirrored from WorkOS, not invented by the platform.
  • packages/database is the single source of truth for schema, migrations, and generated client.
  • Schema changes always go through the migration loop (see Migrations).
  • The frontends import generated types from @repo/database, not from runtime API responses.
  • The end-to-end platform shape (this page).
  • The narrative of who can do what (Roles & Permissions).
  • A code-derived Permissions Matrix of every API route, refreshed at every build.
  • App-by-app deep dives (API, Pool, Ops).
  • The database shape and migration loop.
  • A short Drift control page that explains how the matrix stays honest.