Appearance
How a check runs
The same path every time, whichever provider is involved.
ConfigResolver ──> Adapter#fetch ──> Adapter#normalize ──> ProviderFetchRun ──> Projector
│
EntityCheck1. Resolve the configuration
ProviderFetchRuns::ConfigResolver decides, for a given check type and entity, which provider is used, what the lookup identifier is, which adapter runs, and how the result should be projected.
This is where preconditions are enforced: an other-registrations check for a passport-only person is refused here with an explicit message, rather than sent and failed.
2. Fetch
The adapter calls the provider. Clients build the request, apply credentials from configuration, and raise a typed error on failure. Every provider client's Error descends from a common Providers::Error, which is what lets the capture step catch them all — including providers added later, without anyone remembering to extend a list.
3. Normalise
The adapter turns the provider's shape into Verity's. Normalisation is deliberately conservative:
- Missing is
nil, not a default - An empty collection means the provider said it was empty, not that we did not ask
- A positive claim requires a positive signal in the payload
4. Capture
ProviderFetchRun.capture! records the run either way:
| Outcome | Recorded |
|---|---|
| Success | Raw response, normalised summary, sanitised request/response snapshot, succeeded |
| Failure | Error message and class, whatever snapshots exist, failed |
Credentials are filtered from the snapshot before storage.
5. Project
Some checks write into Verity's own records. The commercial registration projector fills in legal name, status, dates, activities, parties and relationships. Others — commercial contract, employment, other registrations — are normalisation-only and project nothing: their value is the evidence itself.
6. Publish the result
The check exposes a sanitised public result: the provider's payload with credentials and internal keys stripped. This is what the entity page renders and what the API returns.
Idempotency and reuse
Each run carries a request fingerprint, so a repeated identical call can be recognised. Runs are succeeded, reused or failed; both of the first two count as evidence.