Repository navigation
California SBCs: a hand-built manifest, Terms-gated crawling, and manual import - #39
Merged
Merged
Conversation
CMS's California file has no SBC links, so sub-project 2 links each plan by hand and reads its SBC only as the carrier allows. This commit records that decision and the carriers. ADR 0026 and the design spec. The rule that shapes everything: a carrier's website Terms govern, as they already did for Covered California. Kaiser, Blue Shield, Western Health Advantage and Anthem ban robots or scrapers in their Terms although robots.txt allows us, and L.A. Care appears to; they are manual-only, with Valley, whose host blocks bots. IEHP, Molina, Sharp and Balance by CCHP are crawled. Health Net is recorded, disabled. The registry gains mandated_disclosure: an SBC is published because federal law requires it, not under a licence, so the status is allowed only for an sbc_host and only with commercial use under review. sbc_host_for finds a link's entry by the longest prefix. Every scope URL must now be https://host/..., so a prefix can never also match a look-alike host. ADR 0026 amends 0013 (Terms can refuse us; a person's browser download is not the crawler working around a refusal), 0019 (manual documents are never re-requested) and 0025 (the new status).
…t by hand Every California plan had no SBC link, because CMS's file has none. A committed manifest (src/ingestion/sbc/manifests/ca-2026.csv) now gives 114 of the 190 plans a link, to 58 documents. Each row was found and checked by hand; the evidence is in docs/findings/ca-sbc.md. load_manifest checks the file on its own: the plan ID, the year, a safe HTTPS link, and a California registry entry covering it. apply_manifest is authoritative: a plan with no row, or whose carrier's entry is disabled, loses its link, which is how a carrier is removed. make ingest-ca-plans applies it after every load, and make check-sbc-manifest lists what a person should look at after an ingest. make ingest-sbc STATES=CA works, gated by the registry: a crawl carrier is fetched with every existing check, a manual one is never requested, and an unregistered or disabled link is skipped. The 30 API states are read as before. First run: the 19 IEHP, Molina and Sharp SBCs all read ok, with no name mismatches; 39 documents await a manual import. make import-sbc reads a PDF a person downloaded in a browser. The link must be a plan's and its carrier enabled, and the file a PDF under the size cap. The file is copied into the link's cache path, archiving any different one, and parsed with no request. It is recorded as acquisition = 'manual' (migration 3b1d6e2a9c47), kept through re-parses, never refreshed, and reported for re-import if its file goes missing. sbc-report counts read documents by acquisition.
make ingest-sbc's first line gave "N already current" as every document it was not reading, which included the recorded failures that the next line reported as "M recorded failures skipped". A blocked document was counted twice, and a run over a host that refuses us read as mostly healthy. It now counts a recorded failure once, as skipped. This predates the California work; the code review of sub-project 2 found it.
California's links are chosen by hand, one document per base plan: the standard (-01) version's. People who qualify for cost-sharing reductions or American Indian and Alaska Native cost sharing pay less than that document shows, and nothing in it says so. When plan_coverage quotes a filed-rate state's plan, the answer now opens with a server-written notice saying so. plan_coverage returns each plan's state to decide it. It uses the prior-year notice's mechanism, for the same reason: a first version put a note in the tool result and asked the model to include it, and in a live question about Sharp's and Molina's Silver 70 plans the model left it out. API-state plans are unchanged, since nothing has been checked about which variant their links point at.
… commands docs/findings/ca-sbc.md records the per-carrier research behind ADR 0026: - where each carrier publishes; - its Terms on automated access, quoted from the pages; - its robots.txt; - how each manifest row was checked; - which requests scripts made before the Terms were read; - the first run: 19 of 190 plans read, 95 awaiting a manual import, 76 with no link, and the ranking eval at 98.7%. The California runbook gains the yearly SBC routine: re-check each carrier's robots.txt and Terms before any request, write the manifest, apply it, crawl, download the manual carriers' SBCs in a browser, import them, and check. The SBC runbook says how imported documents behave in the monthly one. The README documents apply-sbc-manifest, check-sbc-manifest and import-sbc, and the registry's new status.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every California plan loaded from CMS's state-based exchange PUF (ADR 0024) had no SBC link, because the PUF's SBC column is empty. So every California coverage question ended with "no Summary of Benefits and Coverage link is listed for this plan". The SBC pipeline had three gaps:
Decisions (ADR 0026, amending 0013, 0019 and 0025)
Links come from a hand-built manifest. Carriers publish their SBCs in very different ways, and their pages print no HIOS IDs, so a person finds and checks each link.
Website Terms govern, as for Covered California. A carrier whose Terms ban robots or scrapers is manual-only, even where
robots.txtallows us.A new registry status,
mandated_disclosure. An SBC is published because federal law requires it, and that is not a licence. The status is allowed only for ansbc_host, and always withcommercial_use = "review", because nearly every carrier's Terms limit use to personal or non-commercial purposes. A commercial launch needs a legal review of these entries.Base-plan SBC only. Answers say so.
Implementation (5 commits)
sbc_hostentries, each with verbatim Terms evidence, its robots outcome, its access and how to remove it.sbc_host_formatches the longest prefix. Every scope URL must now be anhttps://host/…prefix.src/ingestion/sbc/manifests/ca-2026.csvlinks 114 of 190 plans to 58 documents.make apply-sbc-manifestvalidates, then applies. It is authoritative: a plan with no row, or on a disabled host, has no link.make ingest-ca-plansalso runs it after each load.make check-sbc-manifestlists what a person should look at.make ingest-sbc STATES=CAis gated by the registry:crawlis fetched,manualis never requested, and unregistered or disabled links are skipped.make import-sbcreads a PDF a person downloaded, with no request made. It is recorded asacquisition = 'manual'(migration3b1d6e2a9c47) and never re-requested.ingest-sbccounted a recorded failure both as "already current" and as "skipped". It is now counted once.docs/findings/ca-sbc.md, the runbook sections, the README and CHANGELOG.Validation
make check: 643 tests pass with 94.1% coverage.alembic checkis clean, and bandit and pip-audit report nothing.test_sbc_manifest,test_sbc_import(a mock fails the test on any network request), California gating intest_sbc_ingestandtest_sbc_refresh, and additions totest_registry,test_sbc_report,test_ca_puf_load,test_tools,test_plan_coverage,test_ingestion_plansandtest_sbc_fetch.apply-sbc-manifest: 114 plans linked to 58 documents.ingest-sbc STATES=CA: 19 of 19 crawlable documents readok, and 39 are awaiting manual import.check-sbc-manifest: no name mismatches.sbc-report STATES=CA VERIFY=1: no missing or changed files.eval_sbc_ranking --year 2026: 1,303 of 1,320 (98.7%; the floor is 97%). IEHP, Molina and Sharp each scored 20/20.Still to do before merge: the manual carriers' 39 SBCs are downloaded in a browser and imported. Any manifest row that fails, since Anthem's links are inferred and L.A. Care's and Valley's come from search results, is fixed in a further commit, and the findings counts are updated.
Security, database and API impact
fetch.unsafe_reason(HTTPS, public host) and be covered by a registry entry.data/sbc/.data/stays gitignored and no PDF is tracked. No file is ever deleted (ADR 0016).3b1d6e2a9c47addssbc_documents.acquisition(String(8), NOT NULL, default'crawl', checked). It is additive and reversible.plan_coverageresults no longer carry anote; the notice is prepended server-side instead.docs/findings/ca-sbc.md, and none of those files is used.Known follow-ups