# Infrastructure

## Infrastructure Overview

Primebrick runs as a set of independent services connected via HTTP and NATS™ messaging. Everything is Dockerized for local development and deployable to any cloud via Terraform.

<Mermaid chart={`graph TB
    subgraph Clients["External Clients"]
        Browser["Browser / Admin UI"]
        API["API Clients (SDK, curl)"]
    end

    subgraph Auth["Identity Provider"]
        Casdoor["Casdoor<br/>OAuth2 / OIDC<br/>port 8000"]
    end

    subgraph FE["Frontend"]
        SvelteKit["SvelteKit Admin UI<br/>port 5173"]
    end

    subgraph BE["Backend (System Brick)"]
        Express["Express API<br/>port 3001<br/>/api/v1/"]
        Registry["Service Registry"]
        Proxy["Round-Robin Proxy<br/>/ws/:serviceCode"]
        AuthMod["Auth + RBAC Module"]
    end

    subgraph Msg["Messaging"]
        NATS["NATS<br/>port 4222<br/>monitoring: 8222"]
    end

    subgraph MS["Microservices (Docker)"]
        EmailSender["EmailSender<br/>port: dynamic"]
        MS2["Microservice B<br/>port: dynamic"]
        MS3["Microservice C<br/>port: dynamic"]
    end

    subgraph Data["Data Layer"]
        Postgres["PostgreSQL<br/>port 5432<br/>+ pgvector (planned)"]
        Redis["Redis<br/>port 6379<br/>Cache + Presence + WebAuthn"]
    end

    subgraph Libs["Shared Libraries"]
        SDK["@primebrick/sdk<br/>Service registration<br/>NATS client<br/>HTTP server<br/>Health checks"]
        DAL["@primebrick/dal-pg<br/>Repository pattern<br/>Pool management<br/>Type-safe queries"]
    end

    Browser -->|HTTP| SvelteKit
    API -->|HTTP /api/v1/| Express
    SvelteKit -->|HTTP /api/v1/| Express

    Express -->|OAuth2 / OIDC| Casdoor
    AuthMod -->|Validate JWT| Casdoor

    Express -->|SQL| Postgres
    EmailSender -->|SQL via DAL| Postgres
    MS2 -->|SQL via DAL| Postgres

    Express <-->|Redis| Redis
    EmailSender <-->|Redis cache| Redis

    Express <-->|NATS subscribe| NATS
    EmailSender <-->|NATS publish| NATS
    MS2 <-->|NATS| NATS

    EmailSender -->|register/heartbeat| NATS
    NATS -->|service events| Registry
    Proxy -->|HTTP proxy| EmailSender
    Proxy -->|HTTP proxy| MS2

    SDK -.->|used by| EmailSender
    SDK -.->|used by| MS2
    SDK -.->|used by| MS3
    DAL -.->|used by| Express
    DAL -.->|used by| EmailSender
    DAL -.->|used by| MS2
`} />

## Components

### External Clients

| Component | Protocol | Description |
|-----------|----------|-------------|
| Browser | HTTP | Admin UI accessed via SvelteKit™ frontend |
| API Clients | HTTP | SDK consumers, curl, integrations calling `/api/v1/` |

### Identity Provider — Casdoor™

Casdoor™ provides OAuth2 / OIDC authentication. The backend validates JWT tokens issued by Casdoor™ and maps IDP roles to internal RBAC permissions.

- **Port**: `8000`
- **Protocol**: HTTP (OAuth2 / OIDC)
- **Role**: Issues JWT tokens, manages users and roles

### Frontend — SvelteKit™

The admin frontend is a SvelteKit™ application. It communicates **only** with the backend API — never directly with microservices.

- **Port**: `5173`
- **Protocol**: HTTP
- **Talks to**: Backend (`/api/v1/`)

### Backend — Express API (System Brick)

The central backend is the "SYSTEM" virtual brick. It handles authentication, RBAC, service registry, and proxies requests to microservices.

- **Port**: `3001`
- **Base path**: `/api/v1/`
- **Modules**: Auth, RBAC, Service Registry, Proxy, OpenAPI
- **Talks to**: Casdoor™ (OAuth), PostgreSQL® (via DAL), NATS™ (subscribe), Microservices (HTTP proxy)

### Messaging — NATS™

NATS™ is the messaging backbone for inter-service communication. Microservices publish lifecycle events (register, heartbeat, unregister) and the backend subscribes to update the service registry.

- **Port**: `4222` (client connections)
- **Monitoring**: `8222`
- **Protocol**: NATS protocol
- **Patterns**: Pub/Sub for lifecycle events, Request/Reply for inter-service calls

### Microservices

Each microservice is an independent, Dockerized service with its own lifecycle, database schema, and port.

- **Port**: Dynamic (loaded from config)
- **Protocol**: HTTP for direct calls, NATS™ for lifecycle events
- **Self-registration**: Via `@primebrick/sdk` `ServiceRegistrar`
- **OpenAPI spec**: Served at `/api/v1/openapi.json`
- **Aggregated spec**: Backend merges all online specs at `/api/v1/openapi/aggregated.json` (microservice paths prefixed with `/ws/:serviceCode`)
- **Talks to**: PostgreSQL® (via DAL), NATS™ (via SDK), Backend (via proxy)

### Data Layer — PostgreSQL® + pgvector

PostgreSQL® is the single data store for all services. pgvector extension enables vector similarity search for AI features.

- **Port**: `5432`
- **Protocol**: PostgreSQL® wire protocol
- **Extensions**: pgvector
- **Access**: All services connect via `@primebrick/dal-pg`

