Two ingesters carry their own Maidenhead regex and they disagree. One of them is correct by accident.
cmd/pskr-collector/main.go:81 — ^[A-R]{2}[0-9]{2}([a-x]{2})?$. Requires a lowercase subsquare and caps the locator at 6 characters. On a non-match it sets the field to "" (lines 208-213), so a rejection is indistinguishable from a station that sent nothing.
cmd/contest-ingest/main.go:55 — ^[A-R]{2}[0-9]{2}([A-X]{2})?$. Requires an uppercase subsquare. It works only because line 330 calls strings.ToUpper() first. It also drops a failing header grid silently.
Measured impact of the PSKR pattern: 6,746,970,499 rows hold no usable grid pair. Valid input it discarded includes uppercase subsquares, 8- and 10-character locators, and lowercase fields. Collection began 2026-02-10 and the erasure ran the whole time.
What to build: one shared validator package, called by both ingesters and by the reference-tier editor. Per ADIF 3.1.7:
GridSquare is 4, 6 or 8 characters; GridSquareExt carries the 2 or 4 beyond that; GridSquareList is comma-delimited.
- Validation is case-insensitive on input; normalise on store.
- Never drop, never blank. A failing locator is stored as received with a validity flag and a reason, so an audit can count failures by cause. This rule is what turns a regression into a visible metric instead of seven months of silent loss.
- Store at full precision; derive
grid_4/grid_6 from the stored value rather than storing a truncated one.
Blank-on-invalid is the part that made this unrecoverable, so the flag/reason columns need a coordinated schema change alongside the validator.
Design: the ADIF-Anchored Dimensions record, "Future-proofing grids — one contract, both paths".
Two ingesters carry their own Maidenhead regex and they disagree. One of them is correct by accident.
cmd/pskr-collector/main.go:81—^[A-R]{2}[0-9]{2}([a-x]{2})?$. Requires a lowercase subsquare and caps the locator at 6 characters. On a non-match it sets the field to""(lines 208-213), so a rejection is indistinguishable from a station that sent nothing.cmd/contest-ingest/main.go:55—^[A-R]{2}[0-9]{2}([A-X]{2})?$. Requires an uppercase subsquare. It works only because line 330 callsstrings.ToUpper()first. It also drops a failing header grid silently.Measured impact of the PSKR pattern: 6,746,970,499 rows hold no usable grid pair. Valid input it discarded includes uppercase subsquares, 8- and 10-character locators, and lowercase fields. Collection began 2026-02-10 and the erasure ran the whole time.
What to build: one shared validator package, called by both ingesters and by the reference-tier editor. Per ADIF 3.1.7:
GridSquareis 4, 6 or 8 characters;GridSquareExtcarries the 2 or 4 beyond that;GridSquareListis comma-delimited.grid_4/grid_6from the stored value rather than storing a truncated one.Blank-on-invalid is the part that made this unrecoverable, so the flag/reason columns need a coordinated schema change alongside the validator.
Design: the ADIF-Anchored Dimensions record, "Future-proofing grids — one contract, both paths".