Verification flow
The Verifier
$verifier = new Verifier(
checks: [ /* Check, Check, ... */ ],
riskStrategy: RuleBasedRiskStrategy::withDefaultRules(),
clock: new SystemClock(),
logger: $psr3Logger, // optional
);
$outcome = $verifier->verify($counterparty);
Step by step, verify():
- Iterates the configured checks and runs each one whose
supports($counterparty)is true. - Collects the
CheckResults into aVerificationReport. - Passes the report to the
RiskStrategy, producing aRiskAssessment. - Returns a
VerificationOutcome(counterparty + report + assessment).
Checks
A Check is one deterministic step:
interface Check
{
public function name(): string; // "PL White List"
public function source(): string; // "pl.white_list"
public function supports(Counterparty $c): bool; // applicable?
public function run(Counterparty $c): CheckResult;
}
Guidelines:
- Return an inconclusive result for expected conditions (missing identifier, unsupported country, transport failure) rather than throwing.
- The
Verifieris a safety net: if a check throws unexpectedly, it is logged and converted to an inconclusive result, so one bad check never sinks the whole verification.
Two kinds of check
- Dedicated checks wrap a specific client:
WhiteListCheck,ViesCheck,SanctionsScreeningCheck. - The capability-routed check
RegistryCheckasks theRegistryManagerwhich driver can answer a capability for the counterparty’s country, and reports an honestinconclusivewhen none can. This is how KRS/CEIDG/REGON/CRBR and your own registries are reached.
Reading the outcome
foreach ($outcome->report->results() as $r) {
printf("[%s] %s: %s\n", $r->status->value, $r->checkName, $r->summary);
}
$outcome->assessment->level->value; // low | medium | high | critical
$outcome->requiresHumanReview(); // act on this before auto-approving
The report is ground truth; the assessment is advisory. Wire your business logic to the report’s hard facts and treat the assessment (and any AI evidence) as guidance that may require a human.