Skip to content

epic: pristine vendor-neutral internal data model (MVP) #93

Description

@pskillen

Epic

Get the internal codeplug model to a pristine, format- and radio-agnostic state ahead of the MVP import → modify → export → write-to-radio loop, without regressing the OpenGD77/Baofeng 1701 round-trip. Radio-specific wire mapping is the adapter's job; the internal model owes nothing to any vendor. This is the umbrella for the data-model refactor that pays down OpenGD77 leakage so adding a second radio/format later is cheap.

Planning input / findings: docs/features/data-model/vendor-agnostic-review.md

Definition of done

  • Every internal foreign key is an internal UUID (no name-based FKs).
  • Every channel scalar is correctly typed (bool / number / enum), not an opaque OpenGD77 wire string.
  • Import provenance ("what we imported originally / most recently") lives in a per-entity meta field, not in load-bearing model fields.
  • Channel.number is gone from the model and assigned at OpenGD77 export.
  • vendorExtras renamed to opengd77Extras; vendor specifics live only at the adapter.
  • OpenGD77/1701 import → edit → export → re-import round-trip stays green throughout.

In-scope tickets

Also folded in under this epic (no separate child tickets): convert FKs to UUID (discriminated { kind: 'talkGroup' | 'contact'; id } refs), and move import provenance into per-entity meta + rename vendorExtrasopengd77Extras.

Locked decisions

  • Delivered as a phased epic across separate agent sessions; each phase is its own subplan + branch + PR, merged to main sequentially.
  • Dual-kind FK = discriminated ref { kind: 'talkGroup' | 'contact'; id }; TalkGroup and Contact stay separate entities.
  • scanSkip first-class; zoneSkip stays an OpenGD77 extra.
  • Field types: frequencies as integer Hz; power / squelch as percent with null = master; tones as a CTCSS/DCS string enum; colourCode / timeslot / dmrId / transmitTimeout nullable numbers/enums; rxOnly boolean.
  • aprsConfigName stays a string FK until APRS is modelled.
  • Vendor cardinality/limits belong at export only — never in model / mutations / validation / CRUD UI.

Phases

  1. Audit close-out + scaffold (docs/chore: audit OpenGD77/1701 import-export implementation against reference docs #91): land review doc, create the OpenGD77 export-issues tracker, fix the stale persistence schema-version doc.
  2. Drop Channel.number (refactor: drop channel number from internal model (assign at export) #53).
  3. Typed channel fields + shared test builders (refactor: rationalise channel data model field types and vendor mappings #52).
  4. Import provenance → per-entity meta + opengd77Extras rename.
  5. FKs by UUID (discriminated refs).
  6. First-class naming + export-name composition (feat: first-class callsign, display name, and export name composition #54).

Each phase bumps CODEPLUG_SCHEMA_VERSION with a migration + fixture.

Tracking docs

Related / out of scope

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions