# Dbrij Proof Documentation

How Dbrij Proof maps a system, checks every feature against the live deployment, monitors on deploy and every day, runs suites, journeys and walkthroughs, takes CI uploads and installs the bug button.

Canonical page: https://dbrij.com/products/proof/docs

## Introduction

**Dbrij Proof** tells you whether the software you paid for, or wrote, actually works. Point it at a deployed app or a repository and it reads the code, writes down every feature it finds, then checks each one against the live deployment. After every deploy, and once a day in between, it checks again and tells you in plain words what changed.

What Proof does for a target, end to end:

- **Maps** the system: features, what kind each is, and the routes or pages where it lives.
- **Checks** every mapped endpoint against the deployed URL and gives each feature a verdict: working, failing or regressed.
- **Runs** the repository's own tests in a sandbox, plays journeys step by step, and photographs the deployed pages.
- **Reports** what changed since last time, and can hold a release until the tests pass.

Alongside that sit test cases and runs a team writes by hand, CI result uploads, and a bug button for your own app that files reports straight into triage.

API base`https://api.dbrij.com/api`

## Targets

A target is one system Proof watches. It points at one of three things:

|  |  |  |
| --- | --- | --- |
| A Hosting service | service | A service you deployed on Dbrij Hosting. Its repository is read from the service, and its live URL is where checks go. The service needs a connected repository. Deploys of this service rescan the target. |
| A Source repository | source | A Dbrij Source repository you can open. No outside grant is involved. |
| An outside repository | repo | A repository from a git host you connected to Dbrij, named owner/repo. |

You can choose a branch, and a target can belong to a company. The first scan starts on its own as soon as the target is made.

### Target settings

|  |  |  |
| --- | --- | --- |
| name | string | What the target is called. |
| baseUrl | string | Where the deployed system answers. Wins over the Hosting URL. Empty clears it back. |
| apiBasePath | string | The prefix every route sits behind ("/api/v1"). Detected unless you set it; empty clears it back to detection. |
| testCommand | string | The command a suite run executes. Empty resets it to npm test. |
| testAuth | object | The test identity journeys use: a ready token, or a login call Proof makes first. Stored on the server and never shown again. |
| allowLiveWrites | boolean | Your explicit choice to let journeys perform real writes with the test identity. |
| retestOnDeploy | boolean | After each deploy, run the suite again and bring failed test cases back for a retest. |
| gatePromotion | boolean | Hold releases until the tests pass (see Release holds and milestones). |
| shipAppId | string | Tie a Dbrij Ship app of the same company to the target. |
| paused | boolean | Stop scanning and checking on its own (see Monitoring and pausing). |

Removing a target stops watching it. Only its owner can remove it.

## The system map

A scan reads the repository without cloning it: the full file list, then the most informative files (up to 44 of them, about 9 KB of each), skipping folders such as `node_modules`, `vendor`, `dist`, `build`, `.next` and `coverage`. Routes are read out of the code itself, and Deputy, Dbrij's AI, explains what the system is and lists its features. A scan spends AI credits.

### Features

Each feature on the map has:

|  |  |  |
| --- | --- | --- |
| name, description | text | What it is, in plain words. |
| kind | api \| page \| job \| realtime \| integration \| other | What sort of thing it is. |
| entryPoints | string[] | Routes, paths or commands where it lives, such as GET /orders/:id. Up to 12. |
| confidence | high \| medium \| low | How sure the scan is that it exists as described. |
| health | untested \| working \| failing \| regressed | The verdict from the latest checks. |
| notes | text | Loose ends the scan noticed: TODOs, stubs, half built parts. |

A scan keeps up to 60 features. Each feature has a stable key, so a rescan updates the same row. A feature you edited keeps your wording across rescans, and one the latest scan no longer sees is archived rather than deleted.

### How much a scan established

|  |  |  |
| --- | --- | --- |
| full | quality | Routes were read from the code and Deputy described them. |
| ai_only | quality | Deputy described the system, but no routes could be read. |
| routes_only | quality | Real routes were read, but Deputy could not write the descriptions. |
| structure_only | quality | Neither: the map is folder names and nothing is testable. |

Anything below full is shown on the target, so a scan never looks successful when it learned nothing.

## Live checks

A check run probes every mapped endpoint at the target's deployed URL: your base URL when you set one, otherwise the Hosting service's live custom domain, otherwise its platform address. Two things are settled before any feature is judged:

- The base URL must answer. A dead host, an expired certificate or a wrong domain fails the run instead of marking every feature broken.
- The route prefix is found. Unless you set one, Proof tries none, `/api`, `/api/v1`, `/v1` and `/api/v2` against a few routes and keeps the one that answers.

