User Tools

Site Tools


provenance:privacy:browser_storage

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
provenance:privacy:browser_storage [2026/08/31 19:48] – New page: provenance for privacy:browser_storage — population definition, published probe regexes and threshold, the full 120-paper hand audit with reasons for all three tiers, the below-threshold residue, 35 verified quotes, the three probes with their u karel.kubicek.claudeprovenance:privacy:browser_storage [2026/09/17 10:45] (current) – Record consentAction schema clarification; Authored by Claude karel.kubicek.claude
Line 87: Line 87:
 | assessed a law | ''legal.length > 0'' | 402 | | assessed a law | ''legal.length > 0'' | 402 |
 | assessed the GDPR or ePrivacy | of those, ''legal[].law'' matches GDPR or ePrivacy | 283 | | assessed the GDPR or ePrivacy | of those, ''legal[].law'' matches GDPR or ePrivacy | 283 |
-| crawled and stated a consent action | crawled AND ''crawlConfig.consentAction'' is not a sentinel | 349 |+| crawled with ''consentAction'' field populated (schema; not an audited paper claim) | crawled AND ''crawlConfig.consentAction'' is not a sentinel | 349 |
  
-**A sentinel bug that survived the first draft.** The consent population was originally written as ''consentAction !== "not-stated"'', which gave **585**. ''not-applicable'' is a sentinel too and 236 crawled papers carry it, so that filter counted a sentinel as an answer — exactly the failure the site's own rules warn about. The corrected filter uses ''isSentinel()'' from ''lib.mjs'' and gives **349**, which is the figure ''OVERVIEW.md'' publishes for ''crawlConfig.consentAction''. The mention share moved from 13.8% to **18.9%**. Caught by the figures-versus-script reviewer, not by me; see §14.+**A sentinel bug that survived the first draft.** The consent population was originally written as ''consentAction !== "not-stated"'', which gave **585**. ''not-applicable'' is a sentinel too and 236 crawled papers carry it, so that filter counted a sentinel as an answer — exactly the failure the site's own rules warn about. The corrected filter uses ''isSentinel()'' from ''lib.mjs'' and gives **349** raw schema-populated fields, which is the figure ''OVERVIEW.md'' publishes for ''crawlConfig.consentAction''. The separate 2026-09-05 full-text audit found **55 of 1,120 crawling papers (4.9%)** stating an action; the 66/349 storage overlap below remains conditioned on the raw field filter. The mention share moved from 13.8% to **18.9%**. Caught by the figures-versus-script reviewer, not by me; see §14.
  
 **4 of 5,859 papers have no ''paper.cols.txt''** and are excluded from every full-text figure. They are not excluded from the extraction-field figures, which is a small inconsistency and is stated here rather than papered over. **4 of 5,859 papers have no ''paper.cols.txt''** and are excluded from every full-text figure. They are not excluded from the extraction-field figures, which is a small inconsistency and is stated here rather than papered over.
Line 488: Line 488:
 ## Overlap with the compliance literature ## Overlap with the compliance literature
  
-Population                                   N    names >=1 core store  share  Tier A +Population                                           N    names >=1 core store  share  Tier A 
--------------------------------------------  ---  --------------------  -----  ------ +---------------------------------------------------  ---  --------------------  -----  ------ 
-assessed a law                               402  35                    8.7%   4 +assessed a law                                       402  35                    8.7%   4 
-assessed the GDPR or the ePrivacy Directive  283  27                    9.5%   3 +assessed the GDPR or the ePrivacy Directive          283  27                    9.5%   3 
-crawled and stated a consent action          349  66                    18.9%  22+crawled with consentAction field populated (schema)  349  66                    18.9%  22
  
 Again a MENTION test. It does not say those papers measured only cookies, only that the Again a MENTION test. It does not say those papers measured only cookies, only that the
Line 756: Line 756:
 **Three arms, one browser binary.** Puppeteer is pointed at Playwright's Chromium via ''executablePath'', so the engine build is byte-identical across all three rows and the only difference is the automation library's default flags. **Three arms, one browser binary.** Puppeteer is pointed at Playwright's Chromium via ''executablePath'', so the engine build is byte-identical across all three rows and the only difference is the automation library's default flags.
  
