Repository navigation
Release 2026.3.0 - #907
Merged
Merged
Release 2026.3.0#907
Conversation
get_hgvs_from_post_mapped can now join the members of a multi-variant block (Haplotype/CisPhasedBlock) into a single bracketed cis-phased expression via the new combine_cis flag, replacing the previous behavior of returning None for any multi-variant block. - combine_cis defaults off because some consumers cannot yet handle a bracketed expression — notably ClinGen submission, which has no single CAID for a multi-variant cis block (#764) - the CSV export fallback opts in, so g./p. HGVS columns are populated from cis-phased post-mapped output instead of left empty - drop the stale commented-out error branches and the resolved TODO
…-keyed refresh Replace MappedVariant-based gnomAD linkage with valid-time GnomadAlleleLink rows keyed on the deduplicated Allele. Linking covers every current allele of a score set (authoritative and RT-derived), so protein/coding score sets — whose genomic allele is RT-derived — are no longer dropped; per-variant annotation status flows through the _annotate_gnomad choke point against authoritative links only (interim bandaid, the AnnotationEvent migration seam). Refresh / idempotency model: - One live link per allele (unique index on allele_id); a gnomAD version bump supersedes rather than accumulating one live link per version. - Supersede only on change — an unchanged re-run leaves the live link untouched, so the valid-time history records no spurious boundary. - Version-keyed skip avoids re-fetching alleles already current at the version; a force param bypasses the skip (re-ingestion / heal) without churning unchanged links. - Per-variant status is a per-run audit event: created / preexisting / skipped. Normalize CAIDs across the Athena join: the gnomAD Hail dump drops leading zeros (CA025094 -> CA25094), so exact-string matching silently missed zero-padded CAIDs. Extract group_alleles_for_annotation as the shared allele-grouping primitive for allele-subject annotation jobs (adopted by gnomAD; VEP/ClinVar to follow). Refs #742. Partially addresses #722 (CAID-completeness tracking there stays open).
Migrate the VEP functional-consequence job (Step 2 of the annotation infrastructure migration) off MappedVariant onto the deduplicated allele model. - New ValidTime vep_allele_consequences table: a single allele-keyed row collapses record + link (the consequence is a scalar with no shared external entity, unlike gnomAD/ClinVar). One live consequence per allele via a partial unique index. - Job runs over the score set's full allele set (authoritative + RT-derived) via get_alleles_for_score_set + the shared grouping primitive; VAS still fans only to authoritative variants (the bandaid seam). - Version-key the refresh on the Ensembl release (/info/software): skip alleles already current, abort if the release can't be fetched. Supersede is value-keyed, not version-keyed — an unchanged consequence at a new release bumps source_version/access_date in place to avoid churning history. force bypasses the skip (e.g. after editing VEP_CONSEQUENCES). - A no-result is treated as a non-answer, never a negative: held consequences are not retired on an empty/failed VEP fetch. - Annotation links stay one-directional to Allele (no reverse back-ref). Adds lib + job tests covering linkage, RT-derived scope, version skip, in-place bump, supersede-on-change, no-result handling, and release-fetch failure.
Step 3 of the #742 external-annotation migration. ClinVar linkage moves off MappedVariant onto the deduplicated allele model. - Rename clinical_controls -> clinvar_controls (ORM model + table + unique constraint). Internal only: the ClinicalControl* view models, the /clinical-controls serving endpoints, and the frozen mapped_variants_clinical_controls association are unchanged, since the view-model name is both the OpenAPI schema name and the record_type discriminator consumed by the UI. - New clinvar_allele_links ValidTime table + ClinvarAlleleLink model. Multi-live: partial unique index (allele_id, clinvar_control_id) WHERE valid_to IS NULL, so an allele accumulates one live link per release. - Refactor refresh_clinvar_controls onto get_alleles_for_score_set + group_alleles_for_annotation (payload = CAID, full allele scope). Links are get-or-create; a same-version re-resolution to a different control supersedes newest-wins (gap-free retire+insert) rather than leaving two live links. VAS writes funnel through the _annotate_clinvar choke point, fanned only to authoritative_variant_ids and version-scoped. - Additively capture ClinVar's VariationID: nullable clinvar_variation_id column populated forward from the variant_summary TSV (parse degrades to None on archival schemas lacking the column). Unserved; the dedicated clinvar_variants remodel is deferred to the read-cutover. Tests rewritten for the allele model, covering the multi-live link writes, the version-scoped supersede guard, and the authoritative-only VAS fan-out.
Steps 4 & 5 of the #742 migration. Both jobs are redundant under the allele model: Allele.hgvs_g/c/p are populated by the mapping job, and the reverse-translation equivalence space (genomic/coding/protein alleles linked per MappingRecord) replaces the ClinGen PA<->CA translation table. - Remove populate_hgvs_for_score_set and populate_variant_translations_for_score_set from the pipeline DAG (both were leaf nodes — no dependency edges to repair), the worker registry (BACKGROUND_FUNCTIONS + STANDALONE_JOB_DEFINITIONS), and the external_services package exports. - Delete the two job modules and the now-orphaned ClinGen HGVS helpers (extract_hgvs_from_ca_allele_data / extract_hgvs_from_pa_allele_data), used only by the HGVS job. - Keep lib/variant_translations.py and the variant_translations table/model, marked FROZEN (serving-only) — they back old-model serving and are dropped at read-cutover. - Delete the obsolete job tests and their conftest fixtures.
get_allele_translations(db, allele_id, *, as_of=None) returns an allele's full cross-layer equivalence set (genomic/coding/protein) by traversing the MappingRecordAllele link graph: allele -> its live links -> mapping record(s) -> all co-linked alleles. The relation is co-membership in a MappingRecord's allele set, not a shared identifier — ClinGen's CAID spans only the nucleotide layers (the protein allele carries a distinct PA), so the link graph is the only thing tying all layers together. This replaces what the retired variant_translations PA<->CA table provided. Forward-compatible with temporal reads: the same half-open valid-time predicate is applied at both the anchor and fan-out hops, so passing as_of reconstructs the equivalence set as of any instant. Defaults to the currently-live set.
…bulary Introduces the AnnotationEvent log: a single append-only event table whose subjects are Variant and Allele, selected by annotation_type via a polymorphic CHECK. "Current" is derived (DISTINCT ON … id DESC), never stored. Adds the shared Disposition (present/absent/not_applicable/failed) and EventReason vocabulary, the v_current_annotation_events view, and the supporting migrations.
group_alleles_for_annotation now returns one job-specific payload per allele instead of an AlleleAnnotationGroup. Drops the authoritative_variant_ids bandaid seam (and is_authoritative from ScoreSetAlleleRow): annotation is an allele-level fact, and with the AnnotationEvent log the per-variant status fan-out goes away.
AnnotationStatusManager now writes AnnotationEvent rows via record_event and derives current status from the event log instead of maintaining per-variant status rows. Resolves subjects through VARIANT_SUBJECT_TYPES/ALLELE_SUBJECT_TYPES and the Disposition vocabulary.
link_gnomad_variants_to_alleles now returns a GnomadLinkVerdict per touched allele (CREATED/UNCHANGED) as the single source of truth for per-allele status; the job derives annotation events directly from the verdict map rather than re-querying link state. Alleles absent from the map are read as 'gnomAD had no record'.
VEP resolution now returns a VepResolution (consequences vs errored) so a genuine empty is distinguished from an unknown, and linking returns a VepLinkVerdict per allele (CREATED/UNCHANGED). The job derives annotation events from these outcomes instead of re-querying consequence state; errored HGVS are retried, not recorded as negatives.
The ClinGen allele-registration and LDH-submission jobs now record AnnotationEvents via record_event, using the shared EventReason vocabulary (created/preexisting/ reconfirmed/submitted, and the CAR-specific failure and reconfirmation-skipped reasons) in place of per-variant status updates.
The ClinVar job records AnnotationEvents via record_event, distinguishing superseded/no_record/no_caid/multi_variant_caid cases through the shared EventReason vocabulary. Clarifies the ClinicalControl comments to mark the row-level vs variation-level link identifiers.
The mapping job records AnnotationEvents via record_event, deriving disposition and reason from the typed MappingOutcome (mapped / intronic / no_protein_consequence / failed) rather than writing per-variant status rows.
The reverse-translation job records AnnotationEvents via record_event, using the RT-specific EventReason cases (translated / no_coding_transcript / no_assay_level_hgvs / translation_failed / translation_error / transcript_unresolved) to distinguish informative negatives from failures.
Adds the pipeline_tracking script for querying pipeline progress from the AnnotationEvent log, and updates the variant_annotations script to read/write through the event model.
An allele with an existing CAID always matched the preexisting branch first, so force_reregister never re-submitted it. Existing-CAID alleles now route to pending whenever force_reregister is set.
Split the resolution exception handling: an HTTPError (VEP rejecting a batch, e.g. a 400 for protein HGVS it cannot parse) now routes the batch to Variant Recoder, which may still resolve it via genomic recoding. Only transport/network errors (RequestException) are marked errored and held for retry — fixing the case where recoverable inputs were wrongly recorded as unknown.
normalize_and_identify/_rle_to_lse assume an inlined SequenceReference and integer coordinates, but the VRS models type location.sequenceReference and location.start/rle.length as unions (iriReference/Range/None). Add narrowing assertions documenting that contract — restoring a green `mypy src/` (a required CI job) and turning the unreachable bad-input case into a clear AssertionError instead of a deeper AttributeError. Adds guard tests.
The newest-wins ClinvarAlleleLink supersede stamped valid_to/valid_from with a tz-naive datetime.now() into timestamptz columns, skewing the valid-time axis against every other job's func.now()-stamped rows. Use supersede_with so retire and insert share one DB timestamp. Test now asserts the boundary is timezone-aware.
Every other FK on annotation_event was indexed except score_set_id. Add it (model __table_args__ + migration) to back the ON DELETE SET NULL cascade on score-set deletion and score-set-scoped audit queries.
Revision a1b2c3d4e5f6 creates alleles/mapping_records/mapping_record_alleles — there is no allele-closure table anywhere (equivalence is a runtime query). Rename the file so it stops misleading readers; the revision id is unchanged.
Re-add cases dropped in the manager rewrite: None/empty reads, no-op flush, auto-flush-before-read for both query methods, a FAILED-disposition round-trip through the manager, and per-subject current-status isolation.
…ents split_cis_phased_hgvs raised ValueError on bracketed input lacking an accession; it now degrades to a single-element list. join_cis_phased_hgvs emits components in coordinate order so CSV exports are deterministic regardless of VRS member ordering (the block digest is order-independent).
get_hgvs_from_post_mapped can now join the members of a multi-variant block (Haplotype/CisPhasedBlock) into a single bracketed cis-phased expression via the new combine_cis flag, replacing the previous behavior of returning None for any multi-variant block. - combine_cis defaults off because some consumers cannot yet handle a bracketed expression — notably ClinGen submission, which has no single CAID for a multi-variant cis block (#764) - the CSV export fallback opts in, so g./p. HGVS columns are populated from cis-phased post-mapped output instead of left empty - drop the stale commented-out error branches and the resolved TODO
Step 3 of the #742 external-annotation migration. ClinVar linkage moves off MappedVariant onto the deduplicated allele model. - Rename clinical_controls -> clinvar_controls (ORM model + table + unique constraint). Internal only: the ClinicalControl* view models, the /clinical-controls serving endpoints, and the frozen mapped_variants_clinical_controls association are unchanged, since the view-model name is both the OpenAPI schema name and the record_type discriminator consumed by the UI. - New clinvar_allele_links ValidTime table + ClinvarAlleleLink model. Multi-live: partial unique index (allele_id, clinvar_control_id) WHERE valid_to IS NULL, so an allele accumulates one live link per release. - Refactor refresh_clinvar_controls onto get_alleles_for_score_set + group_alleles_for_annotation (payload = CAID, full allele scope). Links are get-or-create; a same-version re-resolution to a different control supersedes newest-wins (gap-free retire+insert) rather than leaving two live links. VAS writes funnel through the _annotate_clinvar choke point, fanned only to authoritative_variant_ids and version-scoped. - Additively capture ClinVar's VariationID: nullable clinvar_variation_id column populated forward from the variant_summary TSV (parse degrades to None on archival schemas lacking the column). Unserved; the dedicated clinvar_variants remodel is deferred to the read-cutover. Tests rewritten for the allele model, covering the multi-live link writes, the version-scoped supersede guard, and the authoritative-only VAS fan-out.
… allele links Add the Cat-VRS transit foundation for the #743 variant + annotation API. The CategoricalVariant served on /variants/{urn} is assembled per request from a variant's live MappingRecordAllele links, not materialized: a stored skeleton on MappingRecord (the design's D33) would be a denormalized cache of the link graph with a sync cost and no benefit, since the link graph already derives it on demand and full-scan paths never assemble Cat-VRS. This reverses D33. - lib/alleles.py: get_live_record_allele_links — record-scoped live link set for a variant (defining + members, as_of-aware), distinct from the cross-record union of get_allele_translations. - lib/cat_vrs.py: build_categorical_variant (pure over links) -> CategoricalVariantTransit (spec-pure CategoricalVariant + mode + per-member digest->relation map), plus the categorical_variant_for_variant DB wrapper that threads as_of through the fetch. - ga4gh-cat-vrs promoted to a direct dependency (package 0.7.2 implements Cat-VRS spec 1.0.0); members are bare variations with relations on DefiningAlleleConstraint. - Anomaly logging when an authoritative or member allele has no post_mapped. - 16 tests (7 unit / 9 integration), mypy + ruff clean.
Add score_from_variant_data / variant_score to lib/variants.py as the single accessor for a variant's score_data.score — float-coercing (accepts numeric strings, rejects bool/None), robust to malformed JSONB. Replaces scattered variant.data["score_data"]["score"] reach-ins, several of which carried a # type: ignore. Migrate score_calibrations, annotation/util (variant_can_be_annotated), and annotation/study_result to the helper — dropping the duplicated defensive dict/float handling and the type: ignore suppressions. Unit-tested over the coercion / NA / non-dict matrix.
…variants)
Add the lean per-variant dataset the score-set page composes its table, heatmap, and histograms from: variant_urn, score, representative VEP consequence, ClinGen id + assay-level digest, and HGVS in both frames — submitted hgvs_nt/pro/splice (target) and mapped assay_level_hgvs + protein_level_hgvs (reference). Each slot carries the canonical HGVS string plus a parsed {position,ref,alt} block when it is a simple substitution (splice/indels/multivariants keep the string alone).
Assembled in one bulk query, one row per variant: the authoritative allele is joined directly for digest/ClinGen/consequence; the protein HGVS comes from a correlated scalar subquery so there is no allele fan-out. Opt-in ?as_of= reconstructs the annotation layer over the immutable scores/submitted HGVS and is echoed via the X-As-Of header. response_model_exclude_none keeps the payload lean; READ-gated via fetch_score_set_by_urn.
Adds simple-substitution HGVS parsers to lib/hgvs.py. A single canonical coding projection for genomic/coding assays is deferred to #784 (the degenerate reverse-translation set has no canonical member): the hover tooltip uses this strict model, the selection tooltip uses the detail endpoint's full set.
Tests: parser units + lib integration (nt/protein assays, as_of reconstruction, unmapped, unparseable-string, ordering) + router (serialization, exclude_none, X-As-Of, and the READ permission matrix).
…nly calls Score sets store a 24-bin summary of their scores in a new nullable score_distribution column, written by the variant creation job in the same transaction as the variants and served as scoreDistribution on the ScoreSet view model. Bins span the full [min, max] of the numeric scores; null and non-finite scores are counted separately. backfill_score_distributions fills existing score sets after migration b4d8f2a6c1e3. Allele measurements carry a single classification instead of separate preferred and research-use-only fields. A research-use-only call stands in only when the request sets include_research_use_only and the score set has no readable non-RUO calibration with functional classifications; classificationIsResearchUseOnly marks it. Ordering uses non-RUO calls alone.
Run with --commit against a serving database, a single end-of-run commit held row locks on every updated score set for the whole run. Each score set now commits as it finishes, so locks are brief and an interrupted run keeps its progress. --dry-run still rolls everything back.
…AndThresholdSource Fix the outer source not found error in both Method sources and Threshold sources in creating a new score set and calibration.
A rerun renumbered projection groups by list position, so a measured allele's group could change while its link stayed live, pairing it with the wrong projection. Groups that fold in the measured allele keep their prior numbers where possible, and a measured-allele link whose group does change is superseded and re-created under the same timestamp. A fold-in that misses the measured allele is now logged, counted, and recorded as fold_in_missed in the candidates metadata.
observe_statements (formerly log_slow_statements) also increments db_statement_count in the request logging context, so a route's query count shows up in the request log. CSV tests count statements through the shared captured_statements helper.
…rs with one rule The variant-details stream, annotation streams, and public exports loaded each variant's records, links, cross-references, and classifications separately. They now load per chunk of 500 variants through with_chunk_inputs, a fixed number of queries per chunk, and the single variant routes are chunks of one. Cat-VRS, variant detail, and allele detail each labelled members with their own rule and disagreed. cat_vrs.member_label is now the one labeller. A nucleotide member outside the measured allele's projection group reads as co_encodes/convergent rather than a coordinate representation, so a fold-in miss no longer serves convergent siblings as exact matches. test_query_scaling walks every parameterized GET route and fails when a route runs more queries on a larger score set than a smaller one.
…avedb-api into release-2026.3.0
A cache hit kept the expiry its first writer set, so data a sibling score set cached nearly a day earlier could expire minutes after the warming job read it, leaving the downstream jobs a cold cache. The warming job now restarts each allele's expiry after fetching it.
The first version of a refresh can make thousands of uncached ClinGen lookups without updating progress, so the stall reaper cancelled it at 30 minutes. Progress is now reported every 500 alleles.
The mapper's BLAT limit is now 20 minutes and a failed parse runs BLAT twice, so the 30-minute floor cancelled small score sets before the mapper's own timeout could fire.
…dle findings Add --collection and --translated-since alongside --score-set on both audit scripts, so findings left by an older pipeline drop out. Split measured_allele_outside_projection_group: changes reaching past the codon RT targeted and reference-identical alleles are now info-level checks, since RT can never list them. Correct the malformed-group description: groups of one come from library projection failures, not only failed translations.
A sequence's only correct ga4gh alias is its own digest. Any other makes refget lookups for it nondeterministic, as the mapper's stop-codon digest bug did on staging.
Production RDS runs Postgres 15. Both compose files move to postgres:15 on new volumes, since a 14 data directory won't start under 15; the first `up` initializes an empty database.
Each audit loaded its whole result set into memory before iterating, which exhausted a 14 GB container on a production-sized database (1.6M alleles, 7.3M mapping records). Rows now stream in batches of 5000, keeping memory flat; results are unchanged.
…erver extras The measurements view model imported its relationship enum from lib.allele_measurements, which pulls in fastapi through permissions; the enum now lives in models/enums. The audit-scope and URN-lock tests use the Postgres session fixture, so they skip when psycopg2 is absent.
…he 2026.3.0 substrate Describe measured and candidate projection groups, the ValidTime base class, the 30-minute stall window and the public dump's mapped HGVS columns.
…groups Each mapping record's measured variant now has a projection group holding its genomic, coding and protein HGVS, written from the mapping alone so intronic, UTR, multi-codon and start/stop changes keep their coding and protein descriptions. - Genomic assays without a run transcript fall back to an NM_/ENST target accession, then the MANE Select transcript at the locus. - Genomic HGVS is normalized before projection; inversions are written as the equivalent delins, since VRS cannot represent them; identities keep their span. - A failed projection never replaces a group an earlier run wrote. - A changed standalone re-projection reports the reverse translation links it detaches as detached_rt_links. - Reverse translation joins its candidates to the measured group or its own candidate groups; serving reads mapped HGVS from the measured group. - VRS identifier search also matches pre-mapped identifiers and returns a deterministic order. - project_measured_variants script fills groups for backfilled records.
…queue With the main worker capped at two jobs, hour-long mapping jobs could hold both slots and leave new score sets waiting for variant creation. start_pipeline and create_variants_for_score_set now go to a separate ARQ queue consumed by a second worker process (FastLaneWorkerSettings). - arq_queue_name() routes each JobRun; every enqueue and cleanup's ARQ status/abort checks resolve the queue through it. - The main worker still registers the fast-lane jobs so any already on the default queue at deploy time still run. - Requires the fast-worker container from the deployment repo.
…omic projection An insertion at an exon junction can be written on either side of it. Both spellings identify to one coding allele, but only the in-exon one projects to the genome, and an allele links to a record once. Link pairs with a genomic projection first so the shared allele joins that pair's group rather than a coding-only group.
…s missing cdot's REST client returns None for any non-OK response and caches it for the provider's lifetime, so a cdot-rest 5xx read as "no such transcript" (or no transcripts in a region) until the worker restarted. The MANE Select lookup then returned None, and the measured projection overwrote stored coding and protein HGVS with a group lacking them while reverse translation reported success. cdot_rest() now builds a provider that treats only a 404 as missing, raises on any other error status and sets a request timeout. A transcript a region lists but cdot no longer has is skipped by the MANE lookup.
… the submitted HGVS CAR lists its own normalized spellings of an allele, not the submitted one, so an indel or identity written differently from CAR's form was rejected as a malformed response even though the positional answer was right. On staging that dropped CAIDs for about 0.4% of submissions, all codon-level delins and insertions from reverse translation, and a forced re-registration skipped those alleles instead of verifying them. The count check already ties each response to its submission, so the CAID is linked as usual. An unlisted spelling is recorded on the event as submitted_hgvs_unlisted with the submitted HGVS, counted in the job outcome as unlisted_hgvs_allele_count, and summarized in one warning per job.
…'s shared projection A measured coding change across an exon junction (a codon split by an intron) projected to a genomic change that also deleted the intron, because hgvs maps the two ends of an interval separately. The measured projection and reverse translation's candidates now use variant-annotation's coding_to_genomic and genomic_to_coding, which give such a change no projection and write an inv as the delins on its trimmed span. - Pin variant-annotation to v1.2.0-beta.1, which brings variant-translation 1.2.0. - WorkerCoordinateTranslator gains c_to_n for the span check. - The dump README and CHANGELOG note that a split-codon change has NA for post_mapped_hgvs_g. Score sets that already ran reverse translation need it re-run to retire intron-deleting candidates and refresh measured groups at split codons.
…stribution backfill ScoreSet.modification_date has onupdate=date.today, so writing the summary through the ORM stamped every score set as modified on the day the backfill ran. The summary is now written with an UPDATE that sets modification_date to itself.
…erpart projectionOf names another spelling of the same nucleotide change. Since projection groups landed, the protein consequence in a measured group was also given the measured allele as its projectionOf, so the UI's allele grouping folded the protein into the measured nucleotide group: on a protein-change page with a nucleotide measurement the nucleotide row was marked as the page's own variant, and rows reordered with the selected measurement. The protein's relation (translation_of) already says what it is to the measured allele, so it no longer carries projectionOf in variant or allele detail.
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.
Features
Bug Fixes
Retry-After: 30under load.Content-Length, leading toRuntimeErrors #847 closes Refget sequence endpoint declares the full sequence length asContent-Lengthon subsequence requests #846: Report the correctContent-Lengthfor refget subsequence requests, and return 416 whenstart > endon a linear sequence.POST /api/v1/hgvs/validatereturns 500 for malformed input #860: Return 4XX instead of 500 for malformed input toPOST /hgvs/validate.uniprot_id_from_mapped_metadatavalue fromtarget_geneprior to updating #794: Clear a staleuniprot_id_from_mapped_metadatabefore a remap updates it.Maintenance
Breaking API changes
POST /variants/clingen-allele-id-lookupsremoved (405).GET /score-sets/{urn}/mapped-variantsreturns 410; useGET /score-sets/{urn}/variant-details(NDJSON withpreMapped/postMapped).GET /mapped-variants/{urn}and/mapped-variants/vrs/{id}return 301 to/variants/...with a new body shape;/mapped-variants/{urn}/va/*returns 301 and is wire-compatible.GET /variants/{urn}returnsVariantDetail.id,data,hgvsNt/hgvsPro/hgvsSplice,scoreSet,scoreSetId,mappedVariants[], the dates andrecordTypeare gone.mappedVariants→clinvarLinks[{variantUrn, alleleDigest}]; gnomAD variantsmappedVariants→variantLinks[{variantUrn, alleleDigest}].MappedVariant*,TargetGeneMapping,AnnotationLayer,Variant,VariantEffectMeasurementWith*ScoreSet,ClingenAlleleIdVariant*.only_currentis replaced byas_of. CSV rows are ordered by variant number, and gnomAD columns are no longer filtered to onedb_version.GET /alleles/{identifier},/clingen-alleles/{id}/measurements,/score-sets/{urn}/variants,/score-sets/{urn}/variant-details,/variants/vrs/{identifier},/variants/{urn}/va/*,/diseases/search.Deployment
main's head4dbf24ed1857.variants (id, scoreset_id)unique index by hand before deploying; otherwise45e8ec1db15ebuilds it inline and blocks writes tovariants.45e8ec1db15ealso rewritesmapping_recordsunder an exclusive lock (~4–5 min per million rows).a7c3e5f9b1d2buildsuq_alleles_hgvsconcurrently. Run the duplicate check in its docstring first.