Charlie KrugThe Build Log

← All posts

A state can't ship a law here until it proves the source

Statute Watch tracks US state privacy law by state and data type. Its build refuses to ship a state until an official source is registered, so an unsourced or mis-filed law fails CI instead of reaching you.

There is a failure mode worse than a crash: shipping a fact that is confidently wrong. A privacy tracker that files California's biometric rule under "geolocation," or lists a Washington statute as in effect when it is still sitting in committee, is not slightly off. It is misinformation with a clean UI, and the clean UI is what makes people trust it.

Statute Watch is a browsable dossier of US state privacy law: geolocation, biometric, data-broker, comprehensive consumer rights, plus health and children's data. Each tracked law is one record, tagged by state, by the data types it governs, and by where it sits in its lifecycle (introduced, passed, enacted, in effect), with a plain-English "what changed" and a link to the actual bill. There is no federal baseline, so fifty legislatures are each writing their own rules, and the signal you need is scattered across fifty bill-tracking sites and buried in statutory language nobody has time to read. The point of this tool is to let you ask "show me every effective biometric law" and get an answer in one click instead of a research afternoon.

Correctness is a build step, not a hope

The interesting decision here is that being wrong is treated as a build failure. State, category, and lifecycle stage are closed vocabularies, defined once and validated when the dataset loads. A record with a data type that isn't in the set, or a lifecycle stage spelled encated, doesn't render as a slightly-off card. It fails statute-watch validate, and CI runs validate on every push. You cannot merge a mis-categorized law, because the thing that would ship it refuses to build.

On top of that sits a provenance gate. A state only appears in the output once an authoritative official source is registered for it in sources.yaml. The build checks that every shipped state clears that bar and rejects the whole dataset if one doesn't. No official legislative record, no state. This is deliberately strict: the editorial judgment (deciding what counts, categorizing it, and writing the summary honestly) is the actual product, and the summaries are stored as data with each record rather than generated at render time, so a human can review the exact words that will ship. The pipeline's only job is to keep that reviewed dataset fresh, never to invent it.

Keeping it current without editing YAML blind

The refresh path is a three-step pipeline that treats the curated dataset as sacred until a human signs off. fetch pulls candidate bills from a source feed into a staging area and never touches the real data. diff reports how those candidates differ from what's live, sorted into new, advanced, and unchanged. merge --write folds the approved changes in and re-validates, structure and provenance both, before it writes a single byte. It will not leave behind a dataset that validate would reject.

The one detail I'm quietly proud of: fetch is offline by default. It reads a local feed file, so CI is deterministic and a scheduled rebuild produces byte-identical output from the same dataset. Live network fetching is opt-in behind a --network flag. Determinism first, freshness second.

The honest limitation, stated plainly: this is not a live scraper of all fifty legislatures. That's a later epic. v1 is a curated, correctly categorized slice with hand-written summaries, and it is explicitly not legal advice. Confirm any bill against its linked official source before you act on it. On the front end, the cards are server-rendered and the filtering is a thin JavaScript layer on top, so the page still works with scripts disabled, and the whole dataset ships as data.json if you'd rather have the raw records than my rendering of them.

Try it

Open Statute Watch, pick a state and a data type from the filters, and watch the grid narrow to exactly your slice. Click a card to read what the law actually requires and jump to the bill. If you'd rather audit the rules than trust them, the validator and the pipeline are all on GitHub.

Statute Watch is live. Free, in your browser, no signup.

This post is part of the build log: every app my automated factory ships gets written up here, honestly. Browse everything at apps.charliekrug.com. Comments are open below.

Comments

Loading comments…