Reads are probed with `GET`. Write routes are probed with their real verb but an empty, unauthenticated request, so the auth wall or the validator turns it away before anything could be written; that refusal is the evidence the route exists. Path parameters get a made up value.

HOW A CHECK ENDS

|  |  |  |
| --- | --- | --- |
| ok | 2xx, 3xx | Reachable and answering. |
| guarded | 401, 403 | Reachable, with an auth wall enforced. Counts as evidence it exists. |
| client_error | 400, 422 | The route exists and rejected the made up input. |
| missing | 404 | Nothing answers at that path. |
| error | 5xx | The feature is erroring. |
| unreachable | network | The request failed or timed out. |
| skipped | none | The entry point is not an HTTP path, so it cannot be probed. |

Only server errors, timeouts and vanished routes count against a feature. A feature that was working and is now failing is marked **regressed**. Each feature shows the last answer of every endpoint and a pass rate, the share of its probed endpoints that answered.

Each check waits up to 8 seconds. A run probes up to 12 endpoints a feature and 800 in all, and stops after 5 minutes, reporting what it got. One run at a time per target.

## Monitoring and pausing

### Scans on deploy

When a deploy of a target's Hosting service goes live, Proof rescans the target with that commit, so the map follows every push. With `retestOnDeploy` on, the repository's suite runs again (once it has run to a verdict before) and test cases that failed by hand come back for a retest.

### The daily check

Once a day Proof runs the live checks again on every target that has a URL to check and has not been checked in the last 20 hours, so a silent regression still surfaces between deploys. Scans are not repeated on this schedule, because the code has not changed.

### Updates in plain words

After a cycle Proof writes an update: what changed in the map and in the verdicts, which features regressed and which recovered, the working and failing counts, the suite result when a suite has run, and the commit that triggered it. Each update notes whether a person, a deploy or the schedule started it. Updates older than 180 days are removed.

### Pausing

Pause a target to stop it scanning on deploys and checking on the daily schedule. Everything you start by hand still works while it is paused: pausing means stop doing this on every push, not read only. The target records when it was paused.

## Suite runs

A suite run executes the repository's own tests. The repository is cloned inside a sandboxed job on the Hosting cluster, never on Dbrij's own servers: nothing can connect into it, and its network is fenced like a Hosting build. The command is `npm test` unless you set another, in the target or for one run, on a `node:22-bookworm` image, with 15 minutes to finish.

|  |  |  |
| --- | --- | --- |
| passed | status | The tests ran and passed. |
| failed | status | The tests ran and some failed. |
| error | status | They could not run: the clone, the install or the test script failed. Said plainly. |

Proof keeps the end of the output, the passed and failed counts when the runner reports them, each test it can read from the output (failures first), and Deputy's plain reading of what failed and where to look. When the target's space uses test cases, the results also land there as an automated run.

Suite runs need a target whose repository comes from a connected outside git host. One suite run at a time per target.

## Journeys

A journey is a guided story a person who does not read code can press play on: a few HTTP calls in order, each explained in plain words. Deputy writes journeys from the map in the background, and you can write or edit your own; an edited journey becomes yours.

A STEP

|  |  |  |
| --- | --- | --- |
| title, explanation | text | What the step is, and what a pass proves. |
| method, path | string | The call. Paths may carry {{variables}} saved by earlier steps, such as /orders/{{orderId}}. |
| body | string | JSON for write steps in live mode, also with {{variables}}. |
| auth | boolean | Send the target’s test identity with this step. |
| saveAs | list | Values to keep from the answer for later steps, each a name and a dot path. |

### Simulated or live

A journey plays **simulated** by default: write steps only prove the route exists, the same way live checks do. It plays **live**, really performing writes, only when the target holds a test identity *and* you switched on live writes. Use a test account, never a real customer's.

Up to 12 journeys a target and 20 steps a journey. Each step waits up to 12 seconds.

## Walkthroughs

A walkthrough opens the deployed app in a sandboxed browser on the Hosting cluster and photographs its pages, so people who do not read endpoints see the product itself. Pages come from the map (features of the page kind and the pages journeys visit), up to 8 a walkthrough, with 7 minutes to finish. Screenshots go straight from the sandbox to storage.

A system with no pages on its map, such as an API only service, has nothing to photograph; its journeys and checks cover it instead.

## Release holds and milestones

### Hold releases until the tests pass

With `gatePromotion` on, promoting the target's Hosting service to production waits for a passing test run and no open critical bugs. Tie a Dbrij Ship app to the target and its production releases wait the same way while the hold is on. The hold needs the target to be tied to a Hosting service or a Ship app.

### Evidence on milestones

Link a feature, or a whole target, to a milestone in a Dbrij project. The milestone then shows each linked feature's live verdict, a count of working, failing and untested features, a short verdict such as how many linked features are verified working, and the latest update. Proof never moves the board on its own; it informs the person who does.

You can also turn the map into work: create a project from the features, one milestone per feature and, if you like, one task per endpoint, each linked back to its feature. Or add the milestones to a project that already exists.

## Test cases and CI uploads

Test cases are the checks a team writes by hand: suites of cases, each numbered `TC-1`, `TC-2` and so on, with steps. A run snapshots the cases you pick, and each result is untested, passed, failed, blocked, retest or skipped. A failed result can file a bug, a company task of kind bug, filled in from the case and the run. Deputy can draft cases from a brief for you to review (it spends AI credits), and checks new bugs for ones that describe the same problem.

### Upload results from CI

Make a CI token in Proof, under Test cases, Automation. It starts `dbpci_`, is shown once, writes into one space, and stops working when the person who made it leaves the company. Send your test runner's JUnit XML report, or JSON, and it becomes a closed run.

Upload a JUnit report

```
curl -X POST "https://api.dbrij.com/api/v1/proof/tests/ci/results?suite=Backend&environment=staging&commit=$GIT_SHA" \
  -H "Authorization: Bearer $DBRIJ_PROOF_CI_TOKEN" \
  -H "Content-Type: application/xml" \
  --data-binary @junit.xml
```

Or JSON

```
{ "tests": [
  { "name": "checkout charges the card", "suite": "payments", "status": "passed", "durationMs": 412 },
  { "name": "TC-12 refunds a cancelled order", "status": "failed", "message": "expected 200, got 500" }
] }
```

QUERY

|  |  |  |
| --- | --- | --- |
| suite | string | The suite new cases go into. |
| run | string | A name for the run. |
| environment | string | Where the tests ran. |
| build, commit | string | What was tested. The run is named with the build, or the short commit. |
| target | string | A Proof target id in the same space, to tie the run to it. |
| create | "0" \| "false" | Creating cases for unmatched tests is on; pass 0 or false to turn it off. |

Each test finds its case: the case it matched before, a `TC-12` written in its name or suite, or a case titled exactly like it. The rest become new cases while creating is on and there is room. JSON statuses read as passed (`pass`, `passed`, `ok`, `success`), failed (`fail`, `failed`, `error`, `broken`, `timedout`) or skipped (`skip`, `skipped`, `pending`, `todo`, `disabled`, `ignored`). A test with any other status is left out.

Response

```
{
  "success": true,
  "data": {
    "runId": "r1a2…",
    "url": "…/proof/tests/runs/r1a2…",
    "totals": { "total": 120, "untested": 0, "passed": 118, "failed": 2, "blocked": 0, "retest": 0, "skipped": 0 },
    "matched": 114,
    "created": 6,
    "ignored": 0
  }
}
```

Up to 5,000 tests and 10 MB an upload, 60 uploads a minute. A `401` means the token is missing or no longer valid.

## The bug button

One line on your own site adds a Report a bug button. Each report arrives in your company's bug triage as a task of kind bug, in the backlog, with the reporter's words, the page, the browser, the errors and failed requests the page hit, a screenshot when they attach one, and the Dbrij Glass replay of the visit when Glass runs on the page.

### Install

In Proof, open Test cases, Automation, and make a bug button. Buttons belong to a company, and only its owner or an admin can make or change them. Paste the line it gives you into your app's pages:

Your app's HTML

```
<script src="https://dbrij.com/proof-capture.js" data-key="pc_..." async></script>
```

OPTIONS ON THE TAG

|  |  |  |
| --- | --- | --- |
| data-key* | string | The button’s key, starting pc_. Without a valid one the script logs a warning and does nothing. |
| data-build | string | Your app’s version, recorded on each report (up to 120 characters). |
| data-label | string | The floating button’s text. Defaults to Report a bug. |
| data-position | "left" | Put the floating button bottom left instead of bottom right. |
| data-button | "off" | No floating button: open the form yourself with window.dbrijBugs.open(). |

Your own button

```
// Open the form, optionally filled in
window.dbrijBugs.open({ title: 'The pay button does nothing', steps: 'Added two items, opened the cart, pressed Pay' });

// Or send a report from your own form; resolves when it is filed
await window.dbrijBugs.report({ title: 'Export failed', steps: '…', expected: '…', impact: 'blocks' });
```

The script draws its form in a shadow root, so your styles and its styles never mix. It runs once per page however many times it is included.

### What it collects

From the moment it loads, the script keeps a short trail, in the page only, until someone reports:

