concepts

Targets, scopes, projects, runs, findings, coverage.

The mental model the rest of the docs assume. Read this once; the dashboard makes sense after.

Targets & scopes

A target is the system the agents attack: usually a single base URL like https://api.staging.acme.dev. A scope is the contract around that target — allowed paths, blocked methods, rate limits, and authentication material. The scope proxy enforces every line of it before any request leaves our network.

  • Allowed paths — explicit positive list. Everything else is implicitly blocked.
  • Blocked paths — overrides for sub-trees inside an allowed parent (admin routes under /v1/*, for instance).
  • Blocked methods — by default we block DELETE and PUT. Add POST too if your surface is read-mostly.
  • Max requests / minute — back-pressure for your origin; 60 by default, dial up once you've measured.

Projects

A project wraps one target + one scope + zero or more synthetic accounts. Projects belong to an org. The most common shape is acme-staging for staging and acme-api for prod — each gets its own scope, accounts, and budget.

Runs

A run is one agent's attempt against one project. Runs are bounded by a wall-clock budget (default 15 min) and a token budget (default ~200k tokens, ~$1 of Sonnet 4 at current rates). Either breach kills the run. Runs are durable — they live in Inngest and survive process restarts.

trpc · run.start{
  projectId,
  agentClasses: ["idor", "auth-bypass", "ssrf", "stored-xss", "business-logic"],
  wallClockBudgetMs: 15 * 60 * 1000,
  tokenBudget: 200_000,
}

Findings vs hypotheses

A hypothesis is a guess. An agent might say "I bet /v1/users/{id}/api_keys is missing ownership check" — that's a hypothesis. We log it (you can see them in /ops) but we don't tell you about it.

A finding is a hypothesis that the validator reproduced against a real- but-synthetic account, with a captured response that demonstrates the impact. Only findings hit your inbox. The published false-positive rate is 0.4% per 100 confirmed exploits.

severity isn't the agent's call
Severity is assigned by the validator, not the agent, based on what was actually exfiltrated or escalated. We do not have a "medium" bucket for things we're unsure about.

Coverage

Coverage is the receipt — every route we touched, every method we tried, every hypothesis we logged. It's the most expensive thing about being attacked: knowing whether you were tested for the class of bug you actually got hit by. The coverage view labels routes as hot, covered, or cold and rolls up weekly.

Permissions

Roles in brink are explicit: owner, admin, member, viewer. Every mutation is gated by a typed Permission (e.g. project.create, run.trigger). The mapping lives in packages/core/src/roles.ts; the dashboard refuses the button before the server refuses the call.

Where to next

  • Want to see how agents actually decide what to do? → agent design
  • Want to script the platform from CI? → CLI
  • Want the procedure-level surface? → API reference