# Run-bound provenance contract review

Use this checklist for final read-only reviews of status/API/UI changes that expose provider, currency, timestamp, FX, or similar provenance from rows written by a completed batch/run.

## Trace the binding end to end

1. Identify the completed-run selector and verify that “latest” has the intended ordering semantics.
2. Trace the writer to determine the exact row-to-run key. Prefer an explicit run ID; if a timestamp is used, prove the writer stores the identical value atomically in both places.
3. Aggregate **all rows bound to that run** before applying provider-specific validity rules. A predicate such as `provider='ExpectedProvider'` can hide conflicting rows and make `MIN(provider)=MAX(provider)` tautological.
4. Compare the bound-row count with the completed run’s declared stored-row count. Reject zero, missing, duplicate, or extra sets.
5. Check non-null/non-empty counts for every required provenance component. SQL `MIN`/`MAX` ignore `NULL`, so one complete row can mask another incomplete row unless `COUNT(column)=expected_count` (plus empty-string handling where applicable) is enforced.
6. Emit provenance only when the whole bound set satisfies the contract. Derive direct-base-currency/“no FX run” text only after currency completeness and consistency are proven.
7. Verify strict backend response models, required-nullable frontend types, all source variants, and the user-visible fallback independently.

## Deterministic counterexample matrix

Start from one valid completed synthetic run, mutate only the read-side fixture/database, and call the status builder again:

- delete one bound row;
- add an extra row under the same binding key;
- set a nullable required field such as provider timestamp to `NULL`;
- use an empty string if the schema permits it;
- mix providers across otherwise valid rows;
- mix currencies across otherwise valid rows;
- use a different but internally consistent provider to detect hard-coded filters masquerading as derivation;
- add unrelated rows from another run and prove they cannot contaminate the result.

For each invalid set, assert the exact fields that must become `null`; do not settle for a generic happy-path provenance test. Also validate the response through the strict API model and render both complete and unavailable states in the frontend.

## Review reporting

A green focused suite is not sufficient when the negative matrix is absent. If a deterministic malformed-row probe still produces authoritative provenance, classify it as a release-blocking correctness finding and include the observed payload, source line range, and smallest required correction. Keep environment/setup failures separate from product findings.
