VERIFISDK docsengine v2 · contract 1.5.1 · harness-sdk 1.2.0
Start here

Operating principles

Five rules that explain why these APIs refuse the things they refuse.


The VERIFI SDKs are unusually opinionated. They refuse things that look harmless, and they omit conveniences other tool SDKs provide. Every one of those refusals traces to a specific failure that shipped. Read this page once and the rest of the API stops looking arbitrary.

An assertion is not evidence — P4

A component is not working because it says it is, or because someone wrote it down.

The reference case: a Burp Suite MCP was registered for the entire life of the previous engine and served zero calls. The readiness check counted any 4xx response as ready, and nothing ever performed an MCP initialize or tools/list. Preflight passed, scans proceeded, every Burp call timed out. Web penetration tests ran for months without their primary scanner, and no part of the system could tell the difference.

What this produces in the API:

  • The registry lifecycle enum has no state meaning "registered, assumed working". It is unregistered | probing | available | degraded | unavailable | retired.
  • Registry.register() inserts as probing whatever the caller supplies. setStatus() throws if you pass available. The only route to available is probe() passing.
  • zMcpServer refuses to parse when status: 'available' and probe.passed !== true.
  • zModel refuses available without probeInvoked: true — a real invocation that returned tokens, because model catalogues list models they cannot serve.
  • zKnowledgeBase refuses available with zero chunks — it answers HTTP but retrieves nothing.
  • The probe runs again as a run preflight, because a probe that passed last week says nothing about right now.

The registration schemas are P4 in the type system

A field a caller can set is a field a caller can lie about. So zModelRegistration, zMcpRegistration, zKbRegistration and zHarnessRegistration are all .strict() and simply do not carry the fields that are outcomes:

status  ·  probe  ·  probeInvoked  ·  tools  ·  lastProbedAt  ·  authRef

Sending one is a parse error, not a silently ignored key. Verified against contract 1.5.1 — every one of those six is refused on a model registration. zMcpRegistration goes further and excludes shared from the concurrency enum it accepts, because declaring shared is asserting a passed statelessness probe.

That is also why the console's register form has no status control: there is no request body that can register something as already working. See Registering a component.

Listing is not availability — P12

A provider will cheerfully list models it cannot invoke. NIM does; so does Bedrock, where most modern models are reachable only through a cross-region inference profile and a call to the bare model id returns a validation error.

So a Model does not get a three-gate HTTP probe — it has no endpoint to probe. It gets a real invocation, and the pass condition is that the invocation returned non-zero token counts:

  • parseModelResponse returns { text: '', inputTokens: 0, outputTokens: 0 } for a shape it does not recognise, rather than guessing. A parser that invented plausible numbers would let a model that cannot be called reach available.
  • A 200 response with zero tokens is a failed probe. A well-formed empty response is exactly what a provider returns for a model it advertises and cannot run.
  • zModel refuses status: 'available' without probeInvoked: true.

The same shape applies to a Harness, which serves nothing at all: it is probed by checking that its image digest exists, has been scanned, and the scan is neither stale nor carrying a blocking severity. An unscanned image fails exactly like a vulnerable one — "no findings" and "no scan" are different statements.

A dead scanner reporting zero findings reads as a clean bill of health

This is the failure mode the whole design is bent around. A scan that completes with no findings is indistinguishable, from the outside, from a scan whose tools were never installed. The previous engine's infrastructure line wired end to end perfectly and produced approximately zero findings, because every CLI reported SKIP: not installed.

What this produces in the API:

  • Gate 2 of the three-gate probe (GET /test) must exercise the real backend, not report process liveness. The real MCPs execute each binary with a version flag — presence on $PATH is not enough, because a truncated or wrong-architecture download resolves on $PATH and then fails on every call.
  • Gate 3 requires at least one tool. A server that answers the protocol and exposes nothing is not available; it is decorative.
  • A slot's dead primary raises mcp.no_healthy_tool at error severity, once, rather than emitting one tool_error per call and leaving "the scanner is gone" to be inferred from a thin result set.
  • run.completed_zero_findings is a first-class alert routed to both analyst and ops.
  • A green dry run proves wiring, never findings — the SDK's own comments say so, and so does this site.

A passed check is not a finding

Coverage and findings are separate outputs. A harness declares coverage intent through declarePlan(), and the run reports what it actually achieved against that declaration. A gap is a coverage_gap event and a run.coverage_gap alert — a first-class run output, not an absence.

This is also why declarePlan() is explicitly not the execution plan. At runtime the agent takes a data-dependent number of steps and may use any tool its belt offers, because recon shapes which tests are worth running.

Time is the only hard bound

Cost, tokens, tool calls and evidence bytes are metered, thresholded and alerted — never enforced.

The reasoning is in budget.ts verbatim: capping any of those severs a scan mid-test. The target is left half-examined, the findings are partial, and the delivered report is wrong in a way that is hard to detect from outside. An overspend is a bill; a truncated assessment is a defective product shipped to a client.

What this produces in the API:

  • zBudget is .strict() so a resurrected maxCostUsd or policy field is a loud parse error rather than a silently ignored field somebody believes is enforced.
  • BudgetLedger has no method that can refuse a spend. record() always succeeds.
  • zRunStatus has no budget_exceeded. timed_out is the terminal condition that remains, and since spend accrues at a finite rate, a time bound is also a cost bound.
  • The gRPC Stop message carries 'deadline' | 'operator' | 'failure'. There is deliberately no cost reason.
  • ctx.signal fires on stop, deadline or operator cancel. Never on cost.

Two more that follow from the above

Findings persist the moment they are produced. Never at finalize. The previous engine made _finalize() the only caller of persist_findings, so a failure in a later phase gave the tenant zero findings from a scan whose results were verified on disk. Run outcome and finding persistence are independent: a run that fails late keeps everything it already found.

Credentials are indirections, never values. zCredRef is a regex that only accepts secret:<id>, env:<VAR>, or bedrock-sts. A raw connection string or API key is not representable anywhere a credRef is expected. No sample on this site contains a credential, real or fake.

The single exception is apiKey on a registration, and it is an exception in flight only: the engine splits the key off the record before anything is stored, writes it to Secrets Manager, and persists authRef: secret:<id>. The response carries the reference, never the key, and there is no route that reads it back.

"Read failed" is not "value absent"

The narrowest rule here and the one that has cost the most. Two statements that look alike from a call site and are not:

I looked, and there is nothing there.a fact about the world
I could not look.a fact about us

Collapsing them is how a live credential once got overwritten with a stale seed. It appears throughout these APIs as a deliberate refusal to default:

  • isCompatible('1.0') returns false. Unparseable is never "compatible".
  • A probe that throws is a failed probe, never an absent one — for the three gates, for the model probe, and for the harness image scan.
  • A harness image that has never been scanned fails the probe exactly like one with a critical CVE, and so does one whose scanner could not be reached.
  • parseModelResponse returns zero tokens for an unrecognised payload rather than a guess.
  • buildModelRequest refuses a Bedrock family it has no body shape for, rather than sending an Anthropic body that will 400 in a way that reads like a broken model.
  • modelEndpoint refuses openai_compat with no baseUrl rather than defaulting to OpenAI, which would send a self-hosted deployment's traffic and its key to a third party.

When you write a harness or an MCP, the same rule applies to you: a tool that could not run must not return the same thing as a tool that ran and found nothing.