Research date: 2026-07-13. The organizations named in this file illustrate the domain and possible technical use cases; none is affiliated with, endorses, or uses this project.
Existing organizations already do the hard part of trans ID-document guidance — the writing, legal review, plain language, community trust, and, in Namesake's case, a daily extracted-text monitor for canonical-source PDFs. Freshness is therefore not an untouched category. The working hypothesis is that no public offering yet combines a multi-jurisdiction source registry, dated verification and fetch eligibility, heterogeneous text evidence, independent review/correction, named gaps/run health, and a public no-reader-tracking feed. The repository exists to test that combined contract and possible integration with existing editorial or monitoring workflows, not to replace them.
Building a 52nd guidance website would be the obvious move and the wrong one. The world does not need another page telling a trans person what documents to bring; it needs the four pages that already exist to be right this week.
There are two live hosts, both free and both requiring nothing of you.
| Base URL | Status | Use it when |
|---|---|---|
https://raw.githubusercontent.com/ChelseaKR/id-churn-sentinel/main/docs/ |
Live mirror. | You want the repository's committed bytes directly. No build, CI, Pages, or account is involved. |
https://chelseakr.github.io/id-churn-sentinel/ |
Live canonical host. | You want the human-readable site, canonical feed URLs, or browser-friendly content types. Pages serves main / docs directly. |
Why the published output is committed, and why there is no CI deploy. This repository's owner has an account-wide GitHub Actions spending limit, so an Actions-driven Pages build would simply never run — and a feed that only exists once somebody else's billing system agrees to run a job is a feed that does not exist. So the artifacts are committed and served from the branch, which is also why they live in docs/ (branch-based Pages serves / or /docs, and nothing else). See docs/README.md.
The endpoint paths are identical under both bases, so switching from one to the other is a change to a base URL and nothing else:
BASE=https://chelseakr.github.io/id-churn-sentinel
# or use the raw mirror:
# BASE=https://raw.githubusercontent.com/ChelseaKR/id-churn-sentinel/main/docs
curl -s "$BASE/changes.json" # the versioned JSON feed — integrate against this
curl -s "$BASE/feed.xml" # RSS 2.0, every jurisdiction
curl -s "$BASE/changes-us-tx.json" # just Texas
curl -s "$BASE/feed-us-tx.xml" # just Texas, as RSS
curl -s "$BASE/sources.json" # registered candidates, eligibility, and named gaps
curl -s "$BASE/status.json" # persisted watch health; not the page-build time
curl -s "$BASE/schema/changes-v2.schema.json" # the normative shape of changes.json
curl -s "$BASE/schema/status-v1.schema.json" # the normative shape of status.jsonEverything below is published to a static URL and consumable with no account, no API key, no registration, and no email address:
| Artifact | Path | What it is |
|---|---|---|
| The site | index.html |
The human front door: registered candidates, exact attempt eligibility, run health, gaps, and the reviewed-change log. No JavaScript and no third-party request of any kind are tested properties; full WCAG 2.2 AA audit and remediation remain a V1 gate, not a current conformance claim. |
| The JSON feed | changes.json |
The versioned JSON feed. This is the one you integrate. Formal schema: docs/schema/changes-v2.schema.json. |
| The RSS feed | feed.xml |
RSS 2.0. Point any reader, Slack channel, or Zapier at it and a human sees new changes as they land. |
| One feed per jurisdiction | changes-us-tx.json · feed-us-tx.xml |
An org that serves one state is not made to consume all 52. us-tx for Texas, us-dc for DC, plain us for the federal bucket (passport, SSA, Selective Service). |
| The inventory | sources.json |
Version 2 exposes every registered candidate, its dated attempt_eligible decision and reasons, fetch-policy outcome, and every named gap. Registration is not represented as monitoring. |
| Run health | status.json |
Last attempted and last successful watch, exact eligible/attempted/successful/unmeasured source-ID sets, completeness, and staleness. generated_at is only when this file was rendered. |
| The schema | schema/changes-v2.schema.json |
JSON Schema 2020-12. Build against this, not against our source code. |
| The health schema | schema/status-v1.schema.json |
Closed JSON Schema 2020-12 contract for status.json. |
Every item is a machine-observed change a named human reviewed and confirmed. Source authority is earned only when its source_verification.status is verified and the verification is in date. HTML/text items carry the changed passage; PDF and other binary items in the current alpha carry an explicit byte-change notice because extracted-text passage diffs are not implemented. Nothing unreviewed is ever published.
0 of 156 sources are human-verified. Every URL in our registry was fetched by our crawler and had its title read — a machine fact about a socket. No human has confirmed that any given entry is the official page it claims to be, and a machine cannot establish that: courts.oregon.gov serves a soft 404 (HTTP 200, body titled "404 Page Not Found") and ecfr.gov serves a bot-wall titled "Request Access" (also HTTP 200). So:
| You may rely on | You may not rely on |
|---|---|
| The change records' machine observation and named review receipt. For text/HTML, each carries the changed passage; for binary content, it says only that bytes changed. Hash evidence remains reproducible while the relevant snapshots are among the newest five retained by the alpha. | The registry as a directory of official pages. It is a list of candidates. Do not republish our URLs as "the official page for X" unless source_verification.status is verified and the verification is still in date. |
| The gaps. Every (jurisdiction, document class) pair we do not watch is a named gap with the host that refused us. | Our silence. An empty feed means no human has confirmed a change. It is not a claim that nothing changed. |
verification_status being present, always. It is a field on every source in every artifact, and a merge-blocking gate asserts it on the published bytes. |
verification_status: "unverified" meaning "probably fine". It means nobody has looked. |
Read it in one line, and put it in your pipeline:
# every source we have NOT had a human confirm — today, that is all of them
curl -s $BASE/sources.json | jq '.sources[] | select(.verification_status != "verified")'
# every source the service may actually attempt — today, this returns none
curl -s $BASE/sources.json | jq '.sources[] | select(.attempt_eligible)'
# the exact current denominator and why entries are excluded
curl -s $BASE/sources.json | jq '.coverage | {eligibility_as_of, attempt_eligible, ineligibility_reasons}'
# the counts, straight from the feed you are already polling
curl -s $BASE/changes.json | jq '.registry_verification'If you map a page of yours to one of our source_ids, map it to the URL you already trust, not to ours — and use our feed as an alarm on that URL, which is the job it is actually good at. When the burn-down finishes, verification_status flips to verified with the name of the person who confirmed it and the date they did, and this section shrinks.
Every snippet below uses $BASE — either of the two base URLs above. Nothing here needs a key, an account, or a signup.
1. Poll the JSON. That is the whole integration.
# every confirmed change, newest first
curl -s $BASE/changes.json | jq '.changes[]'
# only the substantive ones, only in Texas
curl -s $BASE/changes.json \
| jq '.changes[] | select(.significance=="substantive" and .jurisdiction=="TX")'
# or skip the filtering: subscribe to the state you actually serve
curl -s $BASE/changes-us-tx.json | jq '.changes[]'2. Dedupe on id. It is deterministic in (source_id, previous_hash, new_hash), so a re-run cannot hand you the same change under a new key, and an id cited in an email six months ago still resolves. Store it. Do not re-key on our timestamps.
3. Map your pages to source_ids, once.
curl -s $BASE/sources.json | jq '.sources[] | {source_id, jurisdiction, document_class, url}'4. Read the gaps before you trust the silence.
curl -s $BASE/sources.json | jq '.gaps[] | {jurisdiction, document_class, reason}'5. Or do none of this and put the RSS in a Slack channel. For a name-change clinic that is genuinely the right integration, and it costs nothing.
RSS is the zero-engineering path, and for most legal-aid orgs it is the right path. There is no push, no webhook, and no subscription: you poll a static file. Nobody is told that you did.
# the whole country
curl -s $BASE/feed.xml
# Texas only. An org that serves one state should never have to consume all 52.
curl -s $BASE/feed-us-tx.xml
# the federal bucket — passport, Social Security, Selective Service
curl -s $BASE/feed-us.xml- The slug is
us-+ the lowercased jurisdiction:feed-us-tx.xml,feed-us-ny.xml,feed-us-dc.xml. The federal bucket is plainfeed-us.xml. Both.xml(RSS) and.jsonforms exist for all 52. - Every jurisdiction's feed exists right now, whether or not it has any items yet. A URL that only appears the day of the emergency is a URL nobody was subscribed to. Point your reader at it today.
- Paste the URL into Slack, Feedly, Thunderbird, Zapier, or a cron job. Slack's
/feed subscribe <url>is a complete integration for a name-change clinic, and it takes about fifteen seconds. - A polite cadence is weekly, which is how often the watcher itself runs. Polling every minute costs you nothing and tells you nothing new.
- Deduping in RSS is on
<guid>. An active observation uses the same permanentidas JSON. A later correction or withdrawal uses a stable, hash-derived lifecycle-event GUID and its lifecycle decision time, so feed readers deliver the correction instead of suppressing it as an already-seen item (isPermaLink="false"— these are identifiers, not URLs). JSON keeps the original observationidand exposes lifecycle fields separately. - Each item's
<category>elements carry the jurisdiction, document class, machine-observedkind,publication-status:<status>, andsource-verification:<status>— so a pipeline can filter RSS without parsing prose. - An empty feed is a correct feed. It has zero
<item>elements and an XML comment saying it is empty rather than broken. Do not alert your team on it. See below.
| Field | Meaning |
|---|---|
id |
Permanent dedupe key. Deterministic; safe forever. |
source_id |
The registry entry that moved. Join against sources.json. |
jurisdiction |
Two-letter state, DC, or US for federal (passport, SSA, Selective Service). |
document_class |
birth_certificate · drivers_license · court_order_name_change · passport · social_security · selective_service. A closed set. |
url |
The registry URL that changed. Treat it as a candidate unless source_verification.status is verified and in date; then it is the government page the named verifier confirmed for this scope. Go and read it. |
observed_at |
When our crawler saw it — not when the agency made the change. A page can sit changed for a week before our weekly pass sees it, and we will never claim otherwise. |
previous_hash / new_hash |
For HTML/text, sha256 of normalized text; for PDF/other binary content, sha256 of raw bytes. The alpha keeps the newest five snapshots per source, so this is a bounded recent evidence window, not a months-long archive. new_hash is "" for possibly_removed — there is no new content, and inventing a hash for bytes we never received would be a lie. |
diff_excerpt |
For HTML/text, the passage that changed. For a PDF or other binary source in the current alpha, an explicit notice that the bytes changed and no text diff is available. Extracted-text PDF diffs are a V1 gate. |
kind |
What the machine observed. content_drift = we fetched it and the text hashed differently. possibly_removed = we could not fetch it at all, N times running. |
significance |
What a human judged. editorial or substantive. Never machine-set. |
review_status |
Always confirmed. Unreviewed drift and dismissed noise never reach you. |
reviewer |
The name of the human who stands behind the item. Never null, never "automated". |
review_note |
Bounded public observation copy. Free-form reviewer rationale is private and never serialized. |
independent_review_status / independent_reviewer / independent_reviewed_at |
confirmed plus a distinct named reviewer and time for substantive observations; null for editorial observations. A returned high-impact decision never publishes. |
publication_status |
active, corrected, or withdrawn. Corrected and withdrawn records remain visible. |
superseded_by / lifecycle_reason / lifecycle_actor / lifecycle_at |
The acyclic replacement link and controlled public decision receipt for a correction or withdrawal; empty/null while active. |
source_verification |
Whether anyone has confirmed the URL in this item is the page it claims to be. {status, verifier, verified_at, note, statement}; note is a compatibility field that is always "" because free-form registry rationale is private. status is unverified | verified | rejected | withdrawn. A different human from reviewer, doing a different job: reviewer read the diff; source_verification is about the source. Today every registry value is unverified, so no newly reviewed observation can publish. The publisher enforces the same dated predicate as the watcher and rejects unverified, rejected/withdrawn, recheck-due, fetch-policy-ineligible, missing, or identity-mismatched sources. |
Two further top-level fields ship in changes.json and in every per-jurisdiction changes-us-xx.json:
| Field | Meaning |
|---|---|
registry_verification |
{scope, sources, human_verified, unverified, rejected, statement} — how much of the source list behind this document a human has actually confirmed. A URL is only authoritative for this contract when its item-level source_verification.status is verified and the verification is in date. |
sources |
The sources behind this feed, scoped the same way changes is, each with its verification_status. They ship inside the feed and not only in sources.json for one reason: the feed is currently empty, so a consumer polling only this file would otherwise learn nothing about the registry's status and would assume the URLs behind it had been confirmed. They have not been. |
unreviewed— a machine saw bytes move. You will never see this; it is withheld by a merge-blocking gate.dismissed— a human looked and decided it was noise (a nav reshuffle, a rotating footer). You will never see this either. Reviewed noise is still noise.confirmed— a named human looked at the diff and decided it was worth your attention. This is the only thing that reaches you, andsignificancetells you whether they thought it waseditorial(wording, layout, a dead link) orsubstantive(the page now says something different about the process).
possibly_removed deserves its own sentence, because it is the item most likely to be misread. It does not say a page was taken down. It says: we failed to fetch this N consecutive times, here is the literal error, and a human confirmed that is worth telling you. Removed, blocked, and down are three different worlds, and the tool refuses to choose between them.
- What the law is. A change to a web page is not a change to the law, and a hash comparison cannot read law. That is your job — you have the writers, the legal review, and the community trust. This is the monitor underneath your work, not a replacement for it.
- What a change means, without a human's name on it. Auto-classification is forbidden in four independent enforcement layers and a merge-blocking gate (
docs/RESPONSIBLE-TECH-AUDITS.md§B). A machine announcing "Texas substantively changed its gender-marker policy" on the strength of a sha256 comparison would be believed, and would sometimes be wrong. - What anyone should do. No advice, ever. Not in the feed, not in a "helpful summary" field.
- That nothing changed. An empty
changesarray means no human has confirmed a change yet. It is not a claim that nothing moved. Policy can change by an internal directive that never touches a web page, and this tool sees none of it. - Who reads this feed. We do not know and we cannot find out. See below.
The normative document is docs/schema/changes-v2.schema.json — JSON Schema 2020-12, and a merge-blocking test asserts that the schema and the code agree about every field and every enum, and that real published output validates against it. Version 1 remains published as the pre-correction compatibility contract.
It is published at the same base as the feed, so you can validate in CI without vendoring anything:
curl -sO $BASE/schema/changes-v2.schema.json
curl -s $BASE/changes.json > changes.json
check-jsonschema --schemafile changes-v2.schema.json changes.json # or any 2020-12 validatorValidate the per-jurisdiction documents against the same schema — changes-us-tx.json is the same shape as changes.json plus a jurisdiction field naming its scope.
The following is a complete schema-valid illustrative record. Its source is deliberately shown as verified; V1 will not publish the same record with an unverified, stale, or fetch-policy-ineligible source.
{
"schema_version": "2.0",
"generated_at": "2026-07-13T12:00:00+00:00",
"feed_url": "https://github.com/ChelseaKR/id-churn-sentinel",
"jurisdiction": "TX",
"disclaimer": "This illustrative feed reports a reviewed machine observation at a source a named human verified for this scope. It does not assert what the law is and is not legal advice.",
"registry_verification": {
"scope": "TX",
"sources": 1,
"human_verified": 1,
"unverified": 0,
"rejected": 0,
"statement": "One source is in scope and a named human verified it on 2026-07-10."
},
"changes": [
{
"id": "4ee6d95ecbc042c4",
"source_id": "tx-dps-change-dl-id",
"jurisdiction": "TX",
"document_class": "drivers_license",
"url": "https://www.dps.texas.gov/section/driver-license/how-change-information-your-driver-license-or-id-card",
"observed_at": "2026-07-11T09:04:11+00:00",
"previous_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"new_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"diff_excerpt": "@@ -1 +1 @@\n-bring a certified copy of the prior document\n+bring a certified copy of the court order",
"kind": "content_drift",
"significance": "substantive",
"review_status": "confirmed",
"reviewer": "Jane Doe",
"reviewed_at": "2026-07-12T14:20:00+00:00",
"review_note": "The reviewed passage changed; downstream legal and editorial review is required.",
"independent_review_status": "confirmed",
"independent_reviewer": "Morgan Lee",
"independent_reviewed_at": "2026-07-12T16:00:00+00:00",
"publication_status": "active",
"superseded_by": null,
"lifecycle_reason": "",
"lifecycle_actor": null,
"lifecycle_at": null,
"source_verification": {
"status": "verified",
"verifier": "Alex Rivera",
"verified_at": "2026-07-10",
"note": "",
"statement": "VERIFIED — Alex Rivera confirmed this URL for the stated jurisdiction and document class on 2026-07-10."
}
}
],
"sources": [
{
"source_id": "tx-dps-change-dl-id",
"jurisdiction": "TX",
"document_class": "drivers_license",
"url": "https://www.dps.texas.gov/section/driver-license/how-change-information-your-driver-license-or-id-card",
"authority": "Texas Department of Public Safety",
"verification_status": "verified",
"human_verified": true,
"verified_by": "Alex Rivera",
"verified_at": "2026-07-10",
"verification_statement": "VERIFIED — Alex Rivera confirmed this URL for the stated jurisdiction and document class on 2026-07-10.",
"reachable_by_our_crawler": true,
"notes": ""
}
]
}significance and reviewer are never machine-set — see docs/RESPONSIBLE-TECH-AUDITS.md §B.
- A major bump means a break. Version 2 adds independent-review and correction lifecycle fields; the v1 schema remains available for integrations that have not migrated. Pin the major and validate against its matching schema.
idis permanently stable for a given(source_id, previous_hash, new_hash)transition.review_statusis alwaysconfirmed. If you ever see another value, we broke a promise — open an issue.- The feed will never require a credential.
- Endpoint paths are stable.
changes.json,feed.xml,sources.json,status.json, their versioned schemas, andchanges-us-xx.json/feed-us-xx.xmlfor every jurisdiction. A per-jurisdiction feed exists whether or not it has items yet — a URL that only appears the day of the emergency is a URL nobody is subscribed to. - Run health is a separate fact. Read
status.jsonbefore interpreting feed silence. Itsgenerated_atnever means a watch succeeded; usestate,last_attempted_run, andlast_successful_run. The contract isschema/status-v1.schema.json. - A successful retrieval is not the same as an observation.
unmeasured_source_ids(schema 1.1) names every source whose fetch succeeded and produced no readable text — a client-rendered shell, an empty 200, a bot-wall. Those pages were not compared against anything, so for them the run is not evidence of no change, and a run holding one ispartialrather thanquiet.observed_source_countis the number actually compared. Do not compute a watched-page count fromsuccessful_retrieval_countalone:
# the sources this run could not read at all — for these, our silence means nothing
curl -s $BASE/status.json | jq '.last_attempted_run.unmeasured_source_ids'- The two base URLs are both supported, and the raw one is not going away. The raw base serves the committed bytes off the branch and needs nothing enabled; the Pages base serves the identical bytes. If a third host ever appears, the paths above will be identical there too — the base is the only thing you should ever have to change.
- A
feed_urlfield appears in every document. It is the project's canonical home, so an item that reaches someone out of context can be traced back. It is not a fetch endpoint — use the bases above.
As of the first baseline run (2026-07-13) the tool watches 152 candidate sources across 52 of 52 jurisdictions, and the feed contains zero items. The live endpoint above is the canonical full payload. This compact fixture is a complete schema-valid empty state with one unverified candidate source; it is not a claim that the aggregate registry contains only one source:
{
"schema_version": "2.0",
"generated_at": "2026-07-13T12:00:00+00:00",
"feed_url": "https://github.com/ChelseaKR/id-churn-sentinel",
"jurisdiction": "TX",
"disclaimer": "This illustrative empty feed contains no human-confirmed changes. Its source is an unverified candidate and is not authoritative guidance.",
"registry_verification": {
"scope": "TX",
"sources": 1,
"human_verified": 0,
"unverified": 1,
"rejected": 0,
"statement": "One candidate source is in scope and no named human has verified it."
},
"changes": [],
"sources": [
{
"source_id": "tx-dps-change-dl-id",
"jurisdiction": "TX",
"document_class": "drivers_license",
"url": "https://www.dps.texas.gov/section/driver-license/how-change-information-your-driver-license-or-id-card",
"authority": "Texas Department of Public Safety",
"verification_status": "unverified",
"human_verified": false,
"verified_by": "",
"verified_at": "",
"verification_statement": "UNVERIFIED — machine-checked, not human-confirmed. Do not treat this candidate as authoritative guidance.",
"reachable_by_our_crawler": true,
"notes": ""
}
]
}That is correct and it is deliberate. Every change the watcher detects is born unclassified / unreviewed and is held until a named human reviews it. None has been confirmed yet, so nothing is published — and no change was manufactured to make the feed look alive. feed.xml is valid RSS 2.0 with no <item> elements and an XML comment saying which of the two states it is in.
What an empty feed means: no human has confirmed a change yet.
What an empty feed does NOT mean: nothing changed at any watched source. Those are different sentences, and conflating them is precisely the wrong "no change" that this project treats as its primary safety failure. Silence from this feed is never evidence that a jurisdiction is unchanged — before you rely on it, read the 8 named gaps in sources.json (or on the published site), which say exactly which (jurisdiction, document class) pairs we do not watch and which host refused us.
Integrator guidance: treat changes: [] as a successful poll returning no new items. Pin on schema_version. Do not treat an empty changes array as an error condition, and do not alert your team on it.
Covers 50 states + DC + 5 territories + 5 federal document classes, and asks users to email in corrections: "Due to the ever-changing nature of state laws and policies, we are working to keep the ID Documents Center as up to date as possible. If you see something that needs updating, please contact us."
Illustrative use case: supplement the contact form with a queue. An integrator could map jurisdiction/document pages to independently trusted source_ids, poll changes.json, and investigate cited observations using its own editorial process. This is not a proposal to, relationship with, or representation about A4TE.
Implementation sketch: one scheduled job and one mapping table. That sketch was not validated with A4TE and is not a claim about its systems, costs, needs, or interest.
Volunteer-maintained since 2016, self-acknowledged incomplete (entries flagged "Help Us Find It"), no API, no export, no last-updated dates.
Illustrative use case: a dated research queue, not a content-freshness certification. An integrator could use changes.json to prioritize which mapped source pages to investigate. observed_at is only when this crawler saw the source content; it is not the agency's change date or a last-updated date for the library. This is not a proposal to, relationship with, or representation about Trans Lifeline.
Open-source and well-engineered. Namesake already runs a scheduled daily monitor for PDFs with canonical source URLs, compares extracted text with its local copy, emits changed-line diffs, and opens or updates an issue when drift appears.
Illustrative use case: any integration analysis would begin by assessing reuse of, or upstream contribution to, Namesake's monitor — not by assuming Namesake lacks monitoring. The unverified registry is not a head start on authoritative URLs. This is not a proposal to, relationship with, or representation about Namesake.
(Lambda Legal, TLDEF, Transgender Law Center, state legal-aid orgs, name-change clinics.)
Illustrative use case: a clinic could place a public RSS feed in an internal channel, inspect cited observations, and use its own qualified process to decide whether its materials need review. The per-jurisdiction feeds illustrate a low-effort technical path. No clinic is represented as using or evaluating this workflow.
The alpha changes.json is a reviewed record of when the crawler observed candidate-source content move. Text/HTML records include a passage diff; binary records currently do not. The newest-five snapshot window supports recent checking, but a durable longitudinal primary-source archive and months-later reproduction are V1 gates, not current claims. A journalist should treat a URL as authoritative only when its source verification is verified and in date, and should still inspect the source itself.
There is no SDK, no auth, no rate limit, no account, and no signup form. That is not minimalism; it is the mitigation.
Anyone who subscribes to a feed of trans identity-document law changes is, with high probability, a trans person or someone working directly with trans people. In the current US environment that list is a targeting artifact. It could be subpoenaed, breached, sold, or handed over, and there is no security control that makes holding it safe. So we do not secure the list. We never create it.
- No user model exists in the codebase. There is nothing to log in to.
- No tracking of any kind in the published bytes: no analytics, no beacon, no pixel, no cookie, no UTM parameter — and the published site additionally makes no third-party request at all: no CDN script, no external stylesheet, no web font, no image. Every external request is a request that tells a third party who is reading about trans ID law, and a page that surveils the people it claims to protect would be a disgrace.
- This is enforced, not promised.
test_the_feed_requires_no_account_and_carries_no_trackingandtest_the_published_site_makes_no_third_party_requestsassert it on the published bytes and run in the merge-blockingfeed_integritygate. If someone adds a font from Google, the build goes red. - There is nothing to subscribe to. Both consumption paths are you fetching a static file. No webhook, no mailing list, no push, no registration — and therefore no list of who reads this.
- Consequently we cannot report readership. We do not know who consumes the artifacts or how many readers there are. The artifact does not require or request that a reader identify itself; nothing in the repository observes a reader who does not do so.
The one honest limit, stated concretely rather than vaguely: the files are hosted on GitHub (chelseakr.github.io canonically and raw.githubusercontent.com as a mirror). GitHub's access logs exist, and they contain the IP address of anyone who fetches a file — including which per-jurisdiction feed they fetched, which is more revealing than the unscoped one, not less. We do not control those logs, we do not receive them, we cannot delete them, and no amount of care in this repository changes that.
What we do control, and do: the logs are not ours, are not enriched with any identity, and are not required in order to consume anything. There is no account to tie an IP to. If that residual risk matters for your threat model, fetch over Tor or a VPN, or mirror the artifacts once and serve them internally — nothing about the feed makes any of that harder, and mirroring is explicitly fine (AGPL-3.0-or-later).
Zero runtime dependencies, SQLite, and committed static artifacts keep technical upkeep low, but they do not create or imply an operating service, reviewer capacity, or a support commitment. The honest validation criterion stands: lack of institutional use is a negative result, and one organization integrating the feed on its own initiative is the M5 outcome (ROADMAP.md). No organization is represented as using the feed today.