Hexagonal architecture
The platform follows strict hexagonal architecture (ports and adapters). This is what keeps the domain testable and lets you extend the platform without forking it.
┌─────────────────────────────────────────┐│ User Interfaces ││ (CLI, Web UI, REST API) │└──────────────┬──────────────────────────┘ │┌──────────────▼──────────────────────────┐│ Application Layer ││ (Use cases, services, orchestration) │└──────────────┬──────────────────────────┘ │┌──────────────▼──────────────────────────┐│ Domain Layer ││ (Entities, Ports / Interfaces) │└──────────────┬──────────────────────────┘ │┌──────────────▼──────────────────────────┐│ Infrastructure Layer ││ (Adapters: DB, API, file system) │└─────────────────────────────────────────┘Where things live
- Ports (interfaces) live in
packages/platform-domain/**/ports/. The domain package is infrastructure-free — nodrizzle-orm,pg-boss,fs, orhttpimports. - Adapters (concrete implementations) live in
apps/api/**/adapters/.
For example, the job runtime defines IJobRepository, IJobRunner, and IWorkflowStep as ports; DrizzleJobRepository, PgBossJobRunner, and the concrete steps are adapters.
The extension surface
The ports are the extension surface. You extend the platform by implementing one:
| Implement… | …to add |
|---|---|
IWorkflowStep / BaseWorkflowStep | a new pipeline step |
IExportTarget | a new export destination |
ISourceReader | a new ingestion source |
ILlmClient | a new LLM provider |
See Extend the platform for a worked example.