Repository navigation
Conversation
Bulk combined import checked each row in four places (its validator, a prepare step, an in-transaction revalidate, and the container writer), and the copies disagreed with the write: - A row naming an existing plate by name with an unknown collection barcode passed validation without an occupancy check, then failed on import, or landed in a plate whose barcode the row contradicted. - Two papers on one Sheet in different subjects failed validation but imported. - One plate named by name in one row and by barcode in another escaped the in-file position check. lib/specimen-registration owns Specimen registration (ADR 0010): registerSpecimens plans every entry, refuses with every error, or writes; checkSpecimenRegistration is the same write, rolled back. It finds or reuses the Specimen by (Source, type, date), resolves each Collection so every identifier given must name the same one, checks Grid positions, barcodes, and sublabels against the database and the rest of the request by resolved Collection, and applies unit defaults. Bulk combined import now finds or creates Subjects and hands the rest to the module; its validate route is the full_file import rolled back. createContainerForSpecimen wraps registerSpecimens, so every container write follows the same rules while the other paths' validators wait for their own slices. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #89. First slice of ADR 0010: Specimen registration goes behind one module, and validation becomes the write itself, rolled back.
Rules now enforced in one place:
createContainerForSpecimennow wrapsregisterSpecimens, so derivations, control batches,POST /specimensand add-container already write with these rules. Their separate validators are replaced in slices 2–4.Evidence
All three mismatches were reproduced against the old code before this change.
P1(barcodeP1-BC, tube at A01) and a row{ name: 'P1', barcode: 'UNKNOWN', position: 'A01' }→ validate{ valid: true }, import fails "Position A01 is already used". At A02 the import put the tube inP1.After: both report
Micronix plate 'P1' has barcode 'P1-BC', not 'UNKNOWN'.After: both accept; a repeated sublabel on that sheet is rejected by both.
validate(payload).valid === importSucceeds(payload), and each matches its expected validity.bun run ci:verifypasses locally (API: 1069 pass, 0 fail).Merge Danger
Door: two-way
No schema or wire-shape change. The validate and import response bodies keep their shapes. A full_file import failure now also carries
details.errorswith every problem.Blast Radius: every container write
Every path that creates a Container goes through the new module. Inputs that used to pass now fail:
Messages for some failures changed wording. Each failure now returns every error in one response.
🤖 Generated with Claude Code