PrimeBrickPrimeBrick
  • Docs
  • Contact
  • MIT License
  • Documentation
  • MCP Server
  • API Catalog
  • Services
  • Libraries
PrimeBrickPrimeBrick

© 2026 PrimeBrick. MIT License. v3.11.2

github
Backend
    Roles and PermissionsWorking Together on the Same RecordManaging ModulesSigning In and MFA
    Generated
    Manual
    Developer Guide
      OverviewArchitectureAPI ConventionsEntity metadata contractEntity CRUD PipelineEntities and CRUD conventionsModule Navigation MetadataService RegistryMCP GatewayThe Service ProxyRotating Secrets EngineTranslationsAuthenticationRBACEnvironment ConfigurationCollaboration & Visual Merge
Frontend
Microservices
powered by Zudoku
Developer Guide

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

AreaWhat it does
REST APIExpress-based HTTP server on port 3001 serving all Primebrick endpoints
DatabasePostgreSQL with a patch-based migration system (db:migrate)
AuthenticationCasdoor IDP integration, JWT/OIDC verification, API keys, passkeys
RBACWildcard-based permission system with role mappings and admin bypass
Service registrySubscribes to microservice lifecycle events over NATS
MCP ServerModel Context Protocol server for AI agent integration
OrganizationsMulti-tenant organization management with user invitations

Architecture

Modules

ModuleDescription
authCasdoor integration, JWT/OIDC verification, user profiles, passkeys, organizations, role mappings, password policy
customersCustomer entity CRUD, audit trail, bulk operations, duplicate/restore
mcpModel Context Protocol server exposing Primebrick tools to AI agents
proxyReverse proxy to registered microservices via NATS
systemSystem configuration, module registry, health checks, version info

Authentication flow

The backend integrates with Casdoor as the identity provider (IDP). The authentication flow is:

  1. The frontend redirects to Casdoor for login (OIDC authorization code flow)
  2. Casdoor returns a JWT access token
  3. The frontend sends the JWT in the Authorization: Bearer header
  4. The backend's auth middleware verifies the JWT against Casdoor's JWKS
  5. 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 customers
  • customer.read.single — read a single customer
  • customer.create.bulk — bulk create customers
  • customer.* — 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 schema
  • pnpm run db:migrate — applies pending .sql patch files in order, using SHA-256 checksums to skip already-applied patches

Commands

ActionCommand
Installpnpm install
Dev APIpnpm run dev (port 3001)
Buildpnpm run build
DB schema comparepnpm run db:meta:compare
Apply DB patchespnpm run db:migrate
Seed demo customerspnpm run db:seed:customers
Postgres updocker compose -f infra/docker-compose.postgres.yml up -d
Postgres downdocker compose -f infra/docker-compose.postgres.yml down

Quick start

1. Start Postgres and apply migrations

TerminalCode
docker compose -f infra/docker-compose.postgres.yml up -d pnpm install pnpm run db:migrate # applies pending .sql patches in order pnpm run db:seed:customers # optional: load demo customers

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:

TerminalCode
curl http://localhost:3001/api/v1/health
Code
{ "ok": true, "service": "primebrick-api", "version": "0.0.0", "db": { "ok": true }, "idp": { "ok": true, "type": "Casdoor", "version": "v1.x.x" } }

3. Start the API

TerminalCode
pnpm run dev # API listening on http://localhost:3001

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.

TerminalCode
# Login (Casdoor password grant) — cookies are set on the response curl -i -X POST http://localhost:3001/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"<user>","password":"<your-password>"}' # Set-Cookie: access_token=eyJhbGciOi...; Path=/; HttpOnly # Set-Cookie: refresh_token=...; Path=/; HttpOnly # Call a protected endpoint with the access token curl http://localhost:3001/api/v1/entities/customer/list \ -H "Authorization: Bearer eyJhbGciOi..."

5. Browse the OpenAPI spec

The OpenAPI JSON is served publicly (no auth) so clients can introspect the API during integration:

TerminalCode
curl http://localhost:3001/api/v1/openapi.json curl http://localhost:3001/api/v1/openapi/aggregated.json

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.

TerminalCode
# Missing Bearer token → 401 curl -i http://localhost:3001/api/v1/entities/customer/list
Code
{ "type": "/errors/unauthorized", "title": "Unauthorized", "status": 401, "detail": "Missing or invalid Authorization header", "instance": "/api/v1/entities/customer/list", "internal_code": "UNAUTHORIZED", "severity": "MEDIUM" }
TerminalCode
# Insufficient permissions → 403 with the missing permissions in extra.issues curl -i http://localhost:3001/api/v1/entities/customer/list \ -H "Authorization: Bearer <token-of-a-guest-user>"
Code
{ "type": "/errors/forbidden", "title": "Forbidden", "status": 403, "detail": "Insufficient permissions to perform this action", "instance": "/api/v1/entities/customer/list", "internal_code": "RBAC_PERMISSION_DENIED", "severity": "MEDIUM", "extra": { "issues": [{ "kind": "missing_any_of_permissions", "required": ["customer.read.all"], "missing": ["customer.read.all"], "mode": "any", "user_roles": ["guest"] }] } }

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.
Last modified on October 28, 2026
Database migrationsArchitecture
On this page
  • Responsibilities
  • Architecture
  • Modules
  • Authentication flow
  • RBAC permission system
  • Database
  • Commands
  • Quick start
    • 1. Start Postgres and apply migrations
    • 2. Configure Casdoor
    • 3. Start the API
    • 4. Authenticate and call a protected endpoint
    • 5. Browse the OpenAPI spec
    • 6. Error responses (RFC 7807)
  • Next steps
JSON
JSON
JSON