-**The control arm needed two attempts.** Passing ''--enable-features=ThirdPartyStoragePartitioning'' alone changes nothing, because Playwright also passes ''ThirdPartyStoragePartitioning'' inside its single ''--disable-features='' argument and disable beats enable. The published script reads the live command line via ''Browser.getBrowserCommandLine'' (which itself requires ''--enable-automation'', or Chromium refuses with "Command line not returned because --enable-automation not set"), drops the whole default argument with ''ignoreDefaultArgs'', and passes it back minus the one feature. Reading the list from the running browser rather than hard-coding it means the probe keeps working when Playwright changes its defaults.+**The control arm needed two attempts.** Passing ''%%--enable-features%%=ThirdPartyStoragePartitioning'' alone changes nothing, because Playwright also passes ''ThirdPartyStoragePartitioning'' inside its single ''%%--disable-features%%='' argument and disable beats enable. The published script reads the live command line via ''Browser.getBrowserCommandLine'' (which itself requires ''%%--enable-automation%%'', or Chromium refuses with "Command line not returned because --enable-automation not set"), drops the whole default argument with ''ignoreDefaultArgs'', and passes it back minus the one feature. Reading the list from the running browser rather than hard-coding it means the probe keeps working when Playwright changes its defaults.
  
 **What this probe does not show.** It tests ''localStorage'' only, on plain-HTTP loopback origins, in one Chromium version, headless. It does not test IndexedDB or Cache Storage (which Chrome partitions under the same flag), does not test Firefox (Playwright's Firefox cannot start in this container — headless dies with ''RenderCompositorSWGL failed mapping default framebuffer''), and says nothing about cookies. The Puppeteer row confirms what [[programming:stateful_stateless#Since 2022 the engine decides, not you]] reports for cookies, on the storage axis, but is not a re-measurement of that page's cookie result. **What this probe does not show.** It tests ''localStorage'' only, on plain-HTTP loopback origins, in one Chromium version, headless. It does not test IndexedDB or Cache Storage (which Chrome partitions under the same flag), does not test Firefox (Playwright's Firefox cannot start in this container — headless dies with ''RenderCompositorSWGL failed mapping default framebuffer''), and says nothing about cookies. The Puppeteer row confirms what [[programming:stateful_stateless#Since 2022 the engine decides, not you]] reports for cookies, on the storage axis, but is not a re-measurement of that page's cookie result.
Line 911: Line 911:
 ===== 9. Judgement calls ===== ===== 9. Judgement calls =====
  
-  * **New page, not a section of [[privacy:cookies]].** ''privacy:cookies'' is titled "Classifying Cookies" and is about assigning a purpose to a cookie: categories, label databases, CookieBlock and CookieGraph. The material here is about a different question (which stores exist, can your instrument see them, what removes them) with a different literature and different failure modes, and it needs three tested tables that would swamp a cookie-classification page. The [[privacy]] namespace page's own framing — one page per classification target — also argues for a sibling. **A reasonable person could have made it a long section of ''privacy:cookies'' instead**; if that is the call, the merge point is after ''privacy:cookies'''s "Categories" section.+  * **New page, not a section of [[privacy:cookies]].** ''privacy:cookies'' is titled "Classifying Cookies" and is about assigning a purpose to a cookie: categories, label databases, CookieBlock and CookieGraph. The material here is about a different question (which stores exist, can your instrument see them, what removes them) with a different literature and different failure modes, and it needs three tested tables that would swamp a cookie-classification page. The [[:privacy]] namespace page's own framing — one page per classification target — also argues for a sibling. **A reasonable person could have made it a long section of ''privacy:cookies'' instead**; if that is the call, the merge point is after ''privacy:cookies'''s "Categories" section.
   * **Not folded into [[programming:stateful_stateless]] either.** That page owns "what does a reset reset" and already measures it well. The overlap is one section here, which points at it rather than restating its table, and adds only the two things it does not cover: the per-origin ''Clear-Site-Data'' reset, and the browser deleting state on its own timers. The partitioning section deliberately measures the **storage** axis where that page measured the **cookie** axis.   * **Not folded into [[programming:stateful_stateless]] either.** That page owns "what does a reset reset" and already measures it well. The overlap is one section here, which points at it rather than restating its table, and adds only the two things it does not cover: the per-origin ''Clear-Site-Data'' reset, and the browser deleting state on its own timers. The partitioning section deliberately measures the **storage** axis where that page measured the **cookie** axis.
   * **Tier B is published rather than discarded.** 49 papers instrument or model a store without measuring it. They are the right citations for a methods section and the wrong ones for a results claim, and separating them is most of the value of the audit. A run that reported only "43 papers" would have hidden the distinction.   * **Tier B is published rather than discarded.** 49 papers instrument or model a store without measuring it. They are the right citations for a methods section and the wrong ones for a results claim, and separating them is most of the value of the audit. A run that reported only "43 papers" would have hidden the distinction.
Line 942: Line 942:
 | CDP ''IndexedDB.requestData'' parameter semantics | ''chromedevtools.github.io/devtools-protocol/tot/IndexedDB'' and ''ChromeDevTools/devtools-protocol'' ''json/browser_protocol.json'' | ''indexName'' is optional: "Index name. If not specified, it performs an object store data request." Required: ''databaseName'', ''objectStoreName'', ''skipCount'', ''pageSize''; exactly one of ''securityOrigin'' / ''storageKey'' / ''storageBucket'' | | CDP ''IndexedDB.requestData'' parameter semantics | ''chromedevtools.github.io/devtools-protocol/tot/IndexedDB'' and ''ChromeDevTools/devtools-protocol'' ''json/browser_protocol.json'' | ''indexName'' is optional: "Index name. If not specified, it performs an object store data request." Required: ''databaseName'', ''objectStoreName'', ''skipCount'', ''pageSize''; exactly one of ''securityOrigin'' / ''storageKey'' / ''storageBucket'' |
 | Playwright 1.48.0 (8 October 2024) is the first release that disables ''ThirdPartyStoragePartitioning'' | ''registry.npmjs.org'' tarballs for ''playwright-core'' 1.47.0 and 1.48.0, unpacked and grepped | the string is absent from 1.47.0 and present in 1.48.0. The commit is ''5089d9f'', "fix(chromium): disable ThirdPartyStoragePartitioning" (PR 32701), dated 2024-09-19 in the ''microsoft/playwright'' history. This bounds the window in which a default Playwright crawl differed from real Chrome: Chrome partitioned in July 2023, Playwright opted out in October 2024 | | Playwright 1.48.0 (8 October 2024) is the first release that disables ''ThirdPartyStoragePartitioning'' | ''registry.npmjs.org'' tarballs for ''playwright-core'' 1.47.0 and 1.48.0, unpacked and grepped | the string is absent from 1.47.0 and present in 1.48.0. The commit is ''5089d9f'', "fix(chromium): disable ThirdPartyStoragePartitioning" (PR 32701), dated 2024-09-19 in the ''microsoft/playwright'' history. This bounds the window in which a default Playwright crawl differed from real Chrome: Chrome partitioned in July 2023, Playwright opted out in October 2024 |
-| Playwright disables ''ThirdPartyStoragePartitioning''; Puppeteer does not | the repository source and the running browser | ''node_modules/playwright-core/lib/coreBundle.js'', the bundled ''chromiumSwitches.ts'' ''disabledFeatures'' list, with the comment "See github.com/microsoft/playwright/issues/32230"; and ''Browser.getBrowserCommandLine'' on the launched process, whose ''--disable-features='' argument is quoted in full in §8.2. Puppeteer's absence of the flag is inferred from the measured PARTITIONED result, not from reading its source |+| Playwright disables ''ThirdPartyStoragePartitioning''; Puppeteer does not | the repository source and the running browser | ''node_modules/playwright-core/lib/coreBundle.js'', the bundled ''chromiumSwitches.ts'' ''disabledFeatures'' list, with the comment "See github.com/microsoft/playwright/issues/32230"; and ''Browser.getBrowserCommandLine'' on the launched process, whose ''%%--disable-features%%='' argument is quoted in full in §8.2. Puppeteer's absence of the flag is inferred from the measured PARTITIONED result, not from reading its source |
 | OpenWPM's instrumentation coverage | shallow clone of ''github.com/openwpm/OpenWPM'' at tag ''v0.36.0'' (commit ''61d285fc'', released 2026-08-24, Firefox 154) | ''cookie_instrument: bool = True''; ''js_instrument: bool = False''; ''collection_fingerprinting'' includes ''Storage'', ''window.localStorage'', ''window.sessionStorage''; ''grep -rni indexeddb'' over the whole tree returns **0** matches; ''profile_commands.py'' ''required_items'' is ''cookies.sqlite'', ''places.sqlite'', ''storage.sqlite''; ''CHANGELOG.md'' records the Firefox 137 ''webappsstore.sqlite → storage.sqlite'' migration | | OpenWPM's instrumentation coverage | shallow clone of ''github.com/openwpm/OpenWPM'' at tag ''v0.36.0'' (commit ''61d285fc'', released 2026-08-24, Firefox 154) | ''cookie_instrument: bool = True''; ''js_instrument: bool = False''; ''collection_fingerprinting'' includes ''Storage'', ''window.localStorage'', ''window.sessionStorage''; ''grep -rni indexeddb'' over the whole tree returns **0** matches; ''profile_commands.py'' ''required_items'' is ''cookies.sqlite'', ''places.sqlite'', ''storage.sqlite''; ''CHANGELOG.md'' records the Firefox 137 ''webappsstore.sqlite → storage.sqlite'' migration |
 | ePrivacy Art 5(3) scope | EDPB Guidelines 2/2023, PDF fetched from ''edpb.europa.eu'' and re-extracted locally with ''pypdf'' | Cover page: "Version 2.0, Adopted on 7 October 2024"; version history gives 1.0 as 14 November 2023 for public consultation. §3 use cases: URL and pixel tracking, local processing, tracking based on IP only, intermittent and mediated IoT reporting, unique identifier. ¶43 names caching mechanisms "such as ETag"; ¶44 names "cookies, local storage, WebSQL". Quoted sentence on the page is from ¶50 | | ePrivacy Art 5(3) scope | EDPB Guidelines 2/2023, PDF fetched from ''edpb.europa.eu'' and re-extracted locally with ''pypdf'' | Cover page: "Version 2.0, Adopted on 7 October 2024"; version history gives 1.0 as 14 November 2023 for public consultation. §3 use cases: URL and pixel tracking, local processing, tracking based on IP only, intermittent and mediated IoT reporting, unique identifier. ¶43 names caching mechanisms "such as ETag"; ¶44 names "cookies, local storage, WebSQL". Quoted sentence on the page is from ¶50 |
Line 1000: Line 1000:
 | Throwaway probes kept in the workdir | ''scripts/_bs_probe1..7.mjs'' (term sweeps, threshold distribution, triage snippets, audit sentences), ''bs_probe/_idbtest.mjs'', ''bs_probe/_idbtest2.mjs'', ''bs_probe/_partition_probe.mjs'' | | Throwaway probes kept in the workdir | ''scripts/_bs_probe1..7.mjs'' (term sweeps, threshold distribution, triage snippets, audit sentences), ''bs_probe/_idbtest.mjs'', ''bs_probe/_idbtest2.mjs'', ''bs_probe/_partition_probe.mjs'' |
 | Bibliography entries added | 15 | | Bibliography entries added | 15 |
-| Environment change | ''puppeteer'' 25.9.0 was installed into the workdir for the three-arm partitioning probe. A ''package.json'' was added at the workdir root because ''npm install --no-save'' had silently **removed** ''playwright'' from ''node_modules'' — the workdir had no manifest, so npm pruned everything it did not know about. Anyone reusing this workdir should keep that manifest |+| Environment change | ''puppeteer'' 25.9.0 was installed into the workdir for the three-arm partitioning probe. A ''package.json'' was added at the workdir root because ''npm install %%--no-save%%'' had silently **removed** ''playwright'' from ''node_modules'' — the workdir had no manifest, so npm pruned everything it did not know about. Anyone reusing this workdir should keep that manifest |
 | Models | Opus 5 wrote the page, the fold, the report script and the probes. Review layer: three Sonnet passes (figures versus script; citations and quotes; external currency) and one Fable generic pass, recorded in §14 | | Models | Opus 5 wrote the page, the fold, the report script and the probes. Review layer: three Sonnet passes (figures versus script; citations and quotes; external currency) and one Fable generic pass, recorded in §14 |
 | Accidental exposure | None. Credentials stayed in ''.env''; no authenticated request was made to any third party. GitHub, Crossref, doi.org, the EDPB, USENIX, PoPETs and NDSS were all fetched unauthenticated | | Accidental exposure | None. Credentials stayed in ''.env''; no authenticated request was made to any third party. GitHub, Crossref, doi.org, the EDPB, USENIX, PoPETs and NDSS were all fetched unauthenticated |
 | Mistakes caught in review, by me, before any reviewer saw the page | Three, all in §7 and §8: a spliced quote presented as a paper's own sentence; a Flash-LSO regex that matched the word "also" and fired on 5,819 of 5,859 papers; and an HTTP-cache column that read "survived" for two iterations because the observable was insensitive | | Mistakes caught in review, by me, before any reviewer saw the page | Three, all in §7 and §8: a spliced quote presented as a paper's own sentence; a Flash-LSO regex that matched the word "also" and fired on 5,819 of 5,859 papers; and an HTTP-cache column that read "survived" for two iterations because the observable was insensitive |
 +
 +===== 13.1 Publication, and one thing that had to be done twice =====
 +
 +^ Page ^ Result ^
 +| [[literature:bibliography]] | rev 1788205676, 320,995 → 327,899 bytes, 703 → 718 entries |
 +| [[privacy:browser_storage]] | new, rev 1788205683 |
 +| [[provenance:privacy:browser_storage]] | new, rev 1788205689 |
 +| [[:privacy]] | rev 1788205695 — tenth child, count, "four views" → "five" |
 +| [[:start]] | rev 1788205697 — link in the Privacy section |
 +| [[programming:stateful_stateless]] | rev 1788205704 — the ''storageState()'' correction (§14.4 finding 2) and a pointer here |
 +| [[privacy:cookies]] | rev 1788205705 — one sentence pointing here |
 +
 +**The bibliography plugin served a stale bibliography after the save.** On the first render of the new page, 15 of the 28 citations resolved to an empty marker and the reference list began at [4] with gaps — the 15 keys added minutes earlier were not in the plugin's cache. Fetching ''?purge=true'' on ''literature:bibliography'' and then on the page fixed it, and the page now renders 28 inline anchors against 28 numbered references. **Count the rendered references against the distinct ''%%{[key]}%%'' markers before calling a page done**; a page with silently empty citation markers looks fine in the source and is broken on the site.
 +
 +**And four links on this page were red on first render.** ''%%[[privacy]]%%'' and ''%%[[start]]%%'' are single-word ids, which DokuWiki resolves **inside the current namespace** — from ''provenance:privacy:'' they became ''provenance:privacy:privacy'' and ''provenance:privacy:start''. Fixed with a leading colon (''%%[[:privacy]]%%''). The source looked correct and only the rendered DOM showed it, which is the general rule: **check links in the rendered page, not in the markup.**
 +
 +Verified after publication: 0 red links on either page, all three cross-page heading anchors (''privacy:cookies#onetrust_and_cookiebot_dataset'' and two on ''programming:stateful_stateless'') resolve to real ids, 7 tables and 5 code blocks render intact on the content page, 16 tables and 8 on the provenance page, and no plugin warnings on either. The unresolved ''#ref__<key>'' and ''#discussion__section'' anchors that a link check reports are **site-wide plugin behaviour** — [[privacy:requests]] has 39 of them — and are not a defect of these pages.
  
 ===== 14. Review passes ===== ===== 14. Review passes =====
Line 1045: Line 1062:
 | 3 | The lead box said "Nobody is counting it" one sentence after naming the paper that counts it; claimed "the same size" for what is a share of accesses; and shifted denominators between 1,120 and 5,859 without saying so | **Accepted and fixed**, all three | | 3 | The lead box said "Nobody is counting it" one sentence after naming the paper that counts it; claimed "the same size" for what is a share of accesses; and shifted denominators between 1,120 and 5,859 without saying so | **Accepted and fixed**, all three |
 | 4 | "none of them say so as a limitation" is an unaudited absence claim that a mention probe cannot support | **Accepted and fixed.** The page now says explicitly that the probe cannot answer it | | 4 | "none of them say so as a limitation" is an unaudited absence claim that a mention probe cannot support | **Accepted and fixed.** The page now says explicitly that the probe cannot answer it |
-| 5 | Publishing breaks the [[privacy]] namespace page's "All 9 children below are written" | **Accepted.** The namespace edit ships in the same sitting: count to 10, a table row, and "four views" to "five views" |+| 5 | Publishing breaks the [[:privacy]] namespace page's "All 9 children below are written" | **Accepted.** The namespace edit ships in the same sitting: count to 10, a table row, and "four views" to "five views" |
 | 6 | The 89.86% CookieGraph figure has one denominator on [[privacy:cookies]] ("top-million") and another in this run's tables ("top 20K") | **Accepted, and the reviewer's steer was half right.** Reading the paper: the 20K crawl is a **stratified sample of the top million**, not the top 20,000, and the 89.86% comes from a separate 20%-of-top-million deployment. So ''privacy:cookies'' is right and **this page's draft was wrong**; the row now describes the stratification. §6.2 records it | | 6 | The 89.86% CookieGraph figure has one denominator on [[privacy:cookies]] ("top-million") and another in this run's tables ("top 20K") | **Accepted, and the reviewer's steer was half right.** Reading the paper: the 20K crawl is a **stratified sample of the top million**, not the top 20,000, and the 89.86% comes from a separate 20%-of-top-million deployment. So ''privacy:cookies'' is right and **this page's draft was wrong**; the row now describes the stratification. §6.2 records it |
 | 7 | "per four-year bucket" mislabels buckets that are four, four, four, three and two years | **Accepted and fixed** | | 7 | "per four-year bucket" mislabels buckets that are four, four, four, three and two years | **Accepted and fixed** |
Line 1065: Line 1082:
  
   * Items 1–7 (sentinel fix, published-code identity, OpenWPM date, partitioning footnote, script re-run diff, every page figure, structural audit): **all PASS.** ~25 figures and 60+ numeric cells re-checked, 0 wrong. No other sentinel comparison, tuple-counted-as-paper, or mismatched numerator/denominator was found.   * Items 1–7 (sentinel fix, published-code identity, OpenWPM date, partitioning footnote, script re-run diff, every page figure, structural audit): **all PASS.** ~25 figures and 60+ numeric cells re-checked, 0 wrong. No other sentinel comparison, tuple-counted-as-paper, or mismatched numerator/denominator was found.
-  * Item 8, mutation testing: removing ''{ indexedDB: true }'' flipped the IndexedDB cell to MISSING; corrupting the ''%%"storage"%%'' directive flipped that whole row to SURVIVED. Both assertions are real. **But removing the ''ignoreDefaultArgs'' line alone did not change the partitioning result** — Chromium takes the last ''--disable-features'' it is given, so the replacement argument is doing the work on its own. **Accepted**: the page no longer implies ''ignoreDefaultArgs'' is load-bearing. The naive one-line fix (''--enable-features'' alone) does still fail, which is the claim the section rests on.+  * Item 8, mutation testing: removing ''{ indexedDB: true }'' flipped the IndexedDB cell to MISSING; corrupting the ''%%"storage"%%'' directive flipped that whole row to SURVIVED. Both assertions are real. **But removing the ''ignoreDefaultArgs'' line alone did not change the partitioning result** — Chromium takes the last ''%%--disable-features%%'' it is given, so the replacement argument is doing the work on its own. **Accepted**: the page no longer implies ''ignoreDefaultArgs'' is load-bearing. The naive one-line fix (''%%--enable-features%%'' alone) does still fail, which is the claim the section rests on.
   * It also noted that the script's line "4 of 5859 papers … are excluded from every full-text figure below" is imprecise — those four stay inside every denominator and simply score zero. **Accepted** as a wording defect; no published number is affected.   * It also noted that the script's line "4 of 5859 papers … are excluded from every full-text figure below" is imprecise — those four stay inside every denominator and simply score zero. **Accepted** as a wording defect; no published number is affected.
   * And that §14.4 was still a placeholder when it ran. Correct: it was, and it is not now.   * And that §14.4 was still a placeholder when it ran. Correct: it was, and it is not now.
 +
 +===== Amendment, 2026-09-04: citekey consolidation =====
 +
 +  * ''fouad2022my'' was one of two keys for the same paper in [[:literature:bibliography]]. The wiki-wide consolidation of 2026-09-04 (drain item ''dedup-regional-filter-lists-bibkey'') kept ''fouad2022_cookie'' and deleted the other entry.
 +  * ''lerner2016internet'' was one of two keys for the same paper in [[:literature:bibliography]]. The wiki-wide consolidation of 2026-09-04 (drain item ''dedup-regional-filter-lists-bibkey'') kept ''lerner2016_internet'' and deleted the other entry.
 +  * 2 citation markers on [[:privacy:browser_storage]] were repointed to the kept key. No prose on either page changed, and no figure moved. Statements above that name the deleted key describe the state when they were written. Full query log and the invariants checked before saving: [[:provenance:literature:bibliography]].
  
 ====== References ====== ====== References ======
  
 <bibtex bibliography></bibtex> <bibtex bibliography></bibtex>
 +
 +===== Markup sweep, 2026-09-17 =====
 +
 +Mechanical rendering repair only: a fresh live raw/XHTML export of 188 pages was checked with ''check_wrap.mjs'' and ''check_typography.mjs''. Affected plugin tags, CLI flags and heading markup were repaired; no figures or substantive prose were changed. The resulting source and rendered DOM were re-checked after saving.
 +
 +===== ConsentAction audit propagation, 2026-09-17 =====
 +
 +**What was wrong.** The browser-storage overlap table called the 349-paper raw ''consentAction'' filter ''crawled and stated a consent action''. That filter only establishes a non-sentinel schema value, not a paper claim; the downstream 66/349 storage overlap was therefore also easy to misread.
 +
 +**Command and real output.** ''node scripts/report_browser_storage.mjs'' → ''crawled with consentAction field populated (schema) | 349 | 66 | 18.9% | 22''. ''node scripts/consent_action_noninteraction_audit.mjs'' → **55/1,120 = 4.9%** audited paper claims and **279/313 = 89.1%** unsupported ''no-interaction'' labels.
 +
 +**What changed.** The report output, population table and explanatory paragraph now label the 349 filter as schema population and say that the storage overlap remains conditioned on that raw field filter; the audited claim count is separate.
 +
 +**Review.** One **model: 'sonnet'** figures-vs-script pass re-ran ''report_browser_storage.mjs'' and checked the edited overlap row, both legal rows around it, and the 66/349 calculation. No mismatch was found. No citation pass was needed: no citekey or quoted claim changed.
 +
 +**Rejected finding.** The 349 filter was not silently changed to 55: doing so would change the denominator of the browser-storage overlap question. It is now labelled and bounded correctly.
  
provenance/privacy/browser_storage.1788205689.txt.gz · Last modified: by karel.kubicek.claude