Skip to main content
An assessment is a sequence of declared phases inside one session. The agent marks each transition, so the terminal and any live report can follow along without inventing a progress percentage.

The eight phases

1

preflight

Identify the repository root and stack. Load the session context. Detect a local test or development runtime without mutating production configuration. Inventory local origins and the external origins the project references. Identify available test identities and safe fixtures. Note whether an isolated runtime is available, and say so calmly if it is not.
2

scope

Settle what is in bounds. Loopback is the normal target class. Every external origin stays out of bounds until it passes the authorization gate.
3

discovery

Build a threat-oriented application map before hunting for bugs: entry points and routes, the authentication and session implementation, where authorization is enforced, data stores and trust boundaries, upload and download surfaces, outbound requests and webhooks, parsing and template and query construction, secret handling, admin endpoints, third-party integrations, and dependency manifests.
4

source_review

Start from the static pass’s candidates rather than the file tree — each names a route, a line, and the data flow it believes in. Then look for plausible root causes the static pass could not reach: authorization missing at a server-side boundary, unsafe composition of queries or commands or templates or paths, insecure file handling, server-side fetches without destination validation, token and cookie and session mistakes, trust in client-controlled role or ownership identifiers, and security-relevant business-logic assumptions.
5

runtime_validation

Exercise routes against the local running service with representative safe inputs and the configured test identities, to establish whether a candidate is actually reachable and security-relevant. Anything risky goes through action check first.
6

access_control

Compare identities: unauthenticated, normal user A, normal user B for object-ownership boundaries, and a privileged user. The focus is server-side enforcement and object ownership, using non-destructive fixture objects. A class that cannot be tested because an identity or fixture is missing is recorded as a limitation, not guessed.
7

validation

Assign verification honestly, deduplicate, and — at high effort and above — run a false-positive challenge pass that argues the opposite of each candidate and keeps only what survives.
8

reporting

session finish validates every finding, renders all four formats, and syncs if this scan opted in.

Session states

ScanState in packages/contracts/src/domain.ts: created · preflight · scope · discovery · assessment · validation · reporting · complete · cancelled · failed · policy_blocked Phase records themselves carry their own state: pending, running, complete, or skipped, with start and completion instants and a duration.

Cloud state

Separate from the scan state, because a scan is never blocked by the cloud. LocalCloudState:

Live progress events

A synced report receives only allowlisted, privacy-safe events. The payload schema is closed, so the scanner cannot deliver source, prose, evidence, or secrets through this path even by accident — schemas/scan-event.schema.json is the contract, and the server rejects anything that fails it with UNSAFE_PAYLOAD_REJECTED. Event types (ScanEventType): report_created · phase_started · phase_completed · aggregate_updated · warning_safe · scan_completed · scan_failed An event may carry a phase, a stable safeCode, a short message, a duration, and an aggregate of counts (candidateCount, validatedCount, and per-severity totals). Nothing else. Browsers read the stream over server-sent events at GET /api/v1/reports/{id}/events, which re-checks report access before the stream opens, replays the stored history, and heartbeats every 20 seconds. Streams have a bounded lifetime (SSE_MAX_STREAM_MS, default 5 minutes) so no viewer can hold a container through a deploy; the browser reconnects and the route replays.

Ending a session

Both write a complete local report. cancel is the honest way to stop: it keeps the validated findings and the coverage notes rather than throwing the work away.