Skip to content

Backend overview

Audience: backend
Status: specced
Owns: backend
Depends on: Domain overview, Domain entities, API overview, Backend stack ADR, Data model, Workflow abstraction

Describe architecture with domain names, not invented DTOs. Stack: Express + TypeScript + Prisma + PostgreSQL + Redis + RabbitMQ/outbox + gRPC — see Backend stack ADR and Coding standards.

Concern Owner context
Application lifecycle, competency, evidence, interview, certification path CAP
Assessor, Centre, AwardingBody, Trade, Unit, candidate onboarding CAP
JWT issuance, shared auth, identity verification, notifications, payment, storage Orchestrator
Course catalogue / recommendations fulfilment LMS (CAP calls over gRPC)

CAP consumes Orchestrator JWT (JWKS); provisions cap_users from user.created and anonymizes on user.deleted — see Data model.

flowchart TB
Orch[Orchestrator Auth Notify Pay ID Storage]
Org[Assessor / Centre / AwardingBody]
Cat[Trade and Unit]
Onb[Candidate onboarding]
App[Application E2E + workflow engine]
Orch --> Onb
Orch --> App
Org --> App
Cat --> App
Onb --> App

The Application aggregate is the process spine:

Transitions (e.g. DRAFTCENTRE_REVIEW) must enforce identity verified, concurrent-application rules, and payment before facilitator.

Adapter Purpose Notes
Orchestrator auth Validate JWT; clients hit Orchestrator for register/login Shared across apps
Identity NIN verify via Orchestrator gRPC/events POL-04 vendor still open
Payment Candidate pays via CAP; OL processes CAP prices + POST …/pay; unlocks on payment.completedPayment architecture
Storage Evidence uploads via OL signed URLs Not Cloudinary SDK in CAP
LMS gRPC Course recommendations On GAP_TRAINING / gap outcomes
Notifications Email / in-app Via Orchestrator (events)

Folders: Authentication & Notification live on OL collections (incl. channel preferences, change-password, delete-account); CAP broken down per persona with shared Me / profile / deletion-eligibility and Onboarding GET/PATCH/submit. HTTP shapes: API overview and openapi/cap.yaml.

Product module Domain focus
Auth User credentials / session via Orchestrator
Onboarding Candidate profile after auth
Identity Identity on User; gate on Application submit
Assessors Assessor pool + centre assignment
Centres Centre CRUD
Awarding bodies AwardingBody CRUD
Trades Trade, Unit (NOS)
Payment Payment before EVIDENCE facilitation
Recommendations Recommendation + LMS integration

HTTP shapes: API overview and openapi/cap.yaml. Do not treat UX screen lists as the API. Events: Event catalog.

CAP ships a Laravel-style CLI under src/console/ (compiled to dist/console/cli.js). Use it for deploy-time backfills and manual VPS repairs — not for HTTP boot.

Entry Purpose
pnpm console … Local dev (tsx src/console/cli.ts)
node dist/console/cli.js --deploy Runs merged deploy list on activate (after migrate, before seed)

Current command: repair:organisation-centres — provisions Centre + founder SUPER_ADMIN for completed organisation onboarding rows missing staff. Shares logic with live org submit in onboarding service.

Full runbook: Console commands. Monorepo: apps/cap/src/console/, infra/deploy/activate.sh.