warmbox/docs/12-architecture.md

158 lines
4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# System Architecture
## Deployment model (hybrid)
**Phase 12:** Self-hosted single-tenant (FillCare) with web UI
**Phase 3+:** Multi-tenant SaaS on shared infrastructure
Design all entities with optional `workspaceId` from day one.
## High-level architecture
```mermaid
flowchart TB
subgraph client [Client Layer]
WebUI[Web Dashboard]
API_Consumers[API / CLI]
end
subgraph app [Application Layer]
API[Express API]
Auth[Auth Middleware]
CampaignSvc[Campaign Service]
RecipeSvc[Recipe Engine]
StatsSvc[Statistics Service]
ContentSvc[AI Content Service]
end
subgraph workers [Worker Layer]
Scheduler[Cron Scheduler]
SendWorker[Send Queue Worker]
RescueWorker[Rescuer Worker]
StatsWorker[Stats Rollup Worker]
end
subgraph connectors [Connectors]
SMTP[nodemailer]
IMAP[imapflow]
AI[OpenRouter]
end
subgraph data [Data Layer]
DB[(SQLite → Postgres)]
Queue[(Job Queue)]
end
WebUI --> API
API_Consumers --> API
API --> Auth
API --> CampaignSvc
API --> StatsSvc
Scheduler --> SendWorker
Scheduler --> RescueWorker
SendWorker --> SMTP
SendWorker --> ContentSvc
ContentSvc --> AI
RescueWorker --> IMAP
RescueWorker --> ContentSvc
workers --> DB
API --> DB
SendWorker --> Queue
```
## Component responsibilities
| Component | Responsibility |
|-----------|----------------|
| **API** | CRUD mailboxes, campaigns, settings; stats queries |
| **Campaign Service** | Lifecycle: draft → active → paused → completed |
| **Recipe Engine** | Compute `DailySchedule` from recipe params |
| **Dispatcher / Send Worker** | Enqueue sends with jitter; role-aware pairing |
| **Rescuer Worker** | IMAP spam scan, rescue, reply sampling |
| **AI Content Service** | Generate + validate email bodies |
| **Stats Service** | Aggregations, rollups, on-track calculation |
| **Scheduler** | Cron triggers; reload on settings change |
## Data store evolution
| Phase | Database | Queue |
|-------|----------|-------|
| MVP (now) | SQLite | In-process cron |
| Phase 2 | SQLite | SQLite-backed queue or BullMQ |
| SaaS | PostgreSQL | Redis + BullMQ |
Use Prisma driver adapters; swap datasource URL for Postgres.
## Multi-tenant (future)
```mermaid
flowchart LR
subgraph tenantA [Workspace A]
A1[Primary]
A2[Satellites]
end
subgraph tenantB [Workspace B]
B1[Primary]
B2[Satellites]
end
API --> tenantA
API --> tenantB
```
- Row-level isolation via `workspaceId`
- JWT auth with workspace scope
- Encrypted credentials per workspace key (KMS in SaaS)
## Frontend architecture (recommended)
| Layer | Tech options |
|-------|----------------|
| Framework | Next.js or Vite + React |
| UI | shadcn/ui + Tailwind |
| Data | TanStack Query |
| Charts | Recharts |
| Auth | Clerk / Auth.js (SaaS) |
Serve as separate app or static build proxied by Express.
## Observability
| Concern | Tool |
|---------|------|
| Logs | Pino (existing) |
| Errors | Sentry |
| Metrics | Prometheus / Grafana (SaaS) |
| Job tracing | Correlation ID per send |
## Security boundaries
- Credentials encrypted at rest (AES-256-GCM)
- API key (self-hosted) → JWT (SaaS)
- No plaintext passwords in logs
- IMAP/SMTP connections TLS-only
## Integration points (external)
| System | Integration | Phase |
|--------|-------------|-------|
| Instantly / Smartlead | Read-only: pause warmup when they send | 3 |
| Google Postmaster | Pull domain stats | 3 |
| Webhooks | Campaign events | 2 |
| Stripe | Billing per primary | SaaS |
## Directory structure (target)
```
warmbox/
├── apps/
│ ├── api/ # Express (current src/)
│ └── web/ # Dashboard
├── packages/
│ ├── database/ # Prisma schema
│ ├── recipe-engine/
│ └── content-validator/
├── docs/
└── prisma/
```
Monorepo optional; single package acceptable through phase 2.