- The last 20 console errors, uncaught errors and unhandled promise rejections, each up to 300 characters.
- The last 20 failed requests (status 400 or above, or no answer): method, address without its query string, status and time taken. Never a request or response body. The script's own calls to Dbrij are left out.

### What a report sends

|  |  |  |
| --- | --- | --- |
| title* | string | What went wrong, up to 200 characters. |
| steps, expected | string | What they were doing, and what they expected. Up to 4,000 characters each. |
| impact | blocks \| annoying \| minor | It stops me, It gets in my way (the default), Small thing. Becomes the bug’s severity: high, medium, low. |
| email | string | Only when the reporter chose to leave it, to hear back. |
| screenshot | image | Optional PNG, JPEG or WebP the reporter attached, up to 4 MB. |
| page | object | The page address, title and referrer. |
| env | object | Browser, language, window and screen size, time zone. |
| console, network | lists | The trail above. |
| build | string | From data-build. |
| glass | object | The Glass visit, when Glass runs on the page. A replay link is added only for a Glass site of the same company. |

### Which sites may send

Give a button the host names it serves (up to 20). A name also covers its subdomains, and a leading `*.` is accepted. A button with no host names accepts reports from any site. Switching a button off, or removing it, stops every page carrying it; so does its maker leaving the company.

Each button takes up to 100 reports in a rolling day. A whole report is at most 6 MB. A company has up to 20 buttons.

## Public endpoints

Two Proof endpoints are called from outside Dbrij, both relative to the API base. Everything else is used through the Proof app.

### POST /v1/public/proof/capture?k=<key>

Where the bug button sends a report. The key is a send only credential, like an analytics site key, so the endpoint answers any origin. The body is the report as JSON sent with `Content-Type: text/plain`, which keeps it a simple request the browser does not preflight.

Accepted

```
HTTP/1.1 202 Accepted

{ "success": true, "data": { "ok": true, "reference": "T-42" } }
```

|  |  |  |
| --- | --- | --- |
| 202 | Accepted | Filed. reference is the bug’s task number. |
| 400 | Bad Request | No title, or a body that is not a report. |
| 403 | Forbidden | This bug button is not set up for this site. |
| 404 | Not Found | This bug button is not switched on. |
| 429 | Too Many Requests | The button’s day is full, or more than 10 reports a minute came from one sender. |

### POST /v1/proof/tests/ci/results

Where CI sends test results, with `Authorization: Bearer dbpci_…`. The body is JUnit XML or JSON, read as text, up to 10 MB. See Test cases and CI uploads.

## Plans and limits

Proof is free for one watched target, so you can point it at a repository and see the map it produces. Subscribe to Proof to watch more. Scans, updates, suite summaries, journey writing and case drafting are written by Deputy and spend AI credits.

|  |  |  |
| --- | --- | --- |
| Targets | per person | 20. |
| Features | per scan | 60, with up to 12 entry points each. |
| Live checks | per run | 12 per feature, 800 in all, 8 seconds each, 5 minutes a run. |
| Suite run | each | 15 minutes. |
| Journeys | per target | 12, with 20 steps each and 12 seconds a step. |
| Walkthrough | each | 8 pages, 7 minutes. |
| Updates kept | days | 180. |
| Test cases | per space | 10,000 cases, 200 suites, 50 steps a case. |
| Runs and imports | each | 2,000 cases a run, 1,000 cases an import, 12 drafted cases at a time. |
| CI | per space | 20 tokens; 5,000 tests and 10 MB an upload. |
| Bug buttons | per company | 20 buttons, 100 reports a button a day, 4 MB screenshots, 6 MB a report. |

## SDKs and packages

Every SDK and package for Proof, with what it does, how to install it and the smallest working use. The whole catalogue, for every product, is on [the apps page](https://dbrij.com/apps#sdks).

- JavaScript 1 package
- Browsers 1 package

### proof-capture.js

A Report a bug button for your own web app that files each report, with the errors the page hit, into your company's bug triage.

Script for your site · JavaScript · Served by Dbrij · Runs on Browsers

- Keeps the last console errors and failed requests from the moment it loads
- Never sends a request or response body, nor a query string
- Reports carry the page, the browser, an optional screenshot and the Glass visit when Glass runs
- window.dbrijBugs.open and report for your own button or form
- Draws its form in a shadow root, so your styles and its styles never mix

Install

```
<script src="https://dbrij.com/proof-capture.js" data-key="pc_..." async></script>
```

Quick start

```
<script src="https://dbrij.com/proof-capture.js" data-key="pc_..." data-build="2.4.1" data-button="off" async></script><script>  document.querySelector('#report').onclick = () => window.dbrijBugs.open();</script>
```
