Documentation
Documentation/Core concepts

Platform overview

The technical mental model for projects, workers, orchestration, and boundaries.

architectureprojectsworkersbackend
View Markdown
On this page

BernOps is a project-scoped automation platform. A project represents one application or operational surface, and every job, run, trigger, queue, API key, variable, and external job belongs to that project boundary.

Mental model

The product has three planes:

PlaneWhat it doesPrimary code path
Control planeBrowser UI for workspaces, projects, jobs, queues, variables, runs, and keys.frontend
Orchestration planeGo REST API, auth checks, run dispatch, WebSocket worker gateway, database writes.backend
Execution planeNode worker that receives run payloads and starts Playwright.worker

The frontend is a static Next application. It does not own API routes. Browser code calls the Go backend through lib/api-client.ts, and authentication is handled by Supabase PKCE in the browser.

Resource hierarchy

The hierarchy is intentionally narrow:

  1. Workspaces contain projects.
  2. Projects contain jobs, variables, queues, triggers, runs, jobs, and API keys.
  3. API keys are project-scoped and cannot cross into another project.
  4. Worker execution is assigned per run, not per project.

This means most automation code only needs three identifiers: a project ID, the resource ID it wants to operate on, and a bearer token with the required scope.

Run execution path

01

Run request

A user, API key, trigger, or saved job starts an execution.

02

Dispatch

The backend records the run and claims one connected worker.

03

Temp workspace

The worker writes test files and a generated Playwright config.

04

Telemetry

Logs, steps, traces, screenshots, and results stream back to BernOps.

When a run starts, the backend creates a test_executions row, resolves project runtime variables, picks an available worker, and sends a run_tests WebSocket message. The worker writes the provided Playwright files into a temporary directory, generates a Playwright config, and starts npx playwright test.

Results are streamed back as structured logs and steps. The backend persists them so the run detail page can show timeline events, console output, network data, screenshots, attachments, and final status.

Auth principals

BernOps recognizes two caller types:

PrincipalBest forNotes
User JWTBrowser-authenticated management actions.Inherits the signed-in user's workspace/project role.
Project API keyCI, external runners, queue workers, saved-job execution, ingest.Bound to one project and limited by scopes.

Use a user JWT for admin actions like creating projects and managing keys. Use a project API key when a machine or external system needs repeatable access.

Technical boundaries

Static frontend contract

The frontend is deployed as a static export. Do not expect frontend routes to run server code, read cookies on the server, or expose app/api handlers. Runtime behavior should go through the Go backend.

The backend routing source of truth is backend/main.go. Worker protocol payloads are mirrored between backend/protocol and worker/src/protocol/types.ts; when fields change, both sides must stay in sync.

Where to go next