Matching an order ID was not enough
A copied sample retained its integration identifiers but requested a different test. The fix cleared those fields on copy and checked incoming outcomes against a request fingerprint.
I originally matched an incoming outcome to a request using its order ID and source system. That seemed reasonable: together, those fields told me which integration request the processor was updating.
Then a normal laboratory workflow broke that assumption.
Copy to new also copied the identity
ZanLIS has a “copy to new” action that lets a user create a sample using details from an existing one. In the case I encountered, the copied sample retained integration fields including the order ID, batch ID, and source system.
The original integration request was for a CD4 test. On the copied sample, the user changed the client details and selected a TB test with a sputum specimen. It was new laboratory work, but it still carried the identifiers of the original integration request.
When the copied sample's outcome reached the processor, the reused order ID allowed TB results to overwrite the CD4 request's outcome. The processor recorded the request as verified, but onward delivery failed because the client ID was missing. The incident established a wrong association inside the processor; it did not establish that the mismatched result reached the clinical system.
The identifiers were present and familiar. The relationship they appeared to establish was wrong.
Clear the integration identity when copying
The fix had two parts. In the “copy to new” flow, I cleared the integration-owned fields on the new sample, including the external order ID, batch ID, and source system.
Those fields belonged to the original integration request. Reusing a sample's details should not make the new sample inherit that request's identity. Clearing them at the point of copying prevented this workflow from carrying the old integration relationship into new laboratory work.
That addressed how the misleading identifiers were introduced. The processor still needed to check the outcomes it received, including outcomes from samples copied before the change.
Check what the request was actually for
I also added a request fingerprint so outcome matching could check more than the reference fields.
The implementation derives the fingerprint from the original request's order ID, patient/client identifier, and test code. When an outcome arrives, the processor derives a comparable fingerprint from the outcome's order ID, patient ID, and test code.
The source-system check remains separate. A matching source and order reference can locate the request; the fingerprint checks whether the patient and test also agree.
For the copied-sample case, changing the test changes the fingerprint even when the order ID and patient remain the same. The processor rejects that mismatch before accepting the outcome into the request's state.
A simplified illustration of the original failure, before clearing the fields on copy, with invented identifiers:
| Field | Original request | Copied sample's outcome |
|---|---|---|
| Source | System A | System A |
| Order | ORDER-EXAMPLE | ORDER-EXAMPLE |
| Patient | PATIENT-EXAMPLE | PATIENT-EXAMPLE |
| Test | CD4 test | TB test |
This illustration holds the patient constant to isolate the test mismatch. In the recorded incident, client details changed too. The old lookup accepted the shared reference; the additional integrity check detects a different patient or test.
The hash is only as useful as its inputs
This fingerprint is a deterministic comparison of selected fields. It is not a signature from a trusted sender, and it cannot establish that every part of a result is correct.
Its usefulness comes from the fields I chose and how consistently the processor extracts them across integrations. If I had fingerprinted only the order ID and source system, hashing them would have preserved the same weakness.
It also cannot distinguish two outcomes that share all the compared fields. The purpose here is specific: reject patient or test mismatches that an order-reference lookup would otherwise accept.
Legacy records need care too. The current handler can reconstruct a missing fingerprint from the saved original request when the patient and test fields are available. Records lacking that context do not gain the same protection simply because new code has been deployed.
Historical data needed repair as well
Clearing fields on new copies and checking incoming outcomes protects the path going forward. Neither change automatically corrects outcomes that were already matched incorrectly.
The reconciliation workflow therefore rechecks outcomes using the current integrity rules before removing old failure records. Deleting duplicate-looking rows first could remove evidence while leaving the wrong outcome in place.
The important change in my thinking was about identity: copying a field does not preserve the relationship that originally made it meaningful. I needed to stop that identity from being copied into new work and validate the relationship again when an outcome arrived.