Platform

Designed for the caller that never reads a screen

Everything a person can do in the dashboard is available to a credential — subject to the scopes it was granted, and to a few things a credential deliberately cannot hold.

Credentials

Bounded by construction

  • Shown once. The secret is in the creation response and nowhere else. No endpoint reads it back; if it is lost, revoke and re-issue.
  • Expiry is mandatory. Ninety days by default, a year at most. There is no “never expires”, because that is a credential nobody rotates.
  • Revocation keeps the row. Immediate and idempotent — a retried revocation during an incident must not fail — and the record survives, because an incident review needs to know which credential did what.
  • No inherited authority. A credential has no role. Its authority is exactly the scopes it was granted, and it does not widen when its creator is promoted.

Three scopes no key can hold

apikeys:manage
A credential that can mint credentials turns a bounded, expiring key into permanent access — and revoking the original achieves nothing.
policies:manage
A build must not be able to rewrite the policy it is graded against.
webhooks:manage
A webhook destination is exfiltration wearing configuration's clothes.

Suppression is its own permission

Accepting risk is separated from ordinary triage. A CI runner that can queue scans has no business being able to silence its own failures.

Enumeration

Pagination that tells you what it guarantees

Offsets are wrong under concurrent writes: rows inserted before your position shift everything, and the client silently skips some. TRUSTIVAN uses signed cursors instead.

Ordering by recency uses immutable keys, so the traversal isexhaustive — every row present when you started and not deleted is visited exactly once. Ordering by severity uses a value that changes, so a re-rated finding can move and be seen twice or missed.

Rather than leaving you to know that, every response reports whether the traversal was stable, so a client can assert the guarantee instead of assuming it.

GET /api/v1/findings?order=recent
{
  "data": [ … ],
  "page": {
    "limit": 200,
    "stable": true,
    "next_cursor": "eyJ…"
  }
}

Retries and volume

Built for callers that will retry

Idempotency

A key is reserved before any work, so two concurrent retries cannot both execute. A completed request replays its stored response verbatim. Reusing a key for a different request is an error, never a replay.

Bulk triage

Up to five hundred findings in one transaction. The actions are verbs — suppress, unsuppress, triage — and there is deliberately no bulk resolve, because no human may assert resolution.

Rate limits per credential

Limits apply to the credential, never to the organisation, so one runaway job cannot lock out everyone's colleagues.

Events

Three events, published from inside the transaction

Scan completion, verdicts, and finding state changes. The set is closed rather than open-ended, so a consumer can handle all of it.

Events are announced from within the transaction that caused them, so a delivery cannot describe a state that was rolled back. Payloads are signed with a rotatable secret, carry a timestamp against replay, and are retried with backoff for about a day — which means consumers must be idempotent.

Destinations are checked before they are accepted: private and loopback addresses are refused unless an operator explicitly opts in. The payload contract is versioned by date and written separately from the database models, so an internal migration cannot break your integration.