fix(context): reject evidence saves after request scope changes
A provider lookup could finish after its request was cancelled or its subject removed, and still save evidence. Recheck request ownership, status and subject membership inside the completion transaction, before either writing evidence or returning an already-saved receipt. Claim/reuse now also rejects missing or malformed subject lists.
Shared request locks keep scope stable through commit while allowing independent collectors to run concurrently. This does not enable provider dispatch or replace API actor/workspace authorization.
Validation:
- Local PostgreSQL 17 regression first reproduced
saved after cancelled, then passed cancellation, removal, missing/null/object membership, wrong owner, valid save and duplicate completion checks. - Existing ten-topic provider evidence/source-lineage regression passed.
- Two local connections verified the completion transaction blocks cancellation until it releases the request lock; completion after cancellation is rejected.
- Minimal disposable Context Engine fixture, not the full historical migration chain or production. No paid calls.
Prerequisite for the runtime integration in recoupable/api#917; tracks recoupable/app#2122. Not deployed.
Summary by cubic
Fixes a race where a provider lookup could finish after its request was cancelled or its subject removed, and still save evidence. Both claim and completion now recheck request ownership, status, and subject membership inside the transaction before writing evidence or returning an already-saved receipt.
Claim and reuse now also reject missing or malformed subject lists. Shared request locks keep scope stable through commit while still allowing independent collectors to run concurrently. This does not enable provider dispatch or replace API actor/workspace authorization.