Summary
Give every Variant a stable, pre-mapped VRS allele object plus its ga4gh digest, minted by MaveDB during variant creation, instead of only for variants that flow through the dcd-mapping service. The digest becomes a universal, joinable identifier for search and export; the value lives on Variant, and the disposition/reason lives in the annotation event log.
Problem
Today, pre-mapped ("assay-level") VRS is a byproduct of invoking dcd-mapping. On the allele-centric branch it lands on MappingRecord.pre_mapped, and a MappingRecord is only created for variants in score sets we actually send to dcd-mapping, and only when that service succeeds in constructing the pre-mapped allele.
Consequences:
- Variants in score sets we never map — or variants where dcd-mapping fails to build the pre-mapped allele — have no VRS identifier at all.
- There is no universal, stable per-variant VRS digest to search or join on, and nothing clean to hand out for export.
- Pre-mapped VRS is not deterministically a property of the measurement; it is contingent on an external reference-projection pipeline that has nothing to do with the pre-mapped object itself.
A pre-mapped VRS allele can be constructed from data MaveDB already holds (the variant's hgvs_nt/hgvs_pro plus the target sequence) for the vast majority of variants, without any reference projection. It cannot always be built — the canonical failure is an accession-based intronic variant, where we lack the local intron sequence needed for precise sequence identity — but those are the minority and must be recorded as such rather than silently dropped.
Proposed behavior
Introduce a MaveDB-owned pre-mapped VRS minting step that runs synchronously during variant creation, for every variant, decoupled from dcd-mapping.
Value on the variant. Add columns to Variant carrying only the minted value:
pre_mapped_vrs (JSONB) — the pre-mapped VRS allele object.
pre_mapped_vrs_digest (string, indexed) — the ga4gh digest; the joinable/searchable identifier that is the primary goal here.
pre_mapped_vrs_version (string) — the VRS spec version used to mint.
Status/rationale in the event log. Do not add per-job status/error columns to Variant. Instead record each minting observation in the existing append-only AnnotationEvent log, following the established "value in the domain table, disposition + why + when in the log" pattern:
- A new
AnnotationType, PRE_MAPPED_VRS, distinct from VRS_MAPPING (which remains the dcd reference-projection step). Subject is the variant, so it joins the variant-subject annotation types.
disposition + reason capture outcome: successful mint → present; structural inability to build (e.g. accession-based intronic variant, no local sequence) → not_applicable; sequencing-resolution/normalization error → failed.
- Reuse existing
EventReason values where they genuinely apply; add new EventReason value(s) for the pre-mapped-specific structural gaps (e.g. accession-based intronic with no resolvable sequence) where none fit.
Minting mechanism. Port the pre-mapped VRS construction logic that currently lives in the dcd-mapping implementation into MaveDB:
- Non-accession targets: MaveDB already stores the full target sequence, so compute the Refget
ga4gh:SQ digest locally and build the allele on the stored hgvs_nt/hgvs_pro.
- Accession-based targets: resolve the reference (SeqRepo/CDOT) to obtain the sequence. Where the required sequence is unavailable (e.g. intronic positions outside what we can resolve), emit a not_applicable event and mint no value.
SeqRepo write-on-mint. On a successful mint, register the target sequence into the local SeqRepo instance so its ga4gh:SQ digest resolves for downstream consumers. This must be idempotent (re-minting the same target sequence is a no-op).
Coexistence with dcd-mapping (phased). For now, keep MaveDB's pre-mapped value separate from dcd-mapping's MappingRecord.pre_mapped; do not change the mapping process. The intended end state (follow-up, out of scope here) is that dcd-mapping stops minting pre-mapped VRS entirely and MaveDB's variant-creation-time value becomes authoritative.
Backfill. Provide a one-off backfill (a manual migration, in the same style as the existing allele-substrate migration) that mints pre-mapped VRS and writes the corresponding PRE_MAPPED_VRS annotation events for all existing variants.
Acceptance criteria
Variant has pre_mapped_vrs (JSONB), pre_mapped_vrs_digest (indexed), and pre_mapped_vrs_version columns.
- Creating a score set's variants mints a pre-mapped VRS for every variant synchronously during variant creation, with no dependency on dcd-mapping having run.
- For a non-accession target, minting succeeds using the DB-stored target sequence with no dcd-mapping call, and
pre_mapped_vrs_digest is populated with a valid ga4gh digest.
- For an accession-based intronic variant that cannot be built,
pre_mapped_vrs* columns are left null and a PRE_MAPPED_VRS AnnotationEvent is written with a not_applicable disposition and a reason identifying the structural gap.
- On a genuine minting/normalization error, a
PRE_MAPPED_VRS AnnotationEvent is written with a failed disposition and an error reason; the variant creation as a whole does not fail because one variant could not be minted.
- Every minting attempt (present, not_applicable, or failed) produces exactly one current
PRE_MAPPED_VRS annotation event for that variant, surfaced through v_current_annotation_events.
- A successful mint registers the target sequence into SeqRepo idempotently; re-running mint for the same target sequence performs no duplicate write and does not error.
PRE_MAPPED_VRS is added to the variant-subject annotation types and passes the ck_annotation_event_subject polymorphic-subject constraint (variant_id set, allele_id null).
- A backfill migration mints pre-mapped VRS and writes
PRE_MAPPED_VRS annotation events for all pre-existing variants; variants for which a value cannot be built get a not_applicable/failed event rather than being skipped silently.
- The dcd-mapping pipeline and
MappingRecord.pre_mapped are unchanged by this work.
- Tests cover: a successful non-accession mint, a successful accession-resolved mint, an accession-intronic not_applicable case, a minting-error failed case, digest determinism (same input → same digest), and idempotent SeqRepo registration.
- A follow up issue is created to remove pre-mapped VRS generation from the dcd-mapping pipeline and harmonize all pre-mapped VRS references to the canonical value minted during variant creation.
Implementation notes
- New enum member
AnnotationType.PRE_MAPPED_VRS; add it to VARIANT_SUBJECT_TYPES so the polymorphic-subject CHECK admits it. Extend the CHECK constraint accordingly via migration.
- Add
EventReason value(s) for the pre-mapped structural-gap and error cases; reuse existing reasons only where they meuplicating vocabulary).
- The submitted HGVS lives on the variant as
hgvs_nt / hgvs_pro / hgvs_splice; these are the minting inputs (distinct from mapper-derived HGVS on alleles).
- Do not route pre-mapped VRS through the
alleles dedup table — pre-mapped is a per-measurement property and the alleletended for the (post-mapped) reference projection; using it here would be non-idiomatic.
- Minting is synchronous within the existing variant-creation job loop, before mapping is queued; a per-variant failure must be isolated (recorded as a failed event) and must not abort creation of the rest of the score set.
- Follow the existing manual-migration pattern (as used for the mapped-variants → allele-substrate migration) for the backfill.
Open questions / follow-ups
- API surface (not settled): at minimum, expose
pre_mapped_vrs and pre_mapped_vrs_digest on the variant view model. Whether/how to surface pre-mapped values (and their annotation-event disposition/reason) through the annotation view, the published-variants materialized view, or a coverage statistic is deferred and should be decided before consumer-facing work.
- Phase 2 (separate issue): retire pre-mapped VRS minting from the dcd-mapping repo and make MaveDB's variant-creation-time value authoritative, removing the
MappingRecord.pre_mapped producer.
- Confirm the local SeqRepo instance is writable in all deploy environments where variant creation runs.
Summary
Give every
Varianta stable, pre-mapped VRS allele object plus its ga4gh digest, minted by MaveDB during variant creation, instead of only for variants that flow through the dcd-mapping service. The digest becomes a universal, joinable identifier for search and export; the value lives onVariant, and the disposition/reason lives in the annotation event log.Problem
Today, pre-mapped ("assay-level") VRS is a byproduct of invoking dcd-mapping. On the allele-centric branch it lands on
MappingRecord.pre_mapped, and aMappingRecordis only created for variants in score sets we actually send to dcd-mapping, and only when that service succeeds in constructing the pre-mapped allele.Consequences:
A pre-mapped VRS allele can be constructed from data MaveDB already holds (the variant's
hgvs_nt/hgvs_proplus the target sequence) for the vast majority of variants, without any reference projection. It cannot always be built — the canonical failure is an accession-based intronic variant, where we lack the local intron sequence needed for precise sequence identity — but those are the minority and must be recorded as such rather than silently dropped.Proposed behavior
Introduce a MaveDB-owned pre-mapped VRS minting step that runs synchronously during variant creation, for every variant, decoupled from dcd-mapping.
Value on the variant. Add columns to
Variantcarrying only the minted value:pre_mapped_vrs(JSONB) — the pre-mapped VRS allele object.pre_mapped_vrs_digest(string, indexed) — the ga4gh digest; the joinable/searchable identifier that is the primary goal here.pre_mapped_vrs_version(string) — the VRS spec version used to mint.Status/rationale in the event log. Do not add per-job status/error columns to
Variant. Instead record each minting observation in the existing append-onlyAnnotationEventlog, following the established "value in the domain table, disposition + why + when in the log" pattern:AnnotationType,PRE_MAPPED_VRS, distinct fromVRS_MAPPING(which remains the dcd reference-projection step). Subject is the variant, so it joins the variant-subject annotation types.disposition+reasoncapture outcome: successful mint → present; structural inability to build (e.g. accession-based intronic variant, no local sequence) → not_applicable; sequencing-resolution/normalization error → failed.EventReasonvalues where they genuinely apply; add newEventReasonvalue(s) for the pre-mapped-specific structural gaps (e.g. accession-based intronic with no resolvable sequence) where none fit.Minting mechanism. Port the pre-mapped VRS construction logic that currently lives in the dcd-mapping implementation into MaveDB:
ga4gh:SQdigest locally and build the allele on the storedhgvs_nt/hgvs_pro.SeqRepo write-on-mint. On a successful mint, register the target sequence into the local SeqRepo instance so its
ga4gh:SQdigest resolves for downstream consumers. This must be idempotent (re-minting the same target sequence is a no-op).Coexistence with dcd-mapping (phased). For now, keep MaveDB's pre-mapped value separate from dcd-mapping's
MappingRecord.pre_mapped; do not change the mapping process. The intended end state (follow-up, out of scope here) is that dcd-mapping stops minting pre-mapped VRS entirely and MaveDB's variant-creation-time value becomes authoritative.Backfill. Provide a one-off backfill (a manual migration, in the same style as the existing allele-substrate migration) that mints pre-mapped VRS and writes the corresponding
PRE_MAPPED_VRSannotation events for all existing variants.Acceptance criteria
Varianthaspre_mapped_vrs(JSONB),pre_mapped_vrs_digest(indexed), andpre_mapped_vrs_versioncolumns.pre_mapped_vrs_digestis populated with a valid ga4gh digest.pre_mapped_vrs*columns are left null and aPRE_MAPPED_VRSAnnotationEventis written with a not_applicable disposition and a reason identifying the structural gap.PRE_MAPPED_VRSAnnotationEventis written with a failed disposition and an error reason; the variant creation as a whole does not fail because one variant could not be minted.PRE_MAPPED_VRSannotation event for that variant, surfaced throughv_current_annotation_events.PRE_MAPPED_VRSis added to the variant-subject annotation types and passes theck_annotation_event_subjectpolymorphic-subject constraint (variant_id set, allele_id null).PRE_MAPPED_VRSannotation events for all pre-existing variants; variants for which a value cannot be built get a not_applicable/failed event rather than being skipped silently.MappingRecord.pre_mappedare unchanged by this work.Implementation notes
AnnotationType.PRE_MAPPED_VRS; add it toVARIANT_SUBJECT_TYPESso the polymorphic-subject CHECK admits it. Extend the CHECK constraint accordingly via migration.EventReasonvalue(s) for the pre-mapped structural-gap and error cases; reuse existing reasons only where they meuplicating vocabulary).hgvs_nt/hgvs_pro/hgvs_splice; these are the minting inputs (distinct from mapper-derived HGVS on alleles).allelesdedup table — pre-mapped is a per-measurement property and the alleletended for the (post-mapped) reference projection; using it here would be non-idiomatic.Open questions / follow-ups
pre_mapped_vrsandpre_mapped_vrs_digeston the variant view model. Whether/how to surface pre-mapped values (and their annotation-event disposition/reason) through the annotation view, the published-variants materialized view, or a coverage statistic is deferred and should be decided before consumer-facing work.MappingRecord.pre_mappedproducer.