### Cache & Presence — Redis™

Redis™ is a **mandatory** infrastructure component. It is not optional or best-effort — the `/health` endpoint returns 503 when Redis is down, and Redis-dependent features hard-fail with `REDIS_UNAVAILABLE` (503).

- **Port**: `6379`
- **Protocol**: RESP (Redis protocol)
- **Used by**: Backend (cache, presence, WebAuthn session relay, keyspace listener), Microservices (entity cache via `@Cached()` decorator)
- **Mandatory for**:
  - **WebAuthn passkey signin** — session cookie relay between begin/finish calls (hard-fail without Redis)
  - **Entity caching** — `@Cached()` decorator + `withCache()` wrapper (DB-only fallback, but performance degradation at scale)
  - **Real-time presence** — collaboration SSE presence store (presence disabled without Redis)
  - **Cache invalidation** — cross-pod config/role-mapping/api-key cache sharing (stale data without Redis)
- **Health check**: `/health` includes `redis: { ok, version }` — actual `PING` command on every probe
- **Startup**: BE retries Redis connection every 5s if unreachable (same pattern as DB/role mappings)

### Shared Libraries

#### @primebrick/sdk

The SDK is the shared toolkit used by every microservice. It provides:

- `ServiceRegistrar` — registration + heartbeats via NATS™
- `NatsClient` — NATS™ connection management
- `createHttpServer` — HTTP server scaffolding
- `HealthCheck` — liveness/readiness endpoints
- `ConfigLoader` — config loading from database
- `requireEnv` — environment variable validation
- `GracefulShutdown` — cleanup on termination

#### @primebrick/dal-pg

The DAL is the shared data access library. It provides:

- `Dal` gateway — manages `pg.Pool`, connection lifecycle
- `Repository` — type-safe CRUD from TypeScript® entity metadata
- Type parsers — `INT8` → `bigint`, `NUMERIC` → `number`/`string`
- Per-connection settings — `search_path`, `statement_timeout`, `application_name`
- Transaction support — `dal.withClient(fn, options?)`

## Data Flow

### Request flow (client → database)

<Mermaid chart={`sequenceDiagram
    participant C as Client
    participant FE as SvelteKit
    participant BE as Backend
    participant Casdoor
    participant Proxy as BE Proxy
    participant MS as Microservice
    participant DB as PostgreSQL

    C->>FE: HTTP request
    FE->>BE: HTTP /api/v1/... (Bearer JWT)
    BE->>Casdoor: Validate JWT
    Casdoor-->>BE: Valid + roles
    BE->>BE: RBAC permission check

    alt Backend endpoint
        BE->>DB: SQL via DAL
        DB-->>BE: Result set
        BE-->>FE: JSON response
        FE-->>C: HTML/JSON
    else Microservice endpoint
        BE->>Proxy: /ws/:serviceCode/...
        Proxy->>MS: HTTP forward (round-robin)
        MS->>DB: SQL via DAL
        DB-->>MS: Result set
        MS-->>Proxy: JSON response
        Proxy-->>BE: JSON response
        BE-->>FE: JSON response
        FE-->>C: HTML/JSON
    end
`} />

### Service lifecycle (startup → heartbeat → shutdown)

<Mermaid chart={`sequenceDiagram
    participant MS as Microservice
    participant SDK as @primebrick/sdk
    participant NATS
    participant BE as Backend
    participant DB as PostgreSQL

    MS->>SDK: Create ServiceRegistrar
    SDK->>NATS: Connect
    SDK->>NATS: Publish "service.register"
    NATS->>BE: Deliver register event
    BE->>DB: INSERT service_registry
    BE-->>BE: Service is online

    loop Every 30s
        SDK->>NATS: Publish "service.heartbeat"
        NATS->>BE: Deliver heartbeat
        BE->>DB: UPDATE last_heartbeat_at
    end

    MS->>SDK: GracefulShutdown
    SDK->>NATS: Publish "service.unregister"
    NATS->>BE: Deliver unregister
    BE->>DB: UPDATE status = offline
`} />

## Deployment

### Docker® (local development)

```yaml
# docker-compose.postgres.yml
services:
  postgres:
    image: postgres:18-bookworm
    ports: ["5432:5432"]
  casdoor:
    image: casbin/casdoor:3.75.0
    ports: ["8000:8000"]
  nats:
    image: nats:latest  # JetStream enabled
    ports: ["4222:4222", "8222:8222"]
  redis:
    image: redis:8-alpine
    ports: ["6379:6379"]
```

### Terraform (production)

Each microservice includes Terraform templates for cloud deployment:

- `terraform/main.tf` — resource definitions
- `terraform/variables.tf` — configurable parameters
- `terraform/scripts/deploy.{ps1,sh}` — cross-platform deploy scripts
- `terraform/scripts/find-available-port.{ps1,sh}` — dynamic port allocation

## Ports Summary

| Component | Default Port | Protocol |
|-----------|-------------|----------|
| Frontend (SvelteKit™) | 5173 | HTTP |
| Backend (Express) | 3001 | HTTP |
| Casdoor™ (OAuth) | 8000 | HTTP |
| PostgreSQL® | 5432 | PostgreSQL® |
| NATS™ (client) | 4222 | NATS™ |
| NATS™ (monitoring) | 8222 | HTTP |
| Microservices | Dynamic | HTTP |

## Next steps

- [Architecture](./architecture) — high-level architectural overview
- [Quick Start](./quick-start) — get running locally
- [Microservice Standard](../api/microservice-standard) — how to build a compliant microservice
