Skip to content

feat: data-quality endpoint, and stop /coverage hiding stateless rows - #12

Merged
keonik merged 1 commit into
mainfrom
feat/data-quality
Sep 14, 2026
Merged

feat: data-quality endpoint, and stop /coverage hiding stateless rows#12
keonik merged 1 commit into
mainfrom
feat/data-quality

Conversation

@keonik

@keonik keonik commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Everything this reports is wrong in a way that raises no error. A search
still returns rows, an import still reports success, nothing appears in the
logs.

Production carried eleven distinct region codes — ON (Ontario), BE, IH,
PJ, a bare 0, a lowercase oh — and 985,634 addresses with no state at all.
None of it was visible anywhere. It surfaced only because /coverage happened
to group by region while being used for something unrelated.

GET /api/v1/admin/data-quality

Reports invalid region codes with a reason for each, blank region / county /
city / postcode counts, and coordinates outside a loose envelope around the US
(a zero pair, a dropped minus sign, a transposed lat/lng).

Two decisions

Classified in Go, not SQL. The set of valid state codes already lives in
utils.IsUSStateCode, and a second copy inside a query is how the two drift
apart.

Cached for 30 minutes. Every check is an aggregate over the whole address
table — the same per-request full-table scan the address search count query was
doing before it was fixed. An import invalidates it, as it does coverage.

A bug my own test caught

IsUSStateCode upper-cases before checking, so it happily accepts "oh". The
first version therefore classified the lowercase region as correct and never
reported it. A value only counts as correct if it is a real code and already
canonical — 'oh' and 'OH' are distinct keys to the uniqueness index, so a
case difference is a real defect, not a cosmetic one.

Also: /coverage was hiding the problem it revealed

It did COALESCE(NULLIF(region,''),'OH'), folding every blank region into the
Ohio bucket. That is the specific reason a million stateless rows went unseen,
and why the Ohio count read ~1M higher than reality (5.78M shown vs ~4.79M
actual). Blanks now report as (none), and the per-county drill-down no longer
absorbs them either.

🤖 Generated with Claude Code

Everything this endpoint reports is wrong in a way that raises no error. A
search still returns rows, an import still reports success, and nothing in the
logs says otherwise.

Production carried eleven distinct region codes -- ON (Ontario), BE, IH, PJ, a
bare 0, a lowercase oh -- and 985,634 addresses with no state at all. None of it
was visible anywhere. It surfaced only because /coverage happened to group by
region while being used for something else.

GET /api/v1/admin/data-quality reports invalid region codes with a reason for
each, blank region, county, city and postcode counts, and coordinates outside a
loose envelope around the United States. Admin-only, and cached for thirty
minutes: every check is an aggregate over the whole address table, and an
operator refreshing a dashboard should not re-scan 5.8M rows each time. An
import invalidates it, as it does coverage.

Regions are classified in Go rather than SQL because the set of valid codes
already lives in utils.IsUSStateCode, and a second copy inside a query is how
the two drift apart. Note IsUSStateCode upper-cases before checking, so it
accepts "oh" -- a value only counts as correct if it is a real code AND already
canonical, since 'oh' and 'OH' are distinct keys to the uniqueness index. The
first version of this missed that and reported the lowercase region as fine;
the test caught it.

Also fixes /coverage, which folded blank regions into the Ohio bucket with
COALESCE(NULLIF(region,''),'OH'). That is the specific reason a million
stateless rows went unseen and the Ohio count read about a million higher than
it was. Blanks are now reported as (none), and the per-county drill-down no
longer absorbs them either.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@keonik
keonik merged commit 114a923 into main Sep 14, 2026
3 checks passed
@keonik
keonik deleted the feat/data-quality branch September 14, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant