Platform overview
The technical mental model for projects, workers, orchestration, and boundaries.
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:
| Plane | What it does | Primary code path |
|---|---|---|
| Control plane | Browser UI for workspaces, projects, jobs, queues, variables, runs, and keys. | frontend |
| Orchestration plane | Go REST API, auth checks, run dispatch, WebSocket worker gateway, database writes. | backend |
| Execution plane | Node 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:
- Workspaces contain projects.
- Projects contain jobs, variables, queues, triggers, runs, jobs, and API keys.
- API keys are project-scoped and cannot cross into another project.
- 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
Run request
A user, API key, trigger, or saved job starts an execution.
Dispatch
The backend records the run and claims one connected worker.
Temp workspace
The worker writes test files and a generated Playwright config.
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:
| Principal | Best for | Notes |
|---|---|---|
| User JWT | Browser-authenticated management actions. | Inherits the signed-in user's workspace/project role. |
| Project API key | CI, 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
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
- Use Playwright Jobs to understand how jobs should be written.
- Use Runtime Variables to pass project-specific values into runs.
- Use API Keys and Scopes before giving external systems access.
- Use Efficient agent tools for version-aware discovery, compact selection, safe batch planning and readiness verification.
- Use the separate API Reference for endpoint paths, request schemas, and try-it tooling.