Overview
The Primebrick Backend (primebrick-api) is the central API server for
Primebrick v3. It exposes the REST API consumed by the frontend, manages
the PostgreSQL database, integrates with Casdoor for identity and
authentication, and acts as the service registry for microservices
connected via NATS.
Responsibilities
| Area | What it does |
|---|---|
| REST API | Express-based HTTP server on port 3001 serving all Primebrick endpoints |
| Database | PostgreSQL with a patch-based migration system (db:migrate) |
| Authentication | Casdoor IDP integration, JWT/OIDC verification, API keys, passkeys |
| RBAC | Wildcard-based permission system with role mappings and admin bypass |
| Service registry | Subscribes to microservice lifecycle events over NATS |
| MCP Server | Model Context Protocol server for AI agent integration |
| Organizations | Multi-tenant organization management with user invitations |
Architecture
Modules
| Module | Description |
|---|---|
| auth | Casdoor integration, JWT/OIDC verification, user profiles, passkeys, organizations, role mappings, password policy |
| customers | Customer entity CRUD, audit trail, bulk operations, duplicate/restore |
| mcp | Model Context Protocol server exposing Primebrick tools to AI agents |
| proxy | Reverse proxy to registered microservices via NATS |
| system | System configuration, module registry, health checks, version info |
Authentication flow
The backend integrates with Casdoor as the identity provider (IDP). The authentication flow is:
- The frontend redirects to Casdoor for login (OIDC authorization code flow)
- Casdoor returns a JWT access token
- The frontend sends the JWT in the
Authorization: Bearerheader - The backend's auth middleware verifies the JWT against Casdoor's JWKS
- The RBAC middleware checks the user's permissions against the required route permission using wildcard pattern matching
RBAC permission system
Permissions follow the pattern module.action.granularity:
customer.read.all— list all customerscustomer.read.single— read a single customercustomer.create.bulk— bulk create customerscustomer.*— wildcard matching all customer permissions*— admin bypass (matches everything)
Role mappings are stored in the role_mappings table and linked to Casdoor
roles. Users with is_admin = true bypass all permission checks.
Database
The backend uses PostgreSQL with a patch-based migration system:
pnpm run db:meta:compare— generates snapshots and patch files when entity models drift from the database schemapnpm run db:migrate— applies pending.sqlpatch files in order, using SHA-256 checksums to skip already-applied patches
Commands
| Action | Command |
|---|---|
| Install | pnpm install |
| Dev API | pnpm run dev (port 3001) |
| Build | pnpm run build |
| DB schema compare | pnpm run db:meta:compare |
| Apply DB patches | pnpm run db:migrate |
| Seed demo customers | pnpm run db:seed:customers |
| Postgres up | docker compose -f infra/docker-compose.postgres.yml up -d |
| Postgres down | docker compose -f infra/docker-compose.postgres.yml down |
Quick start
1. Start Postgres and apply migrations
Code
2. Configure Casdoor
The BE reads its IDP configuration from the config_entries table at
startup. The minimum rows required are the Casdoor endpoint, organization,
builtin client credentials, and the OIDC issuer URL. See
Authentication for the full config schema.
If you just want to explore the API without Casdoor, the /api/v1/health
endpoint is public and returns DB + IDP reachability:
Code
Code
3. Start the API
Code
4. Authenticate and call a protected endpoint
Every endpoint under /api/v1/* (except /health and the OpenAPI docs router)
requires a Bearer JWT issued by Casdoor. The login endpoint exchanges
credentials for an access token and sets access_token / refresh_token
cookies.
Code
5. Browse the OpenAPI spec
The OpenAPI JSON is served publicly (no auth) so clients can introspect the API during integration:
Code
The aggregated router (/api/v1/openapi/aggregated.json) merges the backend
spec with specs from microservices registered via NATS.
6. Error responses (RFC 7807)
Every error response is a JSON Problem Details object (RFC 7807) with a stable
internal_code and a severity field the frontend uses to pick the toast
style. Validation errors include a ZodError-shaped issues array.
Code
Code
Code
Code
See Architecture for the request-flow diagram and the HTTP layer internals, Authentication for the full auth flow, and RBAC for the permission system.
Next steps
- Architecture — module structure, request flow, and the HTTP layer internals.
- Authentication — Casdoor OIDC, JWT verification, passkeys, and the welcome flow.
- RBAC — the wildcard permission system,
rbacHandler, and role mappings. - Collaboration — optimistic locking, audit trail, and clone.