| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| provenance:privacy:privacy_sandbox [2026/09/01 16:59] – Refresh the query table, folding residue and embedded report output after the fold fixes; add the three-pass review log with every finding and its disposition. Authored by Claude. karel.kubicek.claude | provenance:privacy:privacy_sandbox [2026/09/27 22:13] (current) – Removal-status refresh 2026-09-27: 14-build milestone probe (script + unedited output), new asserting external-checks script (+ output, mutation test), status sources verified/rejected, corrections to the 2026-09-01 page, judgement calls, full review log. karel.kubicek.claude |
|---|
| ===== Run record ===== | ===== Run record ===== |
| |
| * Run date: **2026-09-01** (UTC). | * Run date: **2026-09-01** (UTC). **Removal status refreshed 2026-09-27**; everything about that refresh is in [[#Removal-status refresh, 2026-09-27]], and it supersedes the milestone statements elsewhere on this page. |
| * Authoring agent: Claude Opus 5, executing the drain item ''privacy:privacy_sandbox (new)''. Two background research sub-agents (''sonnet'') for the currency and tooling passes; **every load-bearing fact they returned was re-fetched and re-verified by the authoring agent before it reached the page** — see [[#Sub-agent findings that did not survive verification]], which is the part of this log with the most value. | * Authoring agent: Claude Opus 5, executing the drain item ''privacy:privacy_sandbox (new)''. Two background research sub-agents (''sonnet'') for the currency and tooling passes; **every load-bearing fact they returned was re-fetched and re-verified by the authoring agent before it reached the page** — see [[#Sub-agent findings that did not survive verification]], which is the part of this log with the most value. |
| * Corpus at run time: **5,859** extracted papers, 2010–2026, seven venues (CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf, IEEE S&P). The full-text sweep runs over the **5,869** papers that have a rendered ''paper.cols.txt''; the 10-paper difference is papers with text but no extraction record, and it is why the page names 5,869 as the full-text denominator and 5,859 as the extraction denominator rather than using one number for both. | * Corpus at run time: **5,859** extracted papers, 2010–2026, seven venues (CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf, IEEE S&P). The full-text sweep runs over the **5,869** papers that have a rendered ''paper.cols.txt''; the 10-paper difference is papers with text but no extraction record, and it is why the page names 5,869 as the full-text denominator and 5,859 as the extraction denominator rather than using one number for both. |
| * Read-only inputs under ''/workspace/publications_dataset/data/''. Nothing was written there. | * Read-only inputs under ''/workspace/publications_dataset/data/''. Nothing was written there. |
| * Browser measurements: **Chromium 151.0.7922.34** as shipped with **Playwright 1.62.1**, Linux container, headless. Puppeteer was pointed at the same binary via ''chromium.executablePath()'' because the container's own ''/usr/bin/chromium'' cannot be driven (the crashpad-flag problem documented in the workdir README). | * Browser measurements: **Chromium 151.0.7922.34** as shipped with **Playwright 1.62.1**, Linux container, headless. Puppeteer was pointed at the same binary via ''chromium.executablePath()'' because the container's own ''/usr/bin/chromium'' cannot be driven (the crashpad-flag problem documented in the workdir README). //(2026-09-27: not the same binary. ''chromium.executablePath()'' is the full Chromium, and Playwright's default is chrome-headless-shell; see [[#What the 2026-09-01 page said that did not hold]]. Debian's Chromium can in fact be driven; see [[#Milestone probe, 2026-09-27]].)// |
| * This is a **new page**, not an extension. See [[#Why a new page and not a broadened neighbour]]. | * This is a **new page**, not an extension. See [[#Why a new page and not a broadened neighbour]]. |
| * Wiki saves through ''scripts/dw.mjs'' (JSON-RPC). Bibliography saved with ''--if-rev 1788205676''. | * Wiki saves through ''scripts/dw.mjs'' (JSON-RPC). Bibliography saved with ''%%--if-rev%% 1788205676''. |
| |
| ===== Why a new page and not a broadened neighbour ===== | ===== Why a new page and not a broadened neighbour ===== |
| |
| == CDP events received (7) == | == CDP events received (7) == |
| Storage.interestGroupAuctionEventOccurred {"eventTime":1788280668.965319,"type":"started","uniqueAuctionId":"49E0BB9B63C9BD64E47335ECBF4728D0","auctionConfig":{"auctionSignals":{"pending":false,"value":null},"decisionLogicURL":"https://probe.example:8444/decide. | Storage.interestGroupAuctionEventOccurred {"eventTime":1788282880.844885,"type":"started","uniqueAuctionId":"BAA2639A8868AB941264DB3DB6CB5BED","auctionConfig":{"auctionSignals":{"pending":false,"value":null},"decisionLogicURL":"https://probe.example:8444/decide. |
| Storage.interestGroupAuctionNetworkRequestCreated {"type":"bidderJs","requestId":"96FF20B838C9A062BFC9B2D1EB2074F6","auctions":["49E0BB9B63C9BD64E47335ECBF4728D0"]} | Storage.interestGroupAuctionNetworkRequestCreated {"type":"bidderJs","requestId":"06A218F8B3F436C7E8D3F44A2D2806C3","auctions":["BAA2639A8868AB941264DB3DB6CB5BED"]} |
| Storage.interestGroupAuctionNetworkRequestCreated {"type":"sellerJs","requestId":"E700229B68625D5ED4A44112015F90EE","auctions":["49E0BB9B63C9BD64E47335ECBF4728D0"]} | Storage.interestGroupAuctionNetworkRequestCreated {"type":"sellerJs","requestId":"C09A1952CA56CC58940B85D959CCD3A3","auctions":["BAA2639A8868AB941264DB3DB6CB5BED"]} |
| Storage.sharedStorageAccessed {"accessTime":1788280669.021785,"scope":"window","method":"set","mainFrameId":"9EE9B30C8B76A15625E274C35BD01EC1","ownerOrigin":"https://probe.example:8444","ownerSite":"https://probe.example","params":{"key":"k","value": | Storage.sharedStorageAccessed {"accessTime":1788282880.902479,"scope":"window","method":"set","mainFrameId":"B3037C0FA13BA8CE8A07D1020A778F25","ownerOrigin":"https://probe.example:8444","ownerSite":"https://probe.example","params":{"key":"k","value": |
| Storage.sharedStorageAccessed {"accessTime":1788280669.02439,"scope":"window","method":"addModule","mainFrameId":"9EE9B30C8B76A15625E274C35BD01EC1","ownerOrigin":"https://probe.example:8444","ownerSite":"https://probe.example","params":{"scriptSource | Storage.sharedStorageAccessed {"accessTime":1788282880.904117,"scope":"window","method":"addModule","mainFrameId":"B3037C0FA13BA8CE8A07D1020A778F25","ownerOrigin":"https://probe.example:8444","ownerSite":"https://probe.example","params":{"scriptSourc |
| Storage.sharedStorageAccessed {"accessTime":1788280669.033277,"scope":"window","method":"run","mainFrameId":"9EE9B30C8B76A15625E274C35BD01EC1","ownerOrigin":"https://probe.example:8444","ownerSite":"https://probe.example","params":{"operationName":"p | Storage.sharedStorageAccessed {"accessTime":1788282880.912412,"scope":"window","method":"run","mainFrameId":"B3037C0FA13BA8CE8A07D1020A778F25","ownerOrigin":"https://probe.example:8444","ownerSite":"https://probe.example","params":{"operationName":"p |
| Storage.sharedStorageWorkletOperationExecutionFinished {"finishedTime":1788280669.033894,"executionTime":847,"method":"run","operationId":"0","workletTargetId":"383073F2489DBB30E78E8E91A9CF2429","mainFrameId":"9EE9B30C8B76A15625E274C35BD01EC1","ownerOrigin":"https://probe.ex | Storage.sharedStorageWorkletOperationExecutionFinished {"finishedTime":1788282880.913208,"executionTime":1050,"method":"run","operationId":"0","workletTargetId":"EBB22A0151158B1D33AB96EBCA57DF2F","mainFrameId":"B3037C0FA13BA8CE8A07D1020A778F25","ownerOrigin":"https://probe.e |
| </file> | </file> |
| |
| | ''privacysandbox.google.com/blog/update-on-plans-for-privacy-sandbox-technologies'' | The 2025-10-17 retirement of ten technologies | Fetched; the list and the CHIPS/FedCM/PST carve-out quoted **verbatim**; page footer reads "Last updated 2025-10-17 UTC" | **Used**, quoted | | | ''privacysandbox.google.com/blog/update-on-plans-for-privacy-sandbox-technologies'' | The 2025-10-17 retirement of ten technologies | Fetched; the list and the CHIPS/FedCM/PST carve-out quoted **verbatim**; page footer reads "Last updated 2025-10-17 UTC" | **Used**, quoted | |
| | ''privacysandbox.google.com/overview/status'' | Per-feature status: Continue to support / Deprecate and remove / Discontinue / Do not launch; CHIPS default in Chrome 114; Storage Access default in Chrome 119 | Fetched; page states "Last updated: August 14, 2026" | **Used** | | | ''privacysandbox.google.com/overview/status'' | Per-feature status: Continue to support / Deprecate and remove / Discontinue / Do not launch; CHIPS default in Chrome 114; Storage Access default in Chrome 119 | Fetched; page states "Last updated: August 14, 2026" | **Used** | |
| | ''privacysandbox.google.com/private-advertising/enrollment'' | "We will no longer accept new account creation and enrollment" | Fetched, quoted verbatim | Used in provenance; the page states the consequence rather than the quote | | | ''privacysandbox.google.com/private-advertising/enrollment'' | "We will no longer accept new account creation and enrollment" | Fetched, quoted verbatim | **Used, quoted on the content page.** A first draft only implied the consequence; a review pass pointed out the sentence was never actually written, so the quote and the ''%%--privacy-sandbox-enrollment-overrides%%'' workaround are now both on the page | |
| | ''chromestatus.com/api/v0/features/<id>'' × 19 | Ship milestones (M114/M115/M116/M108) and removal milestones (M152/M153/M155), all with status ''Proposed'' | Fetched individually through the JSON API | **Used** | | | ''chromestatus.com/api/v0/features/<id>'' × 19 | Ship milestones (M114/M115/M116/M108) and removal milestones (M152/M153/M155), all with status ''Proposed'' | Fetched individually through the JSON API | **Used** for ship milestones. **Superseded for removal status on 2026-09-27**: the 19 ids were not recorded, the 22 used since are in ''scripts/external_checks_privacy_sandbox.mjs'', Fenced Frames moved to M156, and there was never a Topics removal entry | |
| | ''chromiumdash.appspot.com/fetch_releases'' and ''fetch_milestone_schedule'' | Chrome stable = M152 since 2026-08-25; M153 stable_date 2026-09-08; M114 2023-05-30; M115 2023-07-18; M116 2023-08-15 | Fetched, parsed | **Used** | | | ''chromiumdash.appspot.com/fetch_releases'' and ''fetch_milestone_schedule'' | Chrome stable = M152 since 2026-08-25; M153 stable_date 2026-09-08; M114 2023-05-30; M115 2023-07-18; M116 2023-08-15 | Fetched, parsed | **Used** | |
| | ''gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes'' | Case opened 2021-01-07, **closed 2025-10-17** | Fetched; "Case state: Closed" read off the page | **Used** | | | ''gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes'' | Case opened 2021-01-07, **closed 2025-10-17** | Fetched; "Case state: Closed" read off the page | **Used** | |
| | ''github.com/GoogleChrome/related-website-sets'' → ''related_website_sets.JSON'' | **70 sets, 320 member domains, 66 (94.3%) with an associated site** | Fetched and counted in this run | **Used** | | | ''github.com/GoogleChrome/related-website-sets'' → ''related_website_sets.JSON'' | **70 sets, 320 member domains, 66 (94.3%) with an associated site** | Fetched and counted in this run | **Used** | |
| | | GitHub API on ''privacysandbox/attestation'' and ''patcg-individual-drafts/topics'' | Both ''archived: true''; last pushes **2026-01-22** and **2025-11-07** | Fetched 2026-09-01 after a review pass flagged that the page treated these as live feeds | **Used.** The archival of the topics repo is also the reason there is no taxonomy v3 | |
| | | ''ChromeDevTools/devtools-protocol'' commit history, bisected | The CDP ''Storage'' domain carried ''setAttributionReportingTracking'', ''setAttributionReportingLocalTestingMode'', ''sendPendingAttributionReports'' and four ''attributionReporting*'' events. Present in the descriptor at **2026-04-01**, absent at **2026-04-08** | Fetched five dated snapshots (2026-01-01, 02-01, 03-01, 03-15, 04-01) and four in April, resolving each date to a commit SHA through the GitHub commits API and pulling ''json/browser_protocol.json'' at that SHA | **Used.** This changed the page's advice: Attribution Reporting is measurable with first-class CDP events on a pre-April-2026 build, which the first draft denied | |
| | | ''chromiumdash.appspot.com/fetch_milestone_schedule'' for M146–M151 | Branch points: M147 2026-03-09, M148 **2026-04-06** | Fetched | **Used as an inference, labelled as one.** M147 should carry the ARA surface; M148 branched inside the removal window and is a coin flip. **Not tested** — this run had only Chromium 151 | |
| | | blink-dev, "Intent to Deprecate and Remove: Topics API" (thread ''_R85yctz4Rs'') | "Deprecate in M144 and then remove in M150"; "The Topics API was deprecated in Chrome-144 with a plan to remove it in Chrome-150. Currently the usage is 4.9% of page loads"; the phased M150 field-trial / M152 stub plan, quoted verbatim on the page | Fetched 2026-09-01. Thread opened 2025-11-07; the phased-plan message is dated 2026-06-12; later messages 2026-06-25 and 2026-07-08 | **Used.** A first draft asserted "the removal dates have already slipped twice" on a sub-agent's word; the primary source shows something more precise — deprecation landed at M144 **on schedule**, and it is the removal that moved M150 → M152 → M153. The page was rewritten to say that. It also turned the speculative field-trial hedge into a sourced fact | |
| | | Chrome Platform Status ''motivation'' fields for Topics, Shared Storage, Protected Audience, RWS, Attribution Reporting | Chrome's own usage telemetry: Topics 13% then 4.9% of page loads; Shared Storage ~11% of page loads; Protected Audience ''joinAdInterestGroup()'' down ~100x and ''runAdAuction()'' down >10x with "virtually none" of auctions having winners; RWS 71 sets and ''requestStorageAccessFor'' ~0.95% of page loads; ARA no figure | Fetched 2026-09-01 through the JSON API | **Used, with the caveat foregrounded.** These are unaudited vendor telemetry with no stated methodology and a //page load// unit. They are on the page because they are the only post-April-2025 adoption numbers in existence, and the page says exactly that. The 71-vs-70 RWS discrepancy is published rather than reconciled | |
| | | MDN header reference pages for ''Attribution-Reporting-Eligible'', ''Attribution-Reporting-Register-Source'', ''Attribution-Reporting-Register-Trigger'', ''Sec-Browsing-Topics'', ''Observe-Browsing-Topics'' | All five exist; ''Sec-Browsing-Topics'' "fails silently" and is deleted for an unenrolled caller | All five fetched, HTTP 200; the silent-failure sentence quoted verbatim from the ''Sec-Browsing-Topics'' page | **Used.** ''Sec-Shared-Storage-Writable'' was checked and returns 404 on MDN, so it is not on the page | |
| | GitHub API on ''GoogleChrome/related-website-sets'' and ''GoogleChrome/ip-protection'' | Both ''archived: true''; last pushes 2025-11-21 and 2025-11-03 | Fetched | **Used** | | | GitHub API on ''GoogleChrome/related-website-sets'' and ''GoogleChrome/ip-protection'' | Both ''archived: true''; last pushes 2025-11-21 and 2025-11-03 | Fetched | **Used** | |
| | ''github.com/privacysandbox/attestation'' → ''enrollment_report.csv'' | **326 rows**; Topics 249, Protected Audience 237, Attribution Reporting 228, Shared Storage 205, Private Aggregation 193; 25 rows with no Chrome API | Fetched and counted in this run | **Used** | | | ''github.com/privacysandbox/attestation'' → ''enrollment_report.csv'' | **326 rows**; Topics 249, Protected Audience 237, Attribution Reporting 228, Shared Storage 205, Private Aggregation 193; 25 rows with no Chrome API | Fetched and counted in this run | **Used** | |
| ===== What the corpus does not establish ===== | ===== What the corpus does not establish ===== |
| |
| * **Nothing about Attribution Reporting in deployment.** 4 of 5,869 papers name it, none instrument it. | * **Nothing about Attribution Reporting in deployment.** 3 of 5,869 papers name it, none instrument it. |
| * **No adoption measurement after February 2025.** The two crawl-based papers are from 2023 and February 2025; the retirement was announced in October 2025. Chrome's own removal notes claim usage collapsed; this corpus cannot confirm or refute that. | * **No //independent// adoption measurement after February 2025.** The two crawl-based papers are from 2023 and February 2025; the retirement was announced in October 2025. Chrome's own removal notes claim usage collapsed and give numbers, now quoted on the page; this corpus cannot confirm or refute them, and the party that produced them is the party being measured. |
| * **No CHIPS adoption study inside the seven venues.** ''rasaii2025_crumbs'' gives a 1.3% figure as a side measurement; the dedicated study is a PAM 2025 paper outside the corpus. | * **No CHIPS adoption study inside the seven venues.** ''rasaii2025_crumbs'' gives a 1.3% figure as a side measurement; the dedicated study is a PAM 2025 paper outside the corpus. |
| * **Regional gating of the ads APIs.** Both Google availability pages 404. A DMA-driven gate is plausible but plausible is not measured. A first draft asserted that FLoC's 2021 origin trial excluded the EEA; that came from a sub-agent citing Wikipedia, no primary source for it could be found in this run, and it was removed from the page. What ''berke2022_privacy'' does say, and what the page now carries instead: the trial ran Chrome 89 to 91, spring to autumn 2021, for users with at least seven domains in their history, with //k// = 2000 giving 33,872 cohorts of which 2.3% were deemed sensitive. Published on the page as an explicit unknown with an instruction to test it rather than assume. | * **Regional gating of the ads APIs.** Both Google availability pages 404. A DMA-driven gate is plausible but plausible is not measured. A first draft asserted that FLoC's 2021 origin trial excluded the EEA; that came from a sub-agent citing Wikipedia, no primary source for it could be found in this run, and it was removed from the page. What ''berke2022_privacy'' does say, and what the page now carries instead: the trial ran Chrome 89 to 91, spring to autumn 2021, for users with at least seven domains in their history, with //k// = 2000 giving 33,872 cohorts of which 2.3% were deemed sensitive. Published on the page as an explicit unknown with an instruction to test it rather than assume. |
| * **Title "Measuring the Privacy Sandbox", not "The Privacy Sandbox".** The page is about instrumentation and denominators, not about explaining the APIs; the specs do that better and the wiki's own rule is not to teach the platform. | * **Title "Measuring the Privacy Sandbox", not "The Privacy Sandbox".** The page is about instrumentation and denominators, not about explaining the APIs; the specs do that better and the wiki's own rule is not to teach the platform. |
| * **The retirement is the page's lead, not a footnote.** A reader who takes only one sentence away should take "these are being removed and your browser version is the measurement". The alternative — leading with the API descriptions — would have reproduced the 2022 roadmap, which is the failure mode the task spec warns about. | * **The retirement is the page's lead, not a footnote.** A reader who takes only one sentence away should take "these are being removed and your browser version is the measurement". The alternative — leading with the API descriptions — would have reproduced the 2022 roadmap, which is the failure mode the task spec warns about. |
| * **Removal milestones are reported as //proposed//, not as fact.** They are the ''desktop'' milestone on a Chrome Platform Status entry whose status string is ''Proposed''. Two of them (M144, M150) had already slipped once before landing on M152/M153. The page dates them and does not promise them. | * **Removal milestones are reported as //proposed//, not as fact.** //(2026-09-27: superseded. The page now reports what the binaries do; see [[#Judgement calls, 2026-09-27]].)// They are the ''desktop'' milestone on a Chrome Platform Status entry whose status string is ''Proposed''. Two of them (M144, M150) had already slipped once before landing on M152/M153. The page dates them and does not promise them. |
| * **Published the "8.1% of recent web crawls" silence figure** even though it is a keyword proxy, because the direction is unambiguous at that magnitude and the confound (a paper can measure the platform without naming an API) can only inflate the //true// figure slightly, not reverse it. The page names the proxy. | * **Published the "7.7% of recent web crawls" silence figure** even though it is a keyword proxy, because the direction is unambiguous at that magnitude and the confound (a paper can measure the platform without naming an API) can only inflate the //true// figure slightly, not reverse it. The page names the proxy, and now also names the opposite confound a review pass raised: the denominator includes crawls with no reason to touch an ads API, so the figure is an upper bound on non-engagement rather than a defect rate. |
| * **Did not publish the "Privacy Budget" or "k-anonymity" counts** at all: both regexes are dominated by generic differential-privacy usage and no qualified version was found that was worth the space. | * **Did not publish the "Privacy Budget" or "k-anonymity" counts** at all: both regexes are dominated by generic differential-privacy usage and no qualified version was found that was worth the space. |
| * **Did not publish a figure from the PAM 2025 CHIPS paper.** It is outside the corpus, Springer would not serve its abstract to this run, and nobody here read it. | * **Did not publish a figure from the PAM 2025 CHIPS paper.** It is outside the corpus, Springer would not serve its abstract to this run, and nobody here read it. |
| Generated with ''scripts/bibgen.mjs''. Two needed hand-completion because PETS and USENIX index records carry no authors: the PoPETs authors came from ''petsymposium.org/popets/2023/popets-2023-0101.php'' and the USENIX authors from the venue landing page, both fetched with a browser User-Agent. Reused without change: ''jha2023_topics'', ''beugin2024_interest'', ''ali2023_navigating'', ''lin2024_browsing'', ''rasaii2025_crumbs'', ''bahrami2025_cookieguard'', ''kancherla2025_least''. | Generated with ''scripts/bibgen.mjs''. Two needed hand-completion because PETS and USENIX index records carry no authors: the PoPETs authors came from ''petsymposium.org/popets/2023/popets-2023-0101.php'' and the USENIX authors from the venue landing page, both fetched with a browser User-Agent. Reused without change: ''jha2023_topics'', ''beugin2024_interest'', ''ali2023_navigating'', ''lin2024_browsing'', ''rasaii2025_crumbs'', ''bahrami2025_cookieguard'', ''kancherla2025_least''. |
| |
| After saving, ''literature:bibliography'' and the page were purged (''?purge=true'') and the rendered DOM checked: **58 ''bibtex_citekey'' markers, 13 rendered references for 13 distinct keys, zero unresolved citation markers, 10 tables, 22 headings, 4 WRAP boxes.** | After each save, ''literature:bibliography'' and the page were purged (''?purge=true'') and the rendered DOM re-checked, counting only inside the ''%%<!-- wikipage start -->%%'' … ''%%<!-- wikipage stop -->%%'' markers so that the theme's own chrome is not counted. |
| | |
| | Counts below are for [[privacy:privacy_sandbox]] only. This page's own heading and table counts are deliberately not asserted, because every edit to this paragraph changes them and a self-referential count can never be right for long; what //is// asserted about this page is that it renders **12** downloadable file blocks (7 until the 2026-09-27 refresh added 5) and **zero** red links. |
| | |
| | ^ Count ^ [[privacy:privacy_sandbox]] ^ |
| | | citation markers in the wiki source | **33** | |
| | | distinct citekeys among them | **13** | |
| | | ''bibtex_citekey'' spans in the rendered DOM | **66** | |
| | | ''%%<dt>%%'' entries in the rendered ''bibtex_references'' list | **13** | |
| | | ''%%<table>%%'' in the rendered body | **13** (12 before the 2026-09-27 refresh) | |
| | | ''%%<h1>%%''–''%%<h4>%%'' in the rendered body | **24** (23 before) | |
| | | ''%%<WRAP>%%'' boxes | **6** (5 before) | |
| | | ''wikilink2'' (red links) | **0** | |
| | | downloadable ''%%<file>%%'' blocks | **1** | |
| | |
| | **Read the first three rows together, because two reviewers independently got them wrong and then disagreed with each other.** The bibtex plugin emits **two** ''bibtex_citekey'' spans per source marker — an anchor and a link — so 33 markers render as 66 spans, and neither number is the reference count: 33 markers over 13 distinct keys give 13 entries in the reference list. The rendered heading count is one higher than the source heading count because ''%%~~DISCUSSION~~%%'' contributes its own heading. And a source-side count is not a substitute for a rendered one on either page: the embedded script output here contains ''%%==%%''- and ''%%##%%''-prefixed lines that a naive source-side heading regex picks up as headings (44 against a real 22). |
| | |
| | Two earlier versions of this paragraph were wrong — first 58/22, then 60/21/4, both counted with an unscoped grep and both before the last round of edits. A review pass could not reproduce either. It is recorded rather than quietly corrected because a provenance page whose own self-check does not reproduce is worse than one that has none, and because getting a trivial count wrong twice is the honest illustration of why the rest of the page is scripted. |
| |
| ===== Folding script ===== | ===== Folding script ===== |
| |
| ==== fable — generic ==== | ==== fable — generic ==== |
| | |
| | Run after the three focused passes and their fixes, with no checklist. It found more than the other three combined, and two of its findings were substantive enough to change what the page tells a reader to do. |
| |
| ^ Finding ^ Disposition ^ | ^ Finding ^ Disposition ^ |
| | (pending) | | | | **"Topics and Attribution Reporting have no CDP surface at all, in any Chromium version checked" is misleading, and it misdirects the page's own headline call to action.** "Any version checked" was two versions. ARA had a full CDP ''Storage'' surface until it was removed from the protocol in April 2026 | **Accepted, fixed, and this was the most valuable finding of the whole review.** Verified independently by bisecting the ''devtools-protocol'' history (present 2026-04-01, absent 2026-04-08). The page now carries a box saying the gap is closable with first-class instrumentation on a pre-April-2026 build, with a one-line check for whether a given binary has it. The CDP table has a new row. The two dead ARA listeners in the published script now carry a comment saying why they are there | |
| | | **HTTP headers are missing entirely as an observation surface**, and they are arguably the //primary// one for Attribution Reporting and Topics | **Accepted, fixed.** New subsection with all five headers, verified against MDN. Added to the "What to Report" list | |
| | | **Wrapping the ''attributionSrc'' IDL setter misses server-rendered ''%%attributionsrc%%'' content attributes**, because the parser does not invoke IDL setters | **Accepted, fixed.** The page now says not to do it and gives three alternatives. This was a genuine instrument bug in advice the page was giving | |
| | | ''privacysandbox/attestation'' **and** ''patcg-individual-drafts/topics'' **are also archived**; the page marked only the RWS repo, and said "two of the three" artefacts are frozen | **Accepted, fixed.** Verified through the GitHub API: archived, last pushes 2026-01-22 and 2025-11-07. All three rows now carry the archive date, and the "two of the three" sentence is rewritten — with the distinction that the ''.dat'' inside a Chromium install still moves with the component updater | |
| | | **The enrollment-closure "consequence" this log claimed the page stated was never actually written on the page** | **Accepted, fixed.** The quote and the ''%%--privacy-sandbox-enrollment-overrides%%'' workaround are now both on the content page. This log's own claim has been corrected | |
| | | Two stale figures in **this log's prose**: "4 of 5,869 papers name Attribution Reporting" and "the 8.1% silence figure", both pre-fold-fix | **Accepted, fixed.** This is the known failure mode where a correction reaches the page but not the log; recording that it happened here too | |
| | | **The removal-date slip history is only in this log, not where the reader decides.** "Measured in days" is stated as if M153 were firm | **Accepted, fixed.** The slip history (M144 → M150 → M152/M153/M155) is now a bullet in the top box, and "days" is hedged | |
| | | **"They have not been removed yet" rests on a Chromium 151 probe while stable is M152** | **Accepted, fixed.** The box now says so in one clause | |
| | | **Missing hedge: field trials.** A code-removal milestone is the //latest// end of the window; Chrome ramps features down server-side first, and an automation Chromium has no variations seed | **Accepted, added**, flagged as not established for these specific features | |
| | | **The measured-results table has no written inclusion rule**, and two of its rows are not Privacy Sandbox measurements | **Accepted, fixed.** The rule is now stated above the table and the two exceptions are named and justified. The precision sentence in [[#Folding and residue]] counts the same 11 | |
| | | **Missing: user-side gating.** Real users hold heterogeneous "Ad privacy" toggle states; a crawler profile is one | **Accepted, added** to the pitfalls list | |
| | | "A dozen papers … over sixteen years", after showing 43/67/9 and an 11-row table; and self-referential prose about its own placement; and "the re-identification numbers everyone cites" in a page that proves almost nobody cites them | **All three accepted, fixed** | |
| | | The silence figure's denominator includes crawls with no reason to touch an ads API | **Accepted.** The defence was in this log only; half a sentence of it is now on the content page, framing the figure as an upper bound on non-engagement | |
| | | Bounce-tracking dating differs in phrasing from [[privacy:browser_storage]] | **Accepted, fixed** by naming both the milestone and the later default-on, and cross-linking | |
| | | The provenance page is honest in tone; its overclaims are the three concrete ones above | **Noted.** All three fixed | |
| | |
| | **Rejected: nothing.** Every finding from this pass was accepted. That is unusual and is recorded as such: it is evidence the generic slot earns its place, and also that the three focused passes, by having checklists, all missed the same class of defect — advice that is well-sourced and wrong. |
| | |
| | ==== Work done after the generic pass, and the second round ==== |
| | |
| | Verifying the generic pass's "removal dates have already slipped twice" finding against the blink-dev thread turned up more than the finding itself, and the content page gained a section that no reviewer had seen: **"The only post-2025 adoption numbers that exist are Chrome's own"**, five rows of Chrome Platform Status ''motivation'' telemetry. It is recorded here rather than folded silently into the page because it postdates every review, and because it is exactly the kind of late addition that escapes an audit trail. Its sources are in [[#External sources, verified and rejected]]; two subsequent re-review passes checked all five quotes verbatim and found no error in them. |
| | |
| | Two ''sonnet'' re-review passes were then run over the edited pages, one on figures and one on currency and citations, both told the earlier fixes might themselves be wrong. |
| | |
| | ^ Finding ^ Disposition ^ |
| | | **The DOM self-check numbers in [[#Bibliography]] are still wrong** — "60 citation markers, 10 tables, 21 headings, 4 WRAP boxes" against actual 33 source markers / 12 tables / 23 headings / 5 boxes. Found independently by both re-reviewers, who then disagreed with each other (33 vs 60 markers, 21 vs 22 headings) | **Accepted, fixed, and the disagreement diagnosed.** The whole paragraph is now a table with the counting method stated, and it explains the trap that caught both of them: the plugin emits two spans per source marker, and ''%%~~DISCUSSION~~%%'' adds a heading. Third time | |
| | | **"Every call returned a benign empty value rather than throwing" is contradicted by the page's own committed probe output** — ''sharedStorage.worklet.addModule()'' throws ''OperationError'' in all four configurations, and the illustrative code box on the page had silently dropped that line | **Accepted, fixed.** The eighth call is back in the box, with the reason (the probe server returns ''text/html'' for every path, so the worklet module fails a MIME check — an artefact of the probe, not of the API) and a note that it was trimmed for one revision | |
| | | **The headers table overclaims**: ''Attribution-Reporting-Register-Source'' names a ''destination'' field; MDN documents no "reporting origin" field, which is implicit in the sending origin | **Accepted, fixed** | |
| | | **The bisect window is wider than necessary.** The removal landed in one commit, ''96e032552f'', 2026-04-02, "Roll protocol to r1608973"; the last commit with the symbols is ''1abe750809'', 2026-03-25 | **Accepted, fixed.** Both re-reviewers found the same commit independently. The page now names it | |
| | | The page's "which partition by default" gloss on Firefox and Safari is not literally in ''bahrami2025_cookieguard'' | **Accepted, fixed.** The gloss is now marked as ours and attributed to [[privacy:browser_storage]] instead | |
| | | The new telemetry section had no provenance trail | **Accepted, fixed** — this subsection | |
| | | ''%%--privacy-sandbox-enrollment-overrides%%'' could not be confirmed against Chromium source (code search needed auth); corroborated only by Google's own docs and by the fact that this run's own probe passes it without error | **Accepted as a limitation, recorded.** The switch is used in ''sandbox/ps_call_probe.mjs'' and Chromium does not reject it, which is weaker than a source citation | |
| | | ''w3.org/TR/attribution/'' returns 403 to ''curl'' but 200 to a browser-grade fetch; Bugzilla rejects bare ''HEAD'' | **Noted.** Neither is a dead link; recorded for future link-checkers | |
| | |
| | Everything else in both re-reviews checked out: the fold fix lost exactly the one true positive already admitted and no more (179 of 180 case-insensitive extras in the Protected Audience family are "full-fledged"), every regenerated table matches a fresh script run byte for byte, the published code block is byte-identical to the committed script and reproduces its seven events, the mutation test still drops it to three, and all 34 external claims re-fetched today were confirmed verbatim. |
| | |
| | ===== Removal-status refresh, 2026-09-27 ===== |
| | |
| | * Run date: **2026-09-27** (UTC). Authoring agent: Claude Opus 5.5, executing the drain item "privacy_sandbox removal slippage 2026-09-23". Review passes are logged in [[#Review log, 2026-09-27 refresh]]. |
| | * Trigger: the external-currency reviewer of [[privacy:advertising]] (Finding 4, 2026-09-23). It noted that Chrome stable was M154 while chromestatus 6552486106234880 still read //Proposed//, M153, and asked this page to show the slip. Chrome 150's release notes list no removals, and Topics has no dedicated removal entry. |
| | * Scope: the removal-status statements only. **No corpus figure was touched**; the report script, folding and quote-check sections above are from 2026-09-01 and were not re-run. The 2026-09-01 browser measurements stay on the content page, now labelled as pre-removal. Where one was wrong, it is corrected (see below). |
| | * Method: rather than restate a third status source, **measure the binaries**. Every status source was re-fetched, and fourteen builds from 151 to 156 were probed. Four are Google Chrome for Testing; the first draft probed only ten Chromium builds (see the review log). |
| | |
| | ==== What the 2026-09-01 page said that did not hold ==== |
| | |
| | ^ Statement on the page until 2026-09-27 ^ What the refresh found ^ Change ^ |
| | | "The removal milestone for Topics, Protected Audience, Attribution Reporting, Shared Storage, Related Website Sets and ''requestStorageAccessFor'' is **M153**" | For **Topics** there is no Chrome Platform Status removal entry at all. The chromestatus search for "Topics", "browsingTopics" and "Deprecate and remove" returns 0 Feature-removal entries naming Topics, out of 53 Feature-removal entries in the last query. The Topics ship entry, 5680923054964736, has no deprecation stage. This log's 2026-09-01 notes say "it is the removal that moved M150 → M152 → M153" without naming the entry the M153 came from. For the rest, M153 is the ''460'' (removal ship) stage of entries whose summary still reads //Proposed//. The binaries changed at 152, 153 and 154 | Top box and table rewritten around the measurement; M153 is described as a status label | |
| | | "Removal is a staircase … the current entry says M153" (Topics) | Same: no Topics entry exists to say M153 | Rewritten | |
| | | "Chromium 151.0.7922.34 exposes and answers every one of the APIs" | True of **chrome-headless-shell** 151, which is what Playwright's ''headless: true'' launches and what ''ps_call_probe.mjs'' ran. The **full** Chromium 151 of the same Playwright release, launched through ''executablePath'', rejects ''sharedStorage.set()'' ("sharedStorage is disabled") and runs no auction. Found by accident: the first milestone-probe run passed ''executablePath: chromium.executablePath()'' for its baseline and disagreed with the committed ''ps_call_probe-output.txt'' | The presence section and "What to Report" now say which kind of binary. Puppeteer's 2026-09-01 row was a full-Chromium presence probe, so it is unaffected | |
| | | Fenced Frames "Removal proposed, M155" | Entry 6366274495053824 now says **M156**, updated 2026-09-24 | Updated | |
| | | HTTP headers: "no dependence on the milestone that kills the CDP surface" | ''Attribution-Reporting-Eligible'' was sent by both 151 builds and by none of the twelve builds from 152 to 156 | Rewritten: the header dies with the API | |
| | | CDP table: ''getRelatedWebsiteSets'' present at tip-of-tree | ''devtools-protocol'' ''master'' on 2026-09-27 has only ''runBounceTrackingMitigations'' | Row split | |
| | | "the window to measure a deployed Attribution Reporting API in Chrome is days" | The API went inert at 152 (no header, Permissions-Policy feature unknown) | "The window has closed in current Chrome" | |
| | | Topics footnote attributed the plan to "Yao Xia" | The thread names the author "Yao Xiao" (40 occurrences in the fetched HTML, none of "Yao Xia" alone) | Footnote replaced by one quoting the Protected Audience thread's plan message, signed "Paul", and linking all five threads | |
| | | Timeline: "2026-09-08 M153 stable date: the targeted removal milestone for …" | Replaced by what was measured at each of M152, M153 and M154 | Rows rewritten, two added | |
| | | "Puppeteer was pointed at the same Chromium binary via ''chromium.executablePath()'', so this is a comparison of the two libraries' default flag sets, not of two browser builds" (content page and this page's run record) | ''chromium.executablePath()'' is the full Chromium; Playwright's default is chrome-headless-shell. The 2026-09-01 comparison was two binaries. Its result stands: presence and Permissions-Policy answers agree in builds [1] and [2]. **Missed by this refresh's first draft; the generic reviewer caught it** | Both sentences corrected | |
| | |
| | ==== Status sources as of 2026-09-27 ==== |
| | |
| | ^ Source ^ What it says ^ How it was read ^ Used as ^ |
| | | ''chromiumdash'' ''fetch_releases'' / ''fetch_milestone_schedule'' | Stable = **M154**, 154.0.8037.57. Stable dates: M152 2026-08-25, M153 2026-09-08, M154 2026-09-22, M155 2026-10-06, M156 2026-10-20 | JSON API | Dates on the page | |
| | | Chrome Platform Status, 22 per-feature entries | Every removal entry //Proposed//. Removal stage (''460'') at desktop 153 for Protected Audience, Attribution Reporting, Shared Storage, RWS and ''requestStorageAccessFor''; 152 for Private Aggregation; **156** for Fenced Frames. **No Topics removal entry.** The CHIPS WebView entry is WebView-only | Per-feature endpoint, every ''stages[]'' element printed. Stage names come from ''internals/core_enums.py'' on ''GoogleChrome/chromium-dashboard'' ''main'' (410 plan, 430 dev trial, 450 deprecation trial, 460 ship, 470 remove code) | "What the status label says" column only. **The summary ''status'' field is not used as evidence**: it says //Proposed// for removals the release notes list. The stage-460 milestones are quoted, as labels | |
| | | ''developer.chrome.com/release-notes/150''–''154'' | 150: "There are no deprecations or removals in this release." 151: macOS 12 and a FontFaceSet IDL change. 152: "Remove Private Aggregation API … is deprecated and removed". 153: five "Deprecate and remove" headings, each worded "planned for deprecation and removal". **154: no Deprecations section at all.** 155/156: 404 (not yet stable) | Fetched with ''?hl=en'' and ''accept-language: en-US''. **Without them this run got the release notes in Hebrew** and the status page in Spanish; Google's devsite localises by vantage | Release-notes column; the M154 gap is published | |
| | | blink-dev intents: Protected Audience ''k_nubsMb97g'', Topics ''_R85yctz4Rs'', Attribution Reporting ''4K2RRt6VYCQ'', Shared Storage ''uh5Ke6qyegc'', Private Aggregation ''Ld7avyD0U0Q'' | The same four-step plan in the first four threads (2026-06-11/12), and "no need to replace it with a stub" for Private Aggregation. September updates only on PA (09-07 question, 09-23 request for 100%, 09-24 correction: "~ 1% usage", 10% through Oct 12, 100% from Oct 26) and Topics (09-24: 1% on M153+, "current usage is at 2%", 10% through Oct 15, 100% after). ARA's newest message is 2026-07-01, SS's 2026-07-07, PrivAgg's 2026-07-08 | Google Groups HTML fetched with ''curl''/''fetch''; tags stripped, whitespace collapsed, needles checked by the script. Message dates are Google Groups' display dates and may be off by one day at a time-zone boundary. "Newest" is the newest date stamp in the server-rendered thread page, not checked against Google Groups' own message count; the script prints the stamp count per thread, and it fails if the newest date moves | Rollout column and the telemetry additions | |
| | | ''privacysandbox.google.com/overview/status'' | "Last updated: August 14, 2026", unchanged since 2026-09-01. The Shared Storage row (removed) sits under //Deprecate and remove// with Fenced Frames (present) | Table parsed, not summarised | Footnote only. It cannot tell a removed API from a present one | |
| | | Chrome for Testing (''googlechromelabs.github.io/chrome-for-testing'') | ''linux-arm64'' builds exist from 153 on: 153.0.8010.52, 154.0.8037.57, 155.0.8059.12, 156.0.8075.0. 151 and 152 are ''linux64'' (x86-64) only | The first pass read only the ''linux64'' column. It downloaded those four x86-64 zips, which fail here (''rosetta error: failed to open elf at /lib64/ld-linux-x86-64.so.2''), and concluded "no Google Chrome binary can run on this host". **The external-currency reviewer caught this.** The ''linux-arm64'' zips were then downloaded (SHA-256 below) | **Used**: four probe builds, and the only Google-built ones. The x86-64 zips were deleted | |
| | | Debian ''bookworm-security'' arm64 ''chromium'' + ''chromium-common'' 153.0.8010.52-1~deb12u1 and 154.0.8037.57-1~deb12u1 | The two stable releases, built from Chromium source | Downloaded from ''security.debian.org/debian-security/pool/updates/main/c/chromium/'', unpacked with ''dpkg -x''. SHA-256 of the four ''.deb'' files are listed below the table. 152.0.7977.82-1~deb12u1 is the container's installed package | Probe builds | |
| | | Playwright prereleases | ''playwright-core'' ''browsers.json'' maps 1.63.0-alpha-2026-08-23 to headless shell 152.0.7977.54, 1.63.0-alpha-2026-08-29 to 153.0.8010.12, 1.64.0-alpha-1789764292000 to 154.0.8037.0 and 1.64.0-alpha-2026-09-27 to 155.0.8059.12 | ''npm pack'' each, read ''browsers.json'', install with that package's own ''cli.js'' into a scratch ''PLAYWRIGHT_BROWSERS_PATH'' | Probe builds. They are **pre-stable** builds of each milestone and are labelled as such | |
| | |
| | SHA-256 of the Debian packages and the Chrome for Testing zips: |
| | |
| | <code> |
| | a7bba2726939dfa0484dee3f9c4da46761e32a7b0ee97ffc7040be1582dc5824 chromium_153.0.8010.52-1~deb12u1_arm64.deb |
| | 9e5f90c9643dcbe2964e16d5972e4e7f76c18b1cad7845855116a4890895884d chromium-common_153.0.8010.52-1~deb12u1_arm64.deb |
| | 7ac805587eadc495567342826ec5043b7a9422a5c52b474e469cb23532e1ee1d chromium_154.0.8037.57-1~deb12u1_arm64.deb |
| | 415762c28547f542b7928a093015ed2793de89ff88db47083ee1ef4280bfa435 chromium-common_154.0.8037.57-1~deb12u1_arm64.deb |
| | 794441f3254273eb30d710b3eaab3cd1c7bbf1c88a40275470f6cee350881ce5 chrome-for-testing 153.0.8010.52 linux-arm64/chrome-linux-arm64.zip |
| | da83171e552650df34272a9c51f62182bae88d467d1ac19c92dd97917dfa0bca chrome-for-testing 154.0.8037.57 linux-arm64/chrome-linux-arm64.zip |
| | bf94336ee2e3edb1279da28a74a744958ba10741e5994351610bc19028482b0b chrome-for-testing 155.0.8059.12 linux-arm64/chrome-linux-arm64.zip |
| | f10960090a52d557b5bcc2803a30e3a692852589cb4f37649e7f2d724fd4c0a2 chrome-for-testing 156.0.8075.0 linux-arm64/chrome-linux-arm64.zip |
| | </code> |
| | |
| | ==== Milestone probe, 2026-09-27 ==== |
| | |
| | ''sandbox/ps_milestone_probe.mjs'' runs, in each build, the presence expressions of ''ps_probe.mjs'' and the calls of ''ps_call_probe.mjs''. It adds two probes of its own, both added after the generic review. ''document.featurePolicy.features()'' membership distinguishes a policy feature the browser no longer knows from one it knows but does not grant; it agrees with ''allowsFeature()'' in all 14 builds. A ''fetch()'' with ''browsingTopics: true'' provokes ''Sec-Browsing-Topics'', which is sent only by the two 151 builds. It lifts both at run time with a regex, so it cannot drift from the published probes. It also runs the auction fixture of ''ps_cdp_probe.mjs'', its bidding, decision and worklet scripts lifted the same way. Evidence comes from the server's request log, because the CDP events that probe relied on no longer exist from 152. Finally it reads each binary's own ''/json/protocol''. |
| | |
| | Two things had to be solved to run it, and both are worth the next run knowing: |
| | |
| | * **Debian's Chromium can be driven by Playwright.** It aborts at launch with ''%%chrome_crashpad_handler: --database is required%%''. That is the crash the workdir README records as "Playwright cannot drive /usr/bin/chromium". Pointing ''executablePath'' at the real binary, ''/usr/lib/chromium/chromium'', is not enough on its own. Setting ''BREAKPAD_DUMP_LOCATION'' in the launch environment fixes it. |
| | * **Chrome for Testing runs here only from 153**, and only as its ''linux-arm64'' build (see the table above). Its four builds agree with Debian's Chromium on every row of the output. |
| | |
| | Positive control: build [1], headless shell 151, runs the auction to a ''urn:uuid'' and fetches ''/bid.js'', ''/decide.js'', ''/bid.js''. It also sends ''Attribution-Reporting-Eligible'' and fetches the Shared Storage worklet. Every "stopped at 152" statement on the content page is a difference from that control in a build of the same kind: headless shell 152.0.7977.54, build [3]. Full Chromium 151, build [2], already fails the auction and Shared Storage rows, so for those two APIs no full-Chromium build shows the change. The first draft said "from M152" without that qualifier, and the figures reviewer caught it. |
| | |
| | Controls re-run unchanged the same day: ''ps_probe.mjs'' (output identical to 2026-09-01 except the date line), ''ps_call_probe.mjs'' (identical), ''ps_cdp_probe.mjs'' (the same seven events, differing only in ids and timestamps), ''ps_cdp_surface.mjs'' (the 151 column identical; ''master'' lost ''getRelatedWebsiteSets''). |
| | |
| | <file bash run_ps_milestone_probe.sh> |
| | #!/usr/bin/env bash |
| | # Exact invocation behind ps_milestone_probe-output.txt (2026-09-27). |
| | # Builds: Playwright 1.62.1's bundled pair (chrome-headless-shell and Chromium, |
| | # both 151.0.7922.34); Debian bookworm-security arm64 Chromium 152 (installed), |
| | # 153.0.8010.52 and 154.0.8037.57 (the two stable releases; .deb unpacked with |
| | # dpkg -x under ps0927/deb/, sha256 in the provenance page); and the pair bundled |
| | # by playwright-core 1.64.0-alpha-2026-09-27 (155.0.8059.12, beta), installed |
| | # with its own cli.js into ps0927/pwbrowsers. Headless shells for 152/153/154 |
| | # come from the Playwright prereleases that bundled them (1.63.0-alpha-2026-08-23 |
| | # -> 152.0.7977.54, 1.63.0-alpha-2026-08-29 -> 153.0.8010.12, |
| | # 1.64.0-alpha-1789764292000 -> 154.0.8037.0): these are pre-stable builds of |
| | # each milestone, not the stable patch, and are labelled as such. Google Chrome |
| | # for Testing linux-arm64 (published from 153.0.8001.0 on; no 152 exists) for |
| | # 153.0.8010.52, 154.0.8037.57 (the stable patches), 155.0.8059.12 (beta) and |
| | # 156.0.8075.0, unzipped under ps0927/cft/<version>/ (sha256 in the provenance |
| | # page). These are the only Google-branded builds in the ladder. |
| | set -euo pipefail |
| | W=/workspace/artifacts/wiki |
| | export PLAYWRIGHT_BROWSERS_PATH=/workspace/.playwright |
| | cd "$W/sandbox" |
| | node ps_milestone_probe.mjs \ |
| | "headless shell, Playwright 1.62.1 default=/workspace/.playwright/chromium_headless_shell-1234/chrome-linux/headless_shell" \ |
| | "Chromium, Playwright 1.62.1=/workspace/.playwright/chromium-1234/chrome-linux/chrome" \ |
| | "headless shell, Playwright 1.63.0-alpha-2026-08-23=$W/ps0927/pwbrowsers/chromium_headless_shell-1241/chrome-linux/headless_shell" \ |
| | "Chromium, Debian bookworm-security=/usr/lib/chromium/chromium" \ |
| | "headless shell, Playwright 1.63.0-alpha-2026-08-29=$W/ps0927/pwbrowsers/chromium_headless_shell-1243/chrome-headless-shell-linux-arm64/chrome-headless-shell" \ |
| | "Chromium, Debian bookworm-security=$W/ps0927/deb/153.0.8010.52/usr/lib/chromium/chromium" \ |
| | "Google Chrome for Testing=$W/ps0927/cft/153.0.8010.52/chrome-linux-arm64/chrome" \ |
| | "headless shell, Playwright 1.64.0-alpha-1789764292000=$W/ps0927/pwbrowsers/chromium_headless_shell-1246/chrome-headless-shell-linux-arm64/chrome-headless-shell" \ |
| | "Chromium, Debian bookworm-security=$W/ps0927/deb/154.0.8037.57/usr/lib/chromium/chromium" \ |
| | "Google Chrome for Testing=$W/ps0927/cft/154.0.8037.57/chrome-linux-arm64/chrome" \ |
| | "Chromium, Playwright 1.64.0-alpha-2026-09-27=$W/ps0927/pwbrowsers/chromium-1247/chrome-linux-arm64/chrome" \ |
| | "headless shell, Playwright 1.64.0-alpha-2026-09-27=$W/ps0927/pwbrowsers/chromium_headless_shell-1247/chrome-headless-shell-linux-arm64/chrome-headless-shell" \ |
| | "Google Chrome for Testing=$W/ps0927/cft/155.0.8059.12/chrome-linux-arm64/chrome" \ |
| | "Google Chrome for Testing=$W/ps0927/cft/156.0.8075.0/chrome-linux-arm64/chrome" |
| | </file> |
| | |
| | <file javascript ps_milestone_probe.mjs> |
| | // Has Chrome actually removed the Privacy Sandbox APIs, milestone by milestone? |
| | // |
| | // Chrome Platform Status can say "Proposed" after a removal has shipped, and |
| | // release notes can say "planned for deprecation and removal" in the milestone |
| | // that removes it. Neither is a measurement. This asks the binaries. |
| | // |
| | // Run with one label=executable per argument. This host is aarch64. The builds |
| | // used on 2026-09-27 were Playwright's bundled headless shells and Chromium, |
| | // Debian bookworm-security's arm64 Chromium packages unpacked with `dpkg -x` |
| | // (the real binary is usr/lib/chromium/chromium, not the /usr/bin/chromium |
| | // wrapper), and Google Chrome for Testing's linux-arm64 builds (153 onwards): |
| | // PLAYWRIGHT_BROWSERS_PATH=/workspace/.playwright node sandbox/ps_milestone_probe.mjs \ |
| | // 'Chromium (Debian)=/usr/lib/chromium/chromium' \ |
| | // 'Chromium (Debian)=ps0927/deb/153.0.8010.52/usr/lib/chromium/chromium' ... |
| | // The exact invocation used for the published output is in run_ps_milestone_probe.sh. |
| | // |
| | // Debian's binary aborts at launch with "chrome_crashpad_handler: --database is |
| | // required" under Playwright; setting BREAKPAD_DUMP_LOCATION gives the handler |
| | // its database and the browser starts. That is the whole fix. |
| | // |
| | // The presence expressions and the calls are read out of ps_probe.mjs and |
| | // ps_call_probe.mjs at run time, not copied, so this cannot drift from the |
| | // probes the page already publishes. An automation launch has no variations |
| | // seed, so what it measures is the code in the binary, never a field trial. |
| | import https from 'node:https'; |
| | import { execSync } from 'node:child_process'; |
| | import fs from 'node:fs'; |
| | import os from 'node:os'; |
| | import path from 'node:path'; |
| | import { fileURLToPath } from 'node:url'; |
| | import { chromium } from 'playwright'; |
| | |
| | const here = path.dirname(fileURLToPath(import.meta.url)); |
| | const lift = (file, name) => { |
| | const src = fs.readFileSync(path.join(here, file), 'utf8'); |
| | const m = src.match(new RegExp('const ' + name + ' = `([\\s\\S]*?)`;')); |
| | if (!m) throw new Error(`could not find const ${name} in ${file}`); |
| | return m[1]; |
| | }; |
| | const PROBE = lift('ps_probe.mjs', 'PROBE'); |
| | const CALLS = lift('ps_call_probe.mjs', 'CALLS'); |
| | // The auction fixture of ps_cdp_probe.mjs (bidding script, decision script, |
| | // worklet), served from an enrolled-by-override public-looking origin. Its CDP |
| | // events disappear with the CDP surface, so here the evidence is server-side: |
| | // an auction that runs fetches /bid.js and /decide.js. |
| | const BID = lift('ps_cdp_probe.mjs', 'BID'); |
| | const DEC = lift('ps_cdp_probe.mjs', 'DEC'); |
| | const WORKLET = lift('ps_cdp_probe.mjs', 'WORKLET'); |
| | |
| | // Arguments are label=executable. Label the binary kind: Playwright's default |
| | // `headless: true` launches chrome-headless-shell, not Chromium, and the two |
| | // do not answer the ads APIs the same way (see the output). |
| | const builds = process.argv.slice(2).map((a) => { |
| | const i = a.indexOf('='); |
| | if (i < 1) throw new Error(`argument must be label=executable, got ${a}`); |
| | const [label, exe] = [a.slice(0, i), a.slice(i + 1)]; |
| | if (!fs.existsSync(exe)) throw new Error(`no executable at ${exe} (${label})`); |
| | return [label, exe]; |
| | }); |
| | if (builds.length === 0) throw new Error('usage: ps_milestone_probe.mjs label=<chromium-executable> ...'); |
| | |
| | // localhost over HTTPS, so the page is a secure context. Localhost is exempt |
| | // from enrollment, which is what we want here: the question is whether the |
| | // code is in the binary, not whether an origin is attested. |
| | const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'psms-')); |
| | execSync( |
| | `openssl req -x509 -newkey rsa:2048 -nodes -keyout ${tmp}/k.pem -out ${tmp}/c.pem -days 2 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"`, |
| | { stdio: 'ignore' } |
| | ); |
| | // Every request the page causes is logged with the Privacy Sandbox request |
| | // headers, so a call that "returns" can be told apart from one that does work: |
| | // an auction that runs fetches its decision logic; an attribution-eligible |
| | // fetch carries Attribution-Reporting-Eligible. |
| | const HDRS = ['sec-browsing-topics', 'attribution-reporting-eligible', 'sec-shared-storage-writable', 'sec-fetch-dest']; |
| | let hits = []; |
| | const server = https.createServer( |
| | { key: fs.readFileSync(`${tmp}/k.pem`), cert: fs.readFileSync(`${tmp}/c.pem`) }, |
| | (req, res) => { |
| | hits.push(req.url + ' ' + HDRS.filter((h) => h in req.headers).map((h) => `${h}=${req.headers[h]}`).join(' ')); |
| | res.writeHead(200, { 'content-type': 'text/html' }); |
| | res.end('<!doctype html><meta charset=utf-8><title>ps</title>'); |
| | } |
| | ); |
| | await new Promise((r) => server.listen(8445, '127.0.0.1', r)); |
| | |
| | execSync( |
| | `openssl req -x509 -newkey rsa:2048 -nodes -keyout ${tmp}/k2.pem -out ${tmp}/c2.pem -days 2 -subj "/CN=probe.example" -addext "subjectAltName=DNS:probe.example"`, |
| | { stdio: 'ignore' } |
| | ); |
| | let auctionHits = []; |
| | const auctionServer = https.createServer( |
| | { key: fs.readFileSync(`${tmp}/k2.pem`), cert: fs.readFileSync(`${tmp}/c2.pem`) }, |
| | (req, res) => { |
| | auctionHits.push(req.url); |
| | const js = { 'content-type': 'application/javascript', 'ad-auction-allowed': 'true' }; |
| | if (req.url.startsWith('/bid.js')) return res.writeHead(200, js).end(BID); |
| | if (req.url.startsWith('/decide.js')) return res.writeHead(200, js).end(DEC); |
| | if (req.url.startsWith('/w.js')) return res.writeHead(200, js).end(WORKLET); |
| | if (req.url.startsWith('/ad.html')) return res.writeHead(200, { 'content-type': 'text/html' }).end('<b>ad</b>'); |
| | res.writeHead(200, { 'content-type': 'text/html' }).end('<!doctype html><meta charset=utf-8><title>ps</title>'); |
| | } |
| | ); |
| | await new Promise((r) => auctionServer.listen(8444, '127.0.0.1', r)); |
| | const AUCTION = `(async () => { |
| | const o = {}; |
| | const t = async (n, f) => { try { o[n] = 'ok ' + JSON.stringify(await f()); } catch (e) { o[n] = 'ERR ' + String(e.message).slice(0, 110); } }; |
| | await t('joinAdInterestGroup', () => navigator.joinAdInterestGroup({ |
| | owner: location.origin, name: 'probe', biddingLogicURL: location.origin + '/bid.js', |
| | ads: [{ renderURL: location.origin + '/ad.html', metadata: {} }], |
| | }, 3600)); |
| | await t('runAdAuction', () => navigator.runAdAuction({ |
| | seller: location.origin, decisionLogicURL: location.origin + '/decide.js', |
| | interestGroupBuyers: [location.origin], resolveToConfig: false, |
| | })); |
| | return o; |
| | })()`; |
| | |
| | // Two probes this script adds to the lifted ones. allowsFeature() is false both |
| | // for a policy feature the browser no longer knows and for one it knows but |
| | // does not grant, so print features() membership as well. And ps_call_probe.mjs |
| | // never provokes Sec-Browsing-Topics, so ask for it explicitly. |
| | const PS_FEATURES = ['browsing-topics', 'join-ad-interest-group', 'run-ad-auction', 'attribution-reporting', 'shared-storage', 'private-aggregation']; |
| | const EXTRA = `(async () => { |
| | const o = {}; |
| | const fp = document.featurePolicy; |
| | const known = fp && fp.features ? fp.features() : null; |
| | for (const f of ${JSON.stringify(PS_FEATURES)}) o['PP known:' + f] = known ? String(known.includes(f)) : 'no features()'; |
| | try { o["fetch(browsingTopics)"] = 'RETURNED ' + (await fetch('/t', { browsingTopics: true })).status; } |
| | catch (e) { o["fetch(browsingTopics)"] = (e && e.name ? e.name + ': ' : '') + String(e && e.message || e).slice(0, 150); } |
| | return o; |
| | })()`; |
| | |
| | const RE = /interest|shared|attribution|bounce|related|topic/i; |
| | const results = []; |
| | let port = 9340; |
| | for (const [label, exe] of builds) { |
| | port += 1; |
| | const b = await chromium.launch({ |
| | headless: true, |
| | executablePath: exe, |
| | args: [`--remote-debugging-port=${port}`], |
| | env: { ...process.env, BREAKPAD_DUMP_LOCATION: tmp }, |
| | }); |
| | const version = b.version(); |
| | hits = []; |
| | const ctx = await b.newContext({ ignoreHTTPSErrors: true }); |
| | const p = await ctx.newPage(); |
| | await p.goto('https://localhost:8445/', { waitUntil: 'domcontentloaded' }); |
| | const presence = await p.evaluate(PROBE); |
| | const calls = await p.evaluate(CALLS); |
| | const extra = await p.evaluate(EXTRA); |
| | for (const [k, v] of Object.entries(extra)) (k.startsWith('PP known:') ? presence : calls)[k] = v; |
| | await p.waitForTimeout(2000); |
| | const requests = hits.slice(); |
| | const proto = await (await fetch(`http://127.0.0.1:${port}/json/protocol`)).json(); |
| | const st = proto.domains.find((d) => d.domain === 'Storage'); |
| | const cdp = { |
| | 'CDP Storage commands': st.commands.map((c) => c.name).filter((n) => RE.test(n)), |
| | 'CDP Storage events': st.events.map((e) => e.name).filter((n) => RE.test(n)), |
| | }; |
| | await b.close(); |
| | |
| | // Auction phase: the flag set ps_cdp_probe.mjs used on 2026-09-01. |
| | const b2 = await chromium.launch({ |
| | headless: true, |
| | executablePath: exe, |
| | env: { ...process.env, BREAKPAD_DUMP_LOCATION: tmp }, |
| | args: [ |
| | '--host-resolver-rules=MAP probe.example 127.0.0.1', |
| | '--ignore-certificate-errors', |
| | '--enable-features=PrivacySandboxAdsAPIsOverride', |
| | '--privacy-sandbox-enrollment-overrides=https://probe.example:8444', |
| | ], |
| | }); |
| | auctionHits = []; |
| | const ctx2 = await b2.newContext({ ignoreHTTPSErrors: true }); |
| | const p2 = await ctx2.newPage(); |
| | await p2.goto('https://probe.example:8444/', { waitUntil: 'domcontentloaded' }); |
| | const auction = await p2.evaluate(AUCTION); |
| | await p2.waitForTimeout(2500); |
| | auction['server saw'] = auctionHits.filter((u) => u !== '/' && u !== '/favicon.ico').join(' ') || '(nothing but the page)'; |
| | await b2.close(); |
| | results.push({ label, version, presence, calls, cdp, requests, auction }); |
| | } |
| | server.close(); |
| | auctionServer.close(); |
| | |
| | const cell = (v) => String(v).replace(/\s+/g, ' ').slice(0, 16).padEnd(16); |
| | console.log('probe run:', new Date().toISOString().slice(0, 10)); |
| | results.forEach((r, i) => console.log(` [${i + 1}] ${r.version.padEnd(14)} ${r.label}`)); |
| | for (const [title, key] of [['Presence (ps_probe.mjs PROBE, plus "PP known:" = featurePolicy.features() membership)', 'presence'], ['Calls on https://localhost (ps_call_probe.mjs CALLS, plus fetch(browsingTopics))', 'calls']]) { |
| | const keys = Object.keys(results[0][key]).filter((k) => k !== 'chrome'); |
| | for (const r of results.slice(1)) |
| | for (const k of Object.keys(r[key])) |
| | if (k !== 'chrome' && !keys.includes(k)) keys.push(k); |
| | const w = Math.max(...keys.map((k) => k.length)); |
| | console.log(`\n== ${title} ==`); |
| | console.log('expression'.padEnd(w) + results.map((r, i) => ' ' + cell(`[${i + 1}] ${r.version.split('.')[0]}`)).join('')); |
| | console.log('-'.repeat(w) + results.map(() => ' ' + '-'.repeat(16)).join('')); |
| | for (const k of keys) |
| | console.log(k.padEnd(w) + results.map((r) => ' ' + cell(k in r[key] ? r[key][k] : '(key absent)')).join('')); |
| | } |
| | console.log('\n== Full call results (untruncated) =='); |
| | results.forEach((r, i) => { |
| | console.log(`-- [${i + 1}] ${r.version} ${r.label}`); |
| | for (const [k, v] of Object.entries(r.calls)) console.log(` ${k.padEnd(38)} ${v}`); |
| | }); |
| | console.log('\n== Every request the page caused (path + Privacy Sandbox request headers) =='); |
| | results.forEach((r, i) => { |
| | console.log(`-- [${i + 1}] ${r.version} ${r.label}`); |
| | for (const h of r.requests) console.log(` ${h}`); |
| | }); |
| | console.log('\n== Protected Audience auction with a served bidding and decision script (probe.example, enrollment override) =='); |
| | results.forEach((r, i) => { |
| | console.log(`-- [${i + 1}] ${r.version} ${r.label}`); |
| | for (const [k, v] of Object.entries(r.auction)) console.log(` ${k.padEnd(20)} ${v}`); |
| | }); |
| | console.log('\n== CDP Storage domain, Privacy Sandbox names (from each binary\'s /json/protocol) =='); |
| | results.forEach((r, i) => { |
| | console.log(`-- [${i + 1}] ${r.version} ${r.label}`); |
| | for (const [k, v] of Object.entries(r.cdp)) console.log(` ${k} (${v.length}): ${v.join(', ') || '(none)'}`); |
| | }); |
| | </file> |
| | |
| | Its real, unedited output: |
| | |
| | <file text ps_milestone_probe-output.txt> |
| | probe run: 2026-09-27 |
| | [1] 151.0.7922.34 headless shell, Playwright 1.62.1 default |
| | [2] 151.0.7922.34 Chromium, Playwright 1.62.1 |
| | [3] 152.0.7977.54 headless shell, Playwright 1.63.0-alpha-2026-08-23 |
| | [4] 152.0.7977.82 Chromium, Debian bookworm-security |
| | [5] 153.0.8010.12 headless shell, Playwright 1.63.0-alpha-2026-08-29 |
| | [6] 153.0.8010.52 Chromium, Debian bookworm-security |
| | [7] 153.0.8010.52 Google Chrome for Testing |
| | [8] 154.0.8037.0 headless shell, Playwright 1.64.0-alpha-1789764292000 |
| | [9] 154.0.8037.57 Chromium, Debian bookworm-security |
| | [10] 154.0.8037.57 Google Chrome for Testing |
| | [11] 155.0.8059.12 Chromium, Playwright 1.64.0-alpha-2026-09-27 |
| | [12] 155.0.8059.12 headless shell, Playwright 1.64.0-alpha-2026-09-27 |
| | [13] 155.0.8059.12 Google Chrome for Testing |
| | [14] 156.0.8075.0 Google Chrome for Testing |
| | |
| | == Presence (ps_probe.mjs PROBE, plus "PP known:" = featurePolicy.features() membership) == |
| | expression [1] 151 [2] 151 [3] 152 [4] 152 [5] 153 [6] 153 [7] 153 [8] 154 [9] 154 [10] 154 [11] 155 [12] 155 [13] 155 [14] 156 |
| | --------------------------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- |
| | document.browsingTopics function function function function function function function function function function function function function function |
| | navigator.joinAdInterestGroup function function function function function function function function function function function function function function |
| | navigator.runAdAuction function function function function function function function function function function function function function function |
| | navigator.leaveAdInterestGroup function function function function function function function function function function function function function function |
| | window.sharedStorage object object object object undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined |
| | sharedStorage.selectURL function function function function n/a n/a n/a n/a n/a n/a n/a n/a n/a n/a |
| | HTMLFencedFrameElement function function function function function function function function function function function function function function |
| | document.hasPrivateToken function function function function function function function function function function function function function function |
| | document.hasRedemptionRecord function function function function function function function function function function function function function function |
| | document.requestStorageAccess function function function function function function function function function function function function function function |
| | document.requestStorageAccessFor function function function function function function function undefined undefined undefined undefined undefined undefined undefined |
| | window.IdentityCredential (FedCM) function function function function function function function function function function function function function function |
| | navigator.userAgentData object object object object object object object object object object object object object object |
| | navigator.cookieDeprecationLabel undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined |
| | cookieStore object object object object object object object object object object object object object object |
| | PP:browsing-topics true true true true true true true true true true true true true true |
| | PP:join-ad-interest-group true true true true false false false false false false false false false false |
| | PP:run-ad-auction true true true true false false false false false false false false false false |
| | PP:attribution-reporting true true false false false false false false false false false false false false |
| | PP:shared-storage true true true true false false false false false false false false false false |
| | PP:private-aggregation true true true true false false false false false false false false false false |
| | HTMLImageElement.attributionSrc yes yes yes yes yes yes yes yes yes yes yes yes yes yes |
| | HTMLAnchorElement.attributionSrc yes yes yes yes yes yes yes yes yes yes yes yes yes yes |
| | PP known:browsing-topics true true true true true true true true true true true true true true |
| | PP known:join-ad-interest-group true true true true false false false false false false false false false false |
| | PP known:run-ad-auction true true true true false false false false false false false false false false |
| | PP known:attribution-reporting true true false false false false false false false false false false false false |
| | PP known:shared-storage true true true true false false false false false false false false false false |
| | PP known:private-aggregation true true true true false false false false false false false false false false |
| | |
| | == Calls on https://localhost (ps_call_probe.mjs CALLS, plus fetch(browsingTopics)) == |
| | expression [1] 151 [2] 151 [3] 152 [4] 152 [5] 153 [6] 153 [7] 153 [8] 154 [9] 154 [10] 154 [11] 155 [12] 155 [13] 155 [14] 156 |
| | --------------------------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- |
| | document.browsingTopics() RETURNED [] RETURNED [] NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro NotSupportedErro |
| | navigator.joinAdInterestGroup() RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin |
| | navigator.runAdAuction() RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null RETURNED null |
| | sharedStorage.set() RETURNED undefin OperationError: OperationError: OperationError: TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno |
| | sharedStorage.worklet.addModule() OperationError: OperationError: OperationError: OperationError: TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno TypeError: Canno |
| | document.hasPrivateToken() RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false RETURNED false |
| | document.requestStorageAccess() RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin RETURNED undefin |
| | fetch(attributionReporting) RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 RETURNED 200 |
| | |
| | == Full call results (untruncated) == |
| | -- [1] 151.0.7922.34 headless shell, Playwright 1.62.1 default |
| | document.browsingTopics() RETURNED [] |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() RETURNED undefined |
| | sharedStorage.worklet.addModule() OperationError: Rejecting load of https://localhost:8445/w.js due to unexpected MIME type. |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [2] 151.0.7922.34 Chromium, Playwright 1.62.1 |
| | document.browsingTopics() RETURNED [] |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() OperationError: sharedStorage is disabled |
| | sharedStorage.worklet.addModule() OperationError: sharedStorage.worklet.addModule is disabled because either sharedStorage is disabled or both sharedStorage.selectURL and privateAggregation are disabl |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [3] 152.0.7977.54 headless shell, Playwright 1.63.0-alpha-2026-08-23 |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() OperationError: Failed to execute 'set' on 'SharedStorage': Shared Storage is disabled. |
| | sharedStorage.worklet.addModule() OperationError: Failed to execute 'addModule' on 'SharedStorageWorklet': Shared Storage is disabled. |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [4] 152.0.7977.82 Chromium, Debian bookworm-security |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() OperationError: Failed to execute 'set' on 'SharedStorage': Shared Storage is disabled. |
| | sharedStorage.worklet.addModule() OperationError: Failed to execute 'addModule' on 'SharedStorageWorklet': Shared Storage is disabled. |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [5] 153.0.8010.12 headless shell, Playwright 1.63.0-alpha-2026-08-29 |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [6] 153.0.8010.52 Chromium, Debian bookworm-security |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [7] 153.0.8010.52 Google Chrome for Testing |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [8] 154.0.8037.0 headless shell, Playwright 1.64.0-alpha-1789764292000 |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [9] 154.0.8037.57 Chromium, Debian bookworm-security |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [10] 154.0.8037.57 Google Chrome for Testing |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [11] 155.0.8059.12 Chromium, Playwright 1.64.0-alpha-2026-09-27 |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [12] 155.0.8059.12 headless shell, Playwright 1.64.0-alpha-2026-09-27 |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [13] 155.0.8059.12 Google Chrome for Testing |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | -- [14] 156.0.8075.0 Google Chrome for Testing |
| | document.browsingTopics() NotSupportedError: Failed to execute 'browsingTopics' on 'Document': document.browsingTopics() is deprecated and has been removed. |
| | navigator.joinAdInterestGroup() RETURNED undefined |
| | navigator.runAdAuction() RETURNED null |
| | sharedStorage.set() TypeError: Cannot read properties of undefined (reading 'set') |
| | sharedStorage.worklet.addModule() TypeError: Cannot read properties of undefined (reading 'worklet') |
| | document.hasPrivateToken() RETURNED false |
| | document.requestStorageAccess() RETURNED undefined |
| | fetch(attributionReporting) RETURNED 200 |
| | fetch(browsingTopics) RETURNED 200 |
| | |
| | == Every request the page caused (path + Privacy Sandbox request headers) == |
| | -- [1] 151.0.7922.34 headless shell, Playwright 1.62.1 default |
| | / sec-fetch-dest=document |
| | /w.js sec-fetch-dest=sharedstorageworklet |
| | /x attribution-reporting-eligible=event-source;navigation-source sec-fetch-dest=empty |
| | /t sec-browsing-topics=();p=P0000000000000000000000000000000 sec-fetch-dest=empty |
| | -- [2] 151.0.7922.34 Chromium, Playwright 1.62.1 |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x attribution-reporting-eligible=event-source=navigation-source sec-fetch-dest=empty |
| | /t sec-browsing-topics=();p=P0000000000000000000000000000000 sec-fetch-dest=empty |
| | -- [3] 152.0.7977.54 headless shell, Playwright 1.63.0-alpha-2026-08-23 |
| | / sec-fetch-dest=document |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [4] 152.0.7977.82 Chromium, Debian bookworm-security |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [5] 153.0.8010.12 headless shell, Playwright 1.63.0-alpha-2026-08-29 |
| | / sec-fetch-dest=document |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [6] 153.0.8010.52 Chromium, Debian bookworm-security |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [7] 153.0.8010.52 Google Chrome for Testing |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [8] 154.0.8037.0 headless shell, Playwright 1.64.0-alpha-1789764292000 |
| | / sec-fetch-dest=document |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [9] 154.0.8037.57 Chromium, Debian bookworm-security |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [10] 154.0.8037.57 Google Chrome for Testing |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [11] 155.0.8059.12 Chromium, Playwright 1.64.0-alpha-2026-09-27 |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [12] 155.0.8059.12 headless shell, Playwright 1.64.0-alpha-2026-09-27 |
| | / sec-fetch-dest=document |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [13] 155.0.8059.12 Google Chrome for Testing |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | -- [14] 156.0.8075.0 Google Chrome for Testing |
| | / sec-fetch-dest=document |
| | /favicon.ico sec-fetch-dest=image |
| | /x sec-fetch-dest=empty |
| | /t sec-fetch-dest=empty |
| | |
| | == Protected Audience auction with a served bidding and decision script (probe.example, enrollment override) == |
| | -- [1] 151.0.7922.34 headless shell, Playwright 1.62.1 default |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok "urn:uuid:3012660e-f15c-4b71-a739-523ece3b26a4" |
| | server saw /bid.js /decide.js /bid.js |
| | -- [2] 151.0.7922.34 Chromium, Playwright 1.62.1 |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [3] 152.0.7977.54 headless shell, Playwright 1.63.0-alpha-2026-08-23 |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [4] 152.0.7977.82 Chromium, Debian bookworm-security |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [5] 153.0.8010.12 headless shell, Playwright 1.63.0-alpha-2026-08-29 |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [6] 153.0.8010.52 Chromium, Debian bookworm-security |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [7] 153.0.8010.52 Google Chrome for Testing |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [8] 154.0.8037.0 headless shell, Playwright 1.64.0-alpha-1789764292000 |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [9] 154.0.8037.57 Chromium, Debian bookworm-security |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [10] 154.0.8037.57 Google Chrome for Testing |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [11] 155.0.8059.12 Chromium, Playwright 1.64.0-alpha-2026-09-27 |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [12] 155.0.8059.12 headless shell, Playwright 1.64.0-alpha-2026-09-27 |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [13] 155.0.8059.12 Google Chrome for Testing |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | -- [14] 156.0.8075.0 Google Chrome for Testing |
| | joinAdInterestGroup ok undefined |
| | runAdAuction ok null |
| | server saw (nothing but the page) |
| | |
| | == CDP Storage domain, Privacy Sandbox names (from each binary's /json/protocol) == |
| | -- [1] 151.0.7922.34 headless shell, Playwright 1.62.1 default |
| | CDP Storage commands (12): getInterestGroupDetails, setInterestGroupTracking, setInterestGroupAuctionTracking, getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (5): interestGroupAccessed, interestGroupAuctionEventOccurred, interestGroupAuctionNetworkRequestCreated, sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [2] 151.0.7922.34 Chromium, Playwright 1.62.1 |
| | CDP Storage commands (12): getInterestGroupDetails, setInterestGroupTracking, setInterestGroupAuctionTracking, getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (5): interestGroupAccessed, interestGroupAuctionEventOccurred, interestGroupAuctionNetworkRequestCreated, sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [3] 152.0.7977.54 headless shell, Playwright 1.63.0-alpha-2026-08-23 |
| | CDP Storage commands (9): getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (2): sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [4] 152.0.7977.82 Chromium, Debian bookworm-security |
| | CDP Storage commands (9): getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (2): sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [5] 153.0.8010.12 headless shell, Playwright 1.63.0-alpha-2026-08-29 |
| | CDP Storage commands (9): getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (2): sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [6] 153.0.8010.52 Chromium, Debian bookworm-security |
| | CDP Storage commands (9): getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (2): sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [7] 153.0.8010.52 Google Chrome for Testing |
| | CDP Storage commands (9): getSharedStorageMetadata, getSharedStorageEntries, setSharedStorageEntry, deleteSharedStorageEntry, clearSharedStorageEntries, resetSharedStorageBudget, setSharedStorageTracking, runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (2): sharedStorageAccessed, sharedStorageWorkletOperationExecutionFinished |
| | -- [8] 154.0.8037.0 headless shell, Playwright 1.64.0-alpha-1789764292000 |
| | CDP Storage commands (2): runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (0): (none) |
| | -- [9] 154.0.8037.57 Chromium, Debian bookworm-security |
| | CDP Storage commands (2): runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (0): (none) |
| | -- [10] 154.0.8037.57 Google Chrome for Testing |
| | CDP Storage commands (2): runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (0): (none) |
| | -- [11] 155.0.8059.12 Chromium, Playwright 1.64.0-alpha-2026-09-27 |
| | CDP Storage commands (2): runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (0): (none) |
| | -- [12] 155.0.8059.12 headless shell, Playwright 1.64.0-alpha-2026-09-27 |
| | CDP Storage commands (2): runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (0): (none) |
| | -- [13] 155.0.8059.12 Google Chrome for Testing |
| | CDP Storage commands (2): runBounceTrackingMitigations, getRelatedWebsiteSets |
| | CDP Storage events (0): (none) |
| | -- [14] 156.0.8075.0 Google Chrome for Testing |
| | CDP Storage commands (1): runBounceTrackingMitigations |
| | CDP Storage events (0): (none) |
| | </file> |
| | |
| | ==== External checks, 2026-09-27 ==== |
| | |
| | ''scripts/external_checks_privacy_sandbox.mjs'' is new. The 2026-09-01 run verified its sources by hand and left no re-runnable script, which is why this refresh had to rediscover the 22 feature ids from the search API. It exits non-zero on any FAILED line: a counter and an exit gate, not a grep. **Mutation test:** ''MUTATE=1'' corrupts one check in each of sections 2–6. It also shifts one stated expectation, the Shared Storage thread's newest date. It printed 10 FAILED lines and exited 1: 1 chromestatus name, 1 release-notes phrase, 2 blink-dev phrases, 1 thread-date expectation, 1 retirement-blog phrase and 4 GitHub ''archived'' assertions. The clean run exits 0. Every value the content page states — the four schedule dates it prints, removal-stage milestones, zero Topics removal entries, the release-notes headings for 152–154, each thread's newest date, the ''linux-arm64'' availability per milestone, the tip-of-tree CDP commands — is in the script's ''EXPECT'' and **fails the run when it changes**. The first version only printed several of them next to "OK", and the generic reviewer caught that. Lines that only report are marked INFO. |
| | |
| | <file javascript external_checks_privacy_sandbox.mjs> |
| | // Re-fetches every non-corpus status fact privacy:privacy_sandbox leans on and |
| | // prints what the primary source says today. Written 2026-09-27, when the page's |
| | // "removal milestone M153" statement had gone stale (chromestatus still said |
| | // Proposed while stable was M154). |
| | // |
| | // node scripts/external_checks_privacy_sandbox.mjs > scripts/external_checks_privacy_sandbox-output.txt 2>&1 |
| | // |
| | // Every check prints OK or FAILED. FAILED increments a counter and the process |
| | // exits 1 if the counter is non-zero — the gate is at the bottom, not a grep. |
| | // Where the page states a value (a removal milestone, "no Topics entry", "no |
| | // thread update after July", "M154 lists no removals"), the value is in EXPECT |
| | // below and a change FAILS the run: it means the page needs re-reading, not |
| | // that the fetch broke. Lines that only report are marked INFO, not OK. |
| | // MUTATE=1 corrupts one check in each of sections 2-6 and one EXPECT value, to |
| | // prove those sections can fail; its output is kept beside this file. Section 1 |
| | // asserts the four schedule dates the page prints and reports the rest as INFO. |
| | // |
| | // Google's devsite pages localise by vantage, not by header alone: without |
| | // accept-language this run got Hebrew release notes and a Spanish status page. |
| | // Every Google URL below also carries ?hl=en. |
| | // |
| | // Chrome Platform Status: always the per-feature endpoint, and every stage is |
| | // printed. The summary `browsers.chrome.status` collapses a lifecycle into one |
| | // label and was still "Proposed" for removals Chrome's own release notes list. |
| | import fs from 'node:fs'; |
| | |
| | const UA = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0 Safari/537.36'; |
| | const MUTATE = process.env.MUTATE === '1'; |
| | const OUT = 'out/ps/ext'; |
| | fs.mkdirSync(OUT, { recursive: true }); |
| | let FAILS = 0; |
| | const say = (s = '') => console.log(s); |
| | const fail = (s) => { say(`FAILED: ${s}`); FAILS += 1; }; |
| | const mut = (s) => (MUTATE ? s + ' MUTATED' : s); |
| | const collapse = (t) => |
| | t.replace(/<[^>]+>/g, ' ') |
| | .replace(/ /g, ' ').replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, "'").replace(/</g, '<').replace(/>/g, '>') |
| | .replace(/[’‘]/g, "'").replace(/[“”]/g, '"') |
| | .replace(/\s+/g, ' ') |
| | // tags around link text leave a space before closing punctuation |
| | .replace(/\( /g, '(').replace(/ ([),.;:])/g, '$1'); |
| | |
| | async function get(url, { json = false, xssi = false } = {}) { |
| | let last; |
| | for (let i = 0; i < 3; i++) { |
| | const r = await fetch(url, { headers: { 'user-agent': UA, 'accept-language': 'en-US,en;q=0.9', accept: json ? 'application/json' : 'text/html,*/*' }, redirect: 'follow' }); |
| | const body = await r.text(); |
| | last = { status: r.status, body }; |
| | if (r.status === 200 || r.status === 404) break; |
| | await new Promise((res) => setTimeout(res, 2000)); |
| | } |
| | if (json && last.status === 200) last.data = JSON.parse(xssi ? last.body.slice(last.body.indexOf('\n') + 1) : last.body); |
| | return last; |
| | } |
| | async function phrase(name, url, needles) { |
| | const r = await get(url); |
| | fs.writeFileSync(`${OUT}/${name.replace(/[^A-Za-z0-9]+/g, '_')}.html`, r.body); |
| | const t = collapse(r.body); |
| | for (const n of needles) { |
| | if (r.status === 200 && t.includes(n)) say(`OK [${r.status}] ${name} — "${n}"`); |
| | else fail(`[${r.status}] ${name} — phrase not found: "${n}" (${url})`); |
| | } |
| | return t; |
| | } |
| | |
| | // --------------------------------------------------------------------------- |
| | say('== 1. Chrome release channel and milestone schedule (chromiumdash) =='); |
| | const today = new Date().toISOString().slice(0, 10); |
| | say(`run date ${today}`); |
| | const rel = await get('https://chromiumdash.appspot.com/fetch_releases?channel=Stable&platform=Linux&num=1', { json: true }); |
| | if (rel.status !== 200) fail(`chromiumdash fetch_releases HTTP ${rel.status}`); |
| | const stable = rel.data[0]; |
| | say(`INFO Chrome stable (Linux): milestone ${stable.milestone}, ${stable.version}, this patch released ${new Date(stable.time).toISOString().slice(0, 10)}`); |
| | // The schedule dates the page prints. Kept here rather than in EXPECT because |
| | // section 1 runs before EXPECT is defined. |
| | const SCHEDULE_EXPECT = { 152: { stable_date: '2026-08-25' }, 153: { stable_date: '2026-09-08' }, 154: { stable_date: '2026-09-22' }, 156: { branch_point: '2026-09-28' } }; |
| | const sched = {}; |
| | for (let m = 150; m <= 156; m++) { |
| | const r = await get(`https://chromiumdash.appspot.com/fetch_milestone_schedule?mstone=${m}`, { json: true }); |
| | if (r.status !== 200) { fail(`chromiumdash schedule M${m} HTTP ${r.status}`); continue; } |
| | const s = r.data.mstones[0]; |
| | if (s.mstone !== m) fail(`chromiumdash schedule asked for M${m}, got ${s.mstone}`); |
| | sched[m] = s; |
| | const line = `M${m}: branch_point ${s.branch_point.slice(0, 10)}, earliest_beta ${s.earliest_beta.slice(0, 10)}, stable_date ${s.stable_date.slice(0, 10)}`; |
| | const want = SCHEDULE_EXPECT[m]; |
| | if (!want) { say(`INFO ${line}`); continue; } |
| | const bad = Object.entries(want).filter(([k, v]) => s[k].slice(0, 10) !== v); |
| | if (bad.length) fail(`${line} — page says ${bad.map(([k, v]) => `${k} ${v}`).join(', ')}`); else say(`OK ${line}`); |
| | } |
| | |
| | // --------------------------------------------------------------------------- |
| | say(''); |
| | say('== 2. Chrome Platform Status, per-feature endpoint, every stage =='); |
| | const STAGE = { |
| | 110: 'incubate', 120: 'prototype', 130: 'dev trial', 140: 'eval readiness', 150: 'origin trial', 151: 'extend OT', 160: 'ship', |
| | 220: 'prototype', 230: 'dev trial', 250: 'origin trial', 251: 'extend OT', 260: 'ship', |
| | 320: 'implement', 330: 'dev trial', 360: 'ship', |
| | 410: 'dep: plan', 430: 'dep: dev trial', 450: 'dep: deprecation trial', 451: 'dep: extend DT', 460: 'dep: ship (removal)', 470: 'dep: remove code', |
| | 1061: 'enterprise rollout', 1070: 'enterprise shipped', |
| | }; |
| | // [row on the page, id, name must match] |
| | const FEATURES = [ |
| | ['Topics (ship)', '5680923054964736', /^Topics API$/], |
| | ['Protected Audience (ship)', '5733583115255808', /Protected audience API/i], |
| | ['Protected Audience (removal)', '6552486106234880', /Deprecate and Remove Protected Audience$/], |
| | ['Attribution Reporting (ship)', '6412002824028160', /^Attribution Reporting API$/], |
| | ['Attribution Reporting (removal)', '6320639375966208', /Deprecate and remove: Attribution Reporting API/], |
| | ['Shared Storage (ship)', '6256348582903808', /^Shared Storage API$/], |
| | ['Shared Storage (removal)', '5076349064708096', /Deprecate and Remove: Shared Storage API/], |
| | ['Private Aggregation (ship)', '5743412790689792', /^Private Aggregation API$/], |
| | ['Private Aggregation (removal)', '4683382919397376', /Deprecate and remove: Private Aggregation API/], |
| | ['Fenced Frames (ship)', '5699388062040064', /^Fenced frames$/], |
| | ['Fenced Frames (removal)', '6366274495053824', /Remove FencedFrame element/], |
| | ['Related Website Sets (ship)', '5640066519007232', /^Related Website Sets$/], |
| | ['Related Website Sets (removal)', '5194473869017088', /Deprecate and Remove: Related Website Sets/], |
| | ['requestStorageAccessFor (ship)', '5122534152863744', /^requestStorageAccessFor$/], |
| | ['requestStorageAccessFor (removal)', '5162221567082496', /Deprecate and Remove: document.requestStorageAccessFor/], |
| | ['CHIPS (ship)', '5179189105786880', /CHIPS/], |
| | ['CHIPS (WebView entry)', '5279664766713856', /Deprecate CHIPS and Relaunch in WebView/], |
| | ['Storage Access API (ship)', '5612590694662144', /^Storage Access API$/], |
| | ['Private State Tokens (ship)', '5078049450098688', /^Private State Token API$/], |
| | ['FedCM (ship)', '6438627087220736', /Federated Credential/], |
| | ['Bounce tracking mitigations (ship)', '5705149616488448', /^Bounce Tracking Mitigations$/], |
| | ['UA Client Hints (ship)', '5995832180473856', /Sec-CH-UA Client Hints/], |
| | ]; |
| | // Values the content page states as of 2026-09-27. |
| | const EXPECT = { |
| | removalDesktop: { '6552486106234880': 153, '6320639375966208': 153, '5076349064708096': 153, '4683382919397376': 152, '6366274495053824': 156, '5194473869017088': 153, '5162221567082496': 153 }, |
| | topicsRemovalEntries: 0, |
| | releaseNoteHeads: { 152: ['Remove Private Aggregation API'], 153: ['Deprecate and remove Protected Audience', 'Deprecate and remove Related Website Sets (RWS)', 'Deprecate and remove Shared Storage API', 'Deprecate and remove document.requestStorageAccessFor', 'Deprecate and remove Attribution Reporting API'], 154: null }, |
| | threadNewest: { Attribution_Reporting: '2026-07-01', Shared_Storage: '2026-07-07', Private_Aggregation: '2026-07-08', Protected_Audience: '2026-09-24', Topics: '2026-09-24' }, |
| | cftArm64: { 151: false, 152: false, 153: true, 154: true, 155: true, 156: true }, |
| | totStorage: ['runBounceTrackingMitigations'], |
| | }; |
| | if (MUTATE) EXPECT.threadNewest.Shared_Storage = '2026-07-06'; |
| | const cs = {}; |
| | for (const [row, id, re] of FEATURES) { |
| | const r = await get(`https://chromestatus.com/api/v0/features/${id}`, { json: true, xssi: true }); |
| | if (r.status !== 200) { fail(`chromestatus ${id} (${row}) HTTP ${r.status}`); continue; } |
| | const d = r.data; |
| | cs[id] = d; |
| | const name = MUTATE && id === '6552486106234880' ? d.name + ' MUTATED' : d.name; |
| | if (!re.test(name)) { fail(`chromestatus ${id} (${row}) name is "${name}", expected ${re}`); continue; } |
| | const c = d.browsers.chrome; |
| | say(`OK ${id} ${row} — "${d.name}" [${d.feature_type}] summary: ${c.status.text} (${c.status.milestone_str}), desktop ${c.desktop}, android ${c.android}, webview ${c.webview}; updated ${d.updated.when.slice(0, 10)}`); |
| | if (id in EXPECT.removalDesktop) { |
| | const got = d.stages.filter((st) => st.stage_type === 460).map((st) => st.desktop_first); |
| | if (c.status.text !== 'Proposed' || got.length !== 1 || got[0] !== EXPECT.removalDesktop[id]) |
| | fail(`${id} ${row}: page says Proposed, removal stage desktop ${EXPECT.removalDesktop[id]}; now ${c.status.text}, stage 460 desktop ${got.join('/')}`); |
| | } |
| | for (const s of d.stages) { |
| | const ms = [s.desktop_first && `desktop ${s.desktop_first}${s.desktop_last ? '–' + s.desktop_last : ''}`, s.android_first && `android ${s.android_first}`].filter(Boolean).join(', '); |
| | say(` stage ${s.stage_type} ${(STAGE[s.stage_type] || '?').padEnd(24)} ${ms || '(no milestone)'}${s.intent_thread_url ? ' intent: ' + s.intent_thread_url : ''}`); |
| | } |
| | } |
| | // The page says Topics has no dedicated removal entry. That is a negative |
| | // claim, so print the candidate set it rests on: every Feature-removal entry |
| | // the search returns for these queries. |
| | for (const q of ['Topics', 'browsingTopics', 'Deprecate and remove']) { |
| | const r = await get(`https://chromestatus.com/api/v0/features?q=${encodeURIComponent(q)}&num=300`, { json: true, xssi: true }); |
| | if (r.status !== 200) { fail(`chromestatus search "${q}" HTTP ${r.status}`); continue; } |
| | const rm = r.data.features.filter((f) => f.feature_type === 'Feature removal'); |
| | const topics = rm.filter((f) => /topic/i.test(f.name)); |
| | const line = `search "${q}": ${r.data.total_count} results, ${rm.length} Feature removal, of which name mentions Topics: ${topics.length}${topics.length ? ' — ' + topics.map((f) => f.id + ' ' + f.name).join('; ') : ''}`; |
| | if (topics.length !== EXPECT.topicsRemovalEntries) fail(`${line} (page says there is no Topics removal entry)`); else say(`OK ${line}`); |
| | } |
| | |
| | // --------------------------------------------------------------------------- |
| | say(''); |
| | say('== 3. Chrome release notes, "Deprecations and removals" (developer.chrome.com) =='); |
| | for (let m = 150; m <= 156; m++) { |
| | const url = `https://developer.chrome.com/release-notes/${m}?hl=en`; |
| | const r = await get(url); |
| | const released = sched[m] && sched[m].stable_date.slice(0, 10) <= today; |
| | if (r.status === 404) { |
| | if (released) fail(`[404] ${url} although M${m} stable_date has passed`); |
| | else say(`OK [404] ${url} — M${m} not yet stable (stable_date ${sched[m] ? sched[m].stable_date.slice(0, 10) : '?'})`); |
| | continue; |
| | } |
| | if (r.status !== 200) { fail(`[${r.status}] ${url}`); continue; } |
| | const i = r.body.indexOf('id="deprecations_and_removals"'); |
| | const upd0 = (collapse(r.body).match(/Last updated (\d{4}-\d\d-\d\d) UTC/) || [])[1]; |
| | // A release with nothing removed may have no section at all (M154 did not); |
| | // that is a finding about the notes, not a failed fetch. |
| | if (i < 0) { |
| | if (m in EXPECT.releaseNoteHeads && EXPECT.releaseNoteHeads[m] !== null) fail(`M${m}: no "Deprecations and removals" section, page expects ${EXPECT.releaseNoteHeads[m].join(' | ')}`); |
| | else say(`OK [200] M${m} (page last updated ${upd0}): NO "Deprecations and removals" section on the page`); |
| | continue; |
| | } |
| | if (EXPECT.releaseNoteHeads[m] === null) { fail(`M${m}: page says the notes list no removals, but a "Deprecations and removals" section now exists`); continue; } |
| | const end = r.body.indexOf('Contribute', i); |
| | const seg = r.body.slice(i, end > 0 ? end : undefined); |
| | const heads = [...seg.matchAll(/<h3[^>]*>([\s\S]*?)<\/h3>/g)].map((h) => collapse(h[1]).trim()); |
| | const upd = (collapse(r.body).match(/Last updated (\d{4}-\d\d-\d\d) UTC/) || [])[1]; |
| | const missing = (EXPECT.releaseNoteHeads[m] || []).filter((h) => !heads.includes(h)); |
| | if (missing.length) fail(`M${m}: expected heading(s) missing: ${missing.join(' | ')}`); |
| | say(`${missing.length ? 'INFO' : 'OK '} [200] M${m} (page last updated ${upd}): ${heads.length ? heads.join(' | ') : collapse(seg.replace(/^[^>]*>/, '')).slice(0, 160).trim()}`); |
| | } |
| | // The wording of the M152 and M153 entries is the finding: M152 says Private |
| | // Aggregation "is deprecated and removed"; M153 says the others are "planned". |
| | await phrase('release notes 152', 'https://developer.chrome.com/release-notes/152?hl=en', [ |
| | 'the Private Aggregation API is deprecated and removed (along with related Privacy Sandbox APIs)', |
| | ]); |
| | await phrase('release notes 153', 'https://developer.chrome.com/release-notes/153?hl=en', [ |
| | mut('the Protected Audience API is planned for deprecation and removal (along with related Privacy Sandbox APIs)'), |
| | 'the Shared Storage API is planned for deprecation and removal', |
| | 'the Attribution Reporting API is planned for deprecation and removal', |
| | 'Related Website Sets is planned for deprecation and removal', |
| | 'it is planned for deprecation and removal along with Related Website Sets', |
| | ]); |
| | await phrase('release notes 150', 'https://developer.chrome.com/release-notes/150?hl=en', ['There are no deprecations or removals in this release.']); |
| | |
| | // --------------------------------------------------------------------------- |
| | say(''); |
| | say('== 4. blink-dev intent threads: the phased plan and its September status =='); |
| | await phrase('blink-dev Protected Audience k_nubsMb97g', 'https://groups.google.com/a/chromium.org/g/blink-dev/c/k_nubsMb97g', [ |
| | 'Planning to deprecate in M144 and remove in M150', |
| | 'M152: Permanently remove the underlying implementation code for the API, and replace it with a lightweight stub API. The stub will remain removable via field trial.', |
| | 'M152 Canary/Beta: Begin a controlled rollout of the stub API removal via a field trial.', |
| | 'When I test on Chrome 152 stable, both navigator.joinAdInterestGroup and navigator.runAdAuction exist.', |
| | mut('We have seen no regressions on 1% of stable (M152+)'), |
| | 'We are actually still seeing ~ 1% usage.', |
| | '10% Stable: Hold for 2 weeks (through Oct 12)', |
| | '100% Stable: Roll out starting Oct 26', |
| | 'It wasn\'t actually an increase in API usage, it was just a change in measurement.', |
| | ]); |
| | await phrase('blink-dev Topics _R85yctz4Rs', 'https://groups.google.com/a/chromium.org/g/blink-dev/c/_R85yctz4Rs', [ |
| | 'Deprecate in M144 and then remove in M150', |
| | 'Currently the usage is 4.9% of page loads.', |
| | 'replace it with a lightweight stub API', |
| | mut('We have reached 1% on Stable (M153+) with no regressions or known breakage.'), |
| | 'The current usage is at 2%', |
| | '10% Stable: Hold for 2 weeks (through Oct 15)', |
| | '100% Stable: Target launch after Oct 15', |
| | ]); |
| | |
| | await phrase('blink-dev Attribution Reporting 4K2RRt6VYCQ', 'https://groups.google.com/a/chromium.org/g/blink-dev/c/4K2RRt6VYCQ', [ |
| | 'Currently the usage is 19.7% of page loads.', |
| | 'M152: Permanently remove the underlying implementation code for the API, and replace it with a lightweight stub API.', |
| | ]); |
| | await phrase('blink-dev Shared Storage uh5Ke6qyegc', 'https://groups.google.com/a/chromium.org/g/blink-dev/c/uh5Ke6qyegc', [ |
| | 'Currently, ~11% of page loads use Shared Storage API.', |
| | 'M152: Permanently remove the underlying implementation code for the API, and replace it with a lightweight stub API.', |
| | ]); |
| | await phrase('blink-dev Private Aggregation Ld7avyD0U0Q', 'https://groups.google.com/a/chromium.org/g/blink-dev/c/Ld7avyD0U0Q', [ |
| | 'Currently the usage is still 2.4% of page loads.', |
| | 'M152: Permanently remove the underlying implementation code for the API. There is no need to replace it with a stub API', |
| | ]); |
| | // Which threads have a rollout update after the July LGTMs? Print each |
| | // thread's newest dated message so "no September update" is visible, not assumed. |
| | const MON = { Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5, Jul: 6, Aug: 7, Sep: 8, Oct: 9, Nov: 10, Dec: 11 }; |
| | for (const f of fs.readdirSync(OUT).filter((n) => n.startsWith('blink_dev_'))) { |
| | const t = collapse(fs.readFileSync(`${OUT}/${f}`, 'utf8')); |
| | const ds = [...t.matchAll(/\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{1,2}), (20\d\d), \d{1,2}:\d\d:\d\d\s?[AP]M/g)] |
| | .map((m) => new Date(Date.UTC(+m[3], MON[m[1]], +m[2])).toISOString().slice(0, 10)).sort(); |
| | if (!ds.length) { fail(`${f}: no dated messages parsed`); continue; } |
| | const key = Object.keys(EXPECT.threadNewest).find((k) => f.includes(k)); |
| | const newest = ds[ds.length - 1]; |
| | // "Newest" is the newest date stamp rendered in the server-side HTML of the |
| | // thread page; it is not checked against Google Groups' own message count. |
| | const line = `${f.replace(/\.html$/, '')}: ${ds.length} date stamps rendered, ${new Set(ds).size} distinct dates, first ${ds[0]}, newest ${newest}`; |
| | if (!key) fail(`${line} — no expectation for this thread`); |
| | else if (newest !== EXPECT.threadNewest[key]) fail(`${line} — page says newest ${EXPECT.threadNewest[key]}`); |
| | else say(`OK ${line}`); |
| | } |
| | |
| | // --------------------------------------------------------------------------- |
| | say(''); |
| | say('== 5. Google\'s own Privacy Sandbox status and retirement pages =='); |
| | const st = await get('https://privacysandbox.google.com/overview/status?hl=en'); |
| | if (st.status !== 200) fail(`status page HTTP ${st.status}`); |
| | else { |
| | const upd = (collapse(st.body).match(/Last updated:? ?(\w+ \d{1,2}, \d{4})/) || [])[1]; |
| | say(`OK [200] privacysandbox.google.com/overview/status — "Last updated: ${upd}"`); |
| | const rows = [...st.body.matchAll(/<tr[^>]*>([\s\S]*?)<\/tr>/g)].map((m) => [...m[1].matchAll(/<t[dh][^>]*>([\s\S]*?)<\/t[dh]>/g)].map((c) => collapse(c[1]).trim())); |
| | if (rows.length < 5) fail(`status page: ${rows.length} table rows, expected the per-platform table`); |
| | for (const r of rows.slice(1)) say(` ${r.join(' | ')}`); |
| | } |
| | await phrase('retirement blog 2025-10-17', 'https://privacysandbox.google.com/blog/update-on-plans-for-privacy-sandbox-technologies?hl=en', [ |
| | mut('Related Website Sets (including requestStorageAccessFor and Related Website Partition), SelectURL, SDK Runtime and Topics (Chrome and Android)'), |
| | ]); |
| | await phrase('enrollment page', 'https://privacysandbox.google.com/private-advertising/enrollment?hl=en', [ |
| | 'We will no longer accept new account creation and enrollment', |
| | ]); |
| | await phrase('CMA case page', 'https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes', [ |
| | 'Case state: Closed', 'Closed: 17 October 2025', |
| | ]); |
| | |
| | // --------------------------------------------------------------------------- |
| | say(''); |
| | say('== 6. Artefacts the page names (GitHub archived / pushed_at; tip-of-tree CDP) =='); |
| | const auth = process.env.GH_TOKEN ? { authorization: `Bearer ${process.env.GH_TOKEN}` } : {}; |
| | for (const repo of ['GoogleChrome/related-website-sets', 'GoogleChrome/ip-protection', 'privacysandbox/attestation', 'patcg-individual-drafts/topics']) { |
| | const r = await fetch(`https://api.github.com/repos/${repo}`, { headers: { 'user-agent': UA, ...auth } }); |
| | if (r.status !== 200) { fail(`github ${repo} HTTP ${r.status}`); continue; } |
| | const d = await r.json(); |
| | const ok = d.archived === !MUTATE; |
| | (ok ? say : fail)(`${ok ? 'OK ' : ''}github.com/${repo} archived=${d.archived} pushed_at=${d.pushed_at.slice(0, 10)}`); |
| | } |
| | const tot = await get('https://raw.githubusercontent.com/ChromeDevTools/devtools-protocol/master/json/browser_protocol.json', { json: true }); |
| | if (tot.status !== 200) fail(`devtools-protocol master HTTP ${tot.status}`); |
| | else { |
| | const sd = tot.data.domains.find((d) => d.domain === 'Storage'); |
| | const RE = /interest|shared|attribution|bounce|related|topic/i; |
| | const cmds = sd.commands.map((c) => c.name).filter((n) => RE.test(n)); |
| | const evs = sd.events.map((e) => e.name).filter((n) => RE.test(n)); |
| | const line = `devtools-protocol master Storage domain: commands ${cmds.join(', ') || '(none)'}; events ${evs.join(', ') || '(none)'}`; |
| | if (cmds.join() !== EXPECT.totStorage.join() || evs.length) fail(`${line} — page says only ${EXPECT.totStorage.join(', ')}`); else say(`OK ${line}`); |
| | } |
| | // Chrome for Testing: which milestones have a linux-arm64 build. This host is |
| | // aarch64; the first pass of this refresh looked only for 'linux64', concluded |
| | // no Google-built binary could run here, and a reviewer caught it. |
| | const cft = await get('https://googlechromelabs.github.io/chrome-for-testing/latest-versions-per-milestone-with-downloads.json', { json: true }); |
| | if (cft.status !== 200) fail(`chrome-for-testing JSON HTTP ${cft.status}`); |
| | else { |
| | for (let m = 151; m <= 156; m++) { |
| | const e = cft.data.milestones[String(m)]; |
| | const arm = !!e && e.downloads.chrome.some((d) => d.platform === 'linux-arm64'); |
| | const line = `Chrome for Testing M${m}: ${e ? e.version : 'no entry'}, linux-arm64 ${arm ? 'yes' : 'no'}`; |
| | if (arm !== EXPECT.cftArm64[m]) fail(`${line} — page expects linux-arm64 ${EXPECT.cftArm64[m] ? 'yes' : 'no'}`); else say(`OK ${line}`); |
| | } |
| | } |
| | const npmPw = await get('https://registry.npmjs.org/playwright', { json: true }); |
| | if (npmPw.status !== 200) fail(`npm playwright HTTP ${npmPw.status}`); |
| | else say(`INFO npm playwright dist-tags: latest ${npmPw.data['dist-tags'].latest} (${npmPw.data.time[npmPw.data['dist-tags'].latest].slice(0, 10)}), next ${npmPw.data['dist-tags'].next}`); |
| | |
| | say(''); |
| | say('== summary =='); |
| | say(`FAILED checks: ${FAILS}`); |
| | process.exit(FAILS > 0 ? 1 : 0); |
| | </file> |
| | |
| | Its real, unedited output: |
| | |
| | <file text external_checks_privacy_sandbox-output.txt> |
| | == 1. Chrome release channel and milestone schedule (chromiumdash) == |
| | run date 2026-09-27 |
| | INFO Chrome stable (Linux): milestone 154, 154.0.8037.57, this patch released 2026-09-22 |
| | INFO M150: branch_point 2026-06-01, earliest_beta 2026-06-03, stable_date 2026-06-30 |
| | INFO M151: branch_point 2026-06-29, earliest_beta 2026-07-01, stable_date 2026-07-28 |
| | OK M152: branch_point 2026-07-27, earliest_beta 2026-07-29, stable_date 2026-08-25 |
| | OK M153: branch_point 2026-08-17, earliest_beta 2026-08-19, stable_date 2026-09-08 |
| | OK M154: branch_point 2026-08-31, earliest_beta 2026-09-02, stable_date 2026-09-22 |
| | INFO M155: branch_point 2026-09-14, earliest_beta 2026-09-16, stable_date 2026-10-06 |
| | OK M156: branch_point 2026-09-28, earliest_beta 2026-09-30, stable_date 2026-10-20 |
| | |
| | == 2. Chrome Platform Status, per-feature endpoint, every stage == |
| | OK 5680923054964736 Topics (ship) — "Topics API" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2023-08-17 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/b845db21-f158-4bf3-9109-7f4665126ec1n%40chromium.org |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 101–115, android 101 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAANMuaNXE3KYymq%3Dd0jcOmw%2Br2si_DOJK4cc%2BqMCU8mCoQBWTA%40mail.gmail.com |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAANMuaNc94moaqPPWepai4THP1rOvXoxvixS%3Dostu2QGMLPtvA%40mail.gmail.com |
| | OK 5733583115255808 Protected Audience (ship) — "Protected audience API (formerly FLEDGE)" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2023-06-23 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/w9hm8eQCmNI |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 101–115, android 105 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CABQTWr=-pfYiMtALbieskeC7K7E-fPDA8angjX3SM8gqQS6jpw@mail.gmail.com |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CABQTWrn8eM3wOtUY3RzmDrt7SVxR_y_6Fo02bJ%2BF1bzbwpFfkQ%40mail.gmail.com |
| | OK 6552486106234880 Protected Audience (removal) — "Deprecate and Remove Protected Audience" [Feature removal] summary: Proposed (Proposed), desktop 153, android 153, webview 153; updated 2026-08-21 |
| | stage 410 dep: plan (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CABQTWrnevtY14OMos%2BuDgzXtFwQJ5vzY3hEMmyRFQBKDHBz-9A%40mail.gmail.com |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 153, android 153 |
| | stage 470 dep: remove code (no milestone) |
| | OK 6412002824028160 Attribution Reporting (ship) — "Attribution Reporting API" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/7B0ldtZR_68/m/GjLBu0n4DgAJ |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 101–115, android 101 intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/jEnNpideO1Y/m/nlEDdjmnCgAJ |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/9402d8f1-1700-4eb3-8709-eaba907784aen%40chromium.org |
| | OK 6320639375966208 Attribution Reporting (removal) — "Deprecate and remove: Attribution Reporting API" [Feature removal] summary: Proposed (Proposed), desktop 153, android 153, webview null; updated 2026-08-21 |
| | stage 410 dep: plan (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/beb44d6a-aae5-4664-994a-38fb93bb4580n%40chromium.org |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 153, android 153 |
| | stage 470 dep: remove code (no milestone) |
| | OK 6256348582903808 Shared Storage (ship) — "Shared Storage API" [New or changed feature] summary: Origin trial (115), desktop 115, android 115, webview null; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/_quChIvPzT8/m/0W7IxD_1AAAJ |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 104–115, android 104 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAANMuaNn%3DOwqymhbTRPfcY6zW-S4Gs9JFummJhU%3Dx%2BcoydV%2BYw%40mail.gmail.com |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAANMuaOmcaZAPAgOg97yDtW%2BuEPMXnKb3nnth8GHS28KBqSAWQ%40mail.gmail.com |
| | OK 5076349064708096 Shared Storage (removal) — "Deprecate and Remove: Shared Storage API" [Feature removal] summary: Proposed (Proposed), desktop 153, android 153, webview null; updated 2026-08-21 |
| | stage 410 dep: plan (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAJ8xcq6ty%3DiW_L9%3DpbzJbZKAT7rVdu_%2B9-QJ2P2ojCRtSRk4xw%40mail.gmail.com |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 153, android 153 |
| | stage 470 dep: remove code (no milestone) |
| | OK 5743412790689792 Private Aggregation (ship) — "Private Aggregation API" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview 115; updated 2024-08-15 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAA%2BBiFkKSt4YBNUn2h42G3z%2BqjwxjFAo%3DsPnrbvvOoNaDa_aAQ%40mail.gmail.com |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 107–115, android 107 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAA%2BBiF%3DKQYXEVn%3DB4rMabH14UdYyA%2BF8qQkWyUVPB0rypS1N0Q%40mail.gmail.com |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAA%2BBiFk4cb%2Bi69Symy-KCjHbtquGSQCn5scXy_YMSSWGut2vJw%40mail.gmail.com |
| | OK 4683382919397376 Private Aggregation (removal) — "Deprecate and remove: Private Aggregation API" [Feature removal] summary: Proposed (Proposed), desktop 152, android 152, webview null; updated 2026-08-21 |
| | stage 410 dep: plan (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/8d2b9c6a-d1f1-4111-bdb4-31933998cd36n%40chromium.org |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 152, android 152 |
| | stage 470 dep: remove code (no milestone) |
| | OK 5699388062040064 Fenced Frames (ship) — "Fenced frames" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/Ko9UXQYPgUE/m/URRsB-qvAAAJ |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 102–115, android 102 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CADAcp0-Htb44ezkojydCMKEWM9YnXL0Zc+GVE9xLO68csf8tJw@mail.gmail.com |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CADAcp093_yvrvYDigFOZVdzmBN_cW0y6xLbthQHjNQY5K%2BjVgw%40mail.gmail.com |
| | OK 6366274495053824 Fenced Frames (removal) — "Remove FencedFrame element and window.fence APIs" [Feature removal] summary: Proposed (Proposed), desktop 156, android 156, webview 156; updated 2026-09-24 |
| | stage 410 dep: plan (no milestone) |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 156, android 156 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/6a7b8346.f5684636.88ead.041c.GAE%40google.com |
| | stage 470 dep: remove code (no milestone) |
| | OK 5640066519007232 Related Website Sets (ship) — "Related Website Sets" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2023-10-03 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/0EMGi-xbI-8/m/FgSjq6TtBwAJ |
| | stage 130 dev trial desktop 115, android 115 |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 89–93, android 89 intent: https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/XkWbQKrBzMg |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAD_OO4jfJ3tEbyWMX6RgJMFhhNe5t5aScd9kNerYMC8THe1-Sg%40mail.gmail.com |
| | OK 5194473869017088 Related Website Sets (removal) — "Deprecate and Remove: Related Website Sets (RWS)" [Feature removal] summary: Proposed (Proposed), desktop 153, android 153, webview 153; updated 2026-08-21 |
| | stage 410 dep: plan (no milestone) |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 153, android 153 |
| | stage 470 dep: remove code (no milestone) |
| | stage 1061 enterprise rollout desktop 144 |
| | stage 1061 enterprise rollout desktop 153 |
| | OK 5122534152863744 requestStorageAccessFor (ship) — "requestStorageAccessFor" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2025-03-25 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAGg35awh2_aqmFtWgOdo40vYVnWf%2BkEv3o7jxZ8DLbWq0eC3eQ%40mail.gmail.com |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial (no milestone) |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAD_OO4g87zWDtnn00w1%2BVD%2BYwr9oP0TjOfemX97VrBe96kby3A%40mail.gmail.com |
| | OK 5162221567082496 requestStorageAccessFor (removal) — "Deprecate and Remove: document.requestStorageAccessFor" [Feature removal] summary: Proposed (Proposed), desktop 153, android 153, webview 153; updated 2026-08-21 |
| | stage 410 dep: plan (no milestone) |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) desktop 153, android 153 |
| | stage 470 dep: remove code (no milestone) |
| | stage 1061 enterprise rollout desktop 144 |
| | stage 1061 enterprise rollout desktop 153 |
| | OK 5179189105786880 CHIPS (ship) — "Cookies Having Independent Partitioned State (CHIPS)" [New or changed feature] summary: Enabled by default (114), desktop 114, android 114, webview 114; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/hvMJ33kqHRo/m/3diUOI0uAQAJ |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 106–106, android 106 intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/_dJFNJpf91U |
| | stage 160 ship desktop 114, android 114 intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/JNOQvsTxecI |
| | OK 5279664766713856 CHIPS (WebView entry) — "Deprecate CHIPS and Relaunch in WebView" [Feature removal] summary: Proposed (Proposed), desktop null, android null, webview 128; updated 2026-06-24 |
| | stage 410 dep: plan (no milestone) |
| | stage 430 dep: dev trial (no milestone) |
| | stage 450 dep: deprecation trial (no milestone) |
| | stage 460 dep: ship (removal) (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/_hHg5MASz4s/m/xWu_9uZNAgAJ |
| | stage 470 dep: remove code (no milestone) |
| | OK 5612590694662144 Storage Access API (ship) — "Storage Access API" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial (no milestone) |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAD_OO4hnt1Rd5WSC%3DFU9dQriOP%3DKF0Cz9McxoT2_7UgP0u%3DKPw%40mail.gmail.com |
| | OK 5078049450098688 Private State Tokens (ship) — "Private State Token API" [New or changed feature] summary: Enabled by default (115), desktop 115, android 115, webview null; updated 2024-07-18 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/forum |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 84–101, android 84 intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/UIvia1WwIhk |
| | stage 160 ship desktop 115, android 115 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CANduzxCC8T5D9WSrvo0yq7Tu7hdAj-YXLwuOyu2DqqkTRoHQRg%40mail.gmail.com |
| | OK 6438627087220736 FedCM (ship) — "Federated Credentials Management (was WebID)" [New or changed feature] summary: Origin trial (108), desktop 108, android 108, webview null; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/2B4TJ7j2U4M/m/1X5T3OszCAAJ |
| | stage 130 dev trial desktop 103, android 98 |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial desktop 103–107, android 101 intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/kws-gltC5us |
| | stage 160 ship desktop 108, android 108 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CALdEk-yf1BMQ4ZtMYH9cCQsecroEE3ZPOKgY8LU%3DNX3zAfbwYA%40mail.gmail.com |
| | OK 5705149616488448 Bounce tracking mitigations (ship) — "Bounce Tracking Mitigations" [New or changed feature] summary: Enabled by default (116), desktop 116, android 116, webview null; updated 2023-10-10 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAK7rkMi_7z0-yeTbBiE43V5SD1ri4jSVxrkR8Gs%3DD0NRoRKivA%40mail.gmail.com |
| | stage 130 dev trial desktop 115, android 115 |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial (no milestone) |
| | stage 160 ship desktop 116, android 116 intent: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAK7rkMhBxsxD-V15C0idt4OULm72Oac2yT_hVyPf3noUxex0LA%40mail.gmail.com |
| | OK 5995832180473856 UA Client Hints (ship) — "Sec-CH-UA Client Hints" [New or changed feature] summary: Enabled by default (89), desktop 89, android 89, webview null; updated 2025-08-22 |
| | stage 110 incubate (no milestone) |
| | stage 120 prototype (no milestone) intent: https://groups.google.com/a/chromium.org/d/msg/blink-dev/WQ0eC_Gf8bw/dhWMhCYYDwAJ |
| | stage 130 dev trial (no milestone) |
| | stage 140 eval readiness (no milestone) |
| | stage 150 origin trial (no milestone) |
| | stage 160 ship desktop 89, android 89 |
| | OK search "Topics": 8 results, 0 Feature removal, of which name mentions Topics: 0 |
| | OK search "browsingTopics": 1 results, 0 Feature removal, of which name mentions Topics: 0 |
| | OK search "Deprecate and remove": 106 results, 53 Feature removal, of which name mentions Topics: 0 |
| | |
| | == 3. Chrome release notes, "Deprecations and removals" (developer.chrome.com) == |
| | OK [200] M150 (page last updated 2026-06-30): Deprecations and removals There are no deprecations or removals in this release. Except as otherwise noted, the content of this page is licensed under the Creat |
| | OK [200] M151 (page last updated 2026-07-28): Chrome 151 removes support for macOS 12 | Remove [LegacyNoInterfaceObject] from FontFaceSet IDL |
| | OK [200] M152 (page last updated 2026-08-25): Remove Private Aggregation API |
| | OK [200] M153 (page last updated 2026-09-08): Deprecate and remove Protected Audience | Deprecate and remove Related Website Sets (RWS) | Deprecate and remove Shared Storage API | Deprecate and remove document.requestStorageAccessFor | Deprecate and remove Attribution Reporting API | Remove non-standard navigations targeted at _current |
| | OK [200] M154 (page last updated 2026-09-22): NO "Deprecations and removals" section on the page |
| | OK [404] https://developer.chrome.com/release-notes/155?hl=en — M155 not yet stable (stable_date 2026-10-06) |
| | OK [404] https://developer.chrome.com/release-notes/156?hl=en — M156 not yet stable (stable_date 2026-10-20) |
| | OK [200] release notes 152 — "the Private Aggregation API is deprecated and removed (along with related Privacy Sandbox APIs)" |
| | OK [200] release notes 153 — "the Protected Audience API is planned for deprecation and removal (along with related Privacy Sandbox APIs)" |
| | OK [200] release notes 153 — "the Shared Storage API is planned for deprecation and removal" |
| | OK [200] release notes 153 — "the Attribution Reporting API is planned for deprecation and removal" |
| | OK [200] release notes 153 — "Related Website Sets is planned for deprecation and removal" |
| | OK [200] release notes 153 — "it is planned for deprecation and removal along with Related Website Sets" |
| | OK [200] release notes 150 — "There are no deprecations or removals in this release." |
| | |
| | == 4. blink-dev intent threads: the phased plan and its September status == |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "Planning to deprecate in M144 and remove in M150" |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "M152: Permanently remove the underlying implementation code for the API, and replace it with a lightweight stub API. The stub will remain removable via field trial." |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "M152 Canary/Beta: Begin a controlled rollout of the stub API removal via a field trial." |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "When I test on Chrome 152 stable, both navigator.joinAdInterestGroup and navigator.runAdAuction exist." |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "We have seen no regressions on 1% of stable (M152+)" |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "We are actually still seeing ~ 1% usage." |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "10% Stable: Hold for 2 weeks (through Oct 12)" |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "100% Stable: Roll out starting Oct 26" |
| | OK [200] blink-dev Protected Audience k_nubsMb97g — "It wasn't actually an increase in API usage, it was just a change in measurement." |
| | OK [200] blink-dev Topics _R85yctz4Rs — "Deprecate in M144 and then remove in M150" |
| | OK [200] blink-dev Topics _R85yctz4Rs — "Currently the usage is 4.9% of page loads." |
| | OK [200] blink-dev Topics _R85yctz4Rs — "replace it with a lightweight stub API" |
| | OK [200] blink-dev Topics _R85yctz4Rs — "We have reached 1% on Stable (M153+) with no regressions or known breakage." |
| | OK [200] blink-dev Topics _R85yctz4Rs — "The current usage is at 2%" |
| | OK [200] blink-dev Topics _R85yctz4Rs — "10% Stable: Hold for 2 weeks (through Oct 15)" |
| | OK [200] blink-dev Topics _R85yctz4Rs — "100% Stable: Target launch after Oct 15" |
| | OK [200] blink-dev Attribution Reporting 4K2RRt6VYCQ — "Currently the usage is 19.7% of page loads." |
| | OK [200] blink-dev Attribution Reporting 4K2RRt6VYCQ — "M152: Permanently remove the underlying implementation code for the API, and replace it with a lightweight stub API." |
| | OK [200] blink-dev Shared Storage uh5Ke6qyegc — "Currently, ~11% of page loads use Shared Storage API." |
| | OK [200] blink-dev Shared Storage uh5Ke6qyegc — "M152: Permanently remove the underlying implementation code for the API, and replace it with a lightweight stub API." |
| | OK [200] blink-dev Private Aggregation Ld7avyD0U0Q — "Currently the usage is still 2.4% of page loads." |
| | OK [200] blink-dev Private Aggregation Ld7avyD0U0Q — "M152: Permanently remove the underlying implementation code for the API. There is no need to replace it with a stub API" |
| | OK blink_dev_Attribution_Reporting_4K2RRt6VYCQ: 11 date stamps rendered, 9 distinct dates, first 2025-11-07, newest 2026-07-01 |
| | OK blink_dev_Private_Aggregation_Ld7avyD0U0Q: 9 date stamps rendered, 5 distinct dates, first 2025-11-07, newest 2026-07-08 |
| | OK blink_dev_Protected_Audience_k_nubsMb97g: 14 date stamps rendered, 11 distinct dates, first 2025-11-07, newest 2026-09-24 |
| | OK blink_dev_Shared_Storage_uh5Ke6qyegc: 12 date stamps rendered, 9 distinct dates, first 2025-11-07, newest 2026-07-07 |
| | OK blink_dev_Topics_R85yctz4Rs: 9 date stamps rendered, 6 distinct dates, first 2025-11-07, newest 2026-09-24 |
| | |
| | == 5. Google's own Privacy Sandbox status and retirement pages == |
| | OK [200] privacysandbox.google.com/overview/status — "Last updated: August 14, 2026" |
| | Chrome | Bounce tracking mitigations CHIPS FedCM frame-ancestors directive Private State Tokens Storage and Network State Partitioning Storage Access (including Storage Access Header) User-Agent Client Hints User-Agent reduction | Continue to support |
| | Chrome | Aggregation Service Attribution Reporting Fenced Frames Private Aggregation Protected Audience Related Web Sites (including requestStorageAccessFor()) Shared Storage (including Select URL) Topics | Deprecate and remove |
| | Chrome | IP Protection Partitioned Popins Related Website Partition | Discontinue |
| | Chrome | Fenced Storage Read Private Proofs Probabilistic Reveal Tokens Script Blocking | Do not launch |
| | Android | Attribution Reporting On-Device Personalization Protected App Signals Protected Audience SDK Runtime Topics | Deprecate and remove |
| | OK [200] retirement blog 2025-10-17 — "Related Website Sets (including requestStorageAccessFor and Related Website Partition), SelectURL, SDK Runtime and Topics (Chrome and Android)" |
| | OK [200] enrollment page — "We will no longer accept new account creation and enrollment" |
| | OK [200] CMA case page — "Case state: Closed" |
| | OK [200] CMA case page — "Closed: 17 October 2025" |
| | |
| | == 6. Artefacts the page names (GitHub archived / pushed_at; tip-of-tree CDP) == |
| | OK github.com/GoogleChrome/related-website-sets archived=true pushed_at=2025-11-21 |
| | OK github.com/GoogleChrome/ip-protection archived=true pushed_at=2025-11-03 |
| | OK github.com/privacysandbox/attestation archived=true pushed_at=2026-01-22 |
| | OK github.com/patcg-individual-drafts/topics archived=true pushed_at=2025-11-07 |
| | OK devtools-protocol master Storage domain: commands runBounceTrackingMitigations; events (none) |
| | OK Chrome for Testing M151: 151.0.7922.138, linux-arm64 no |
| | OK Chrome for Testing M152: 152.0.7977.82, linux-arm64 no |
| | OK Chrome for Testing M153: 153.0.8010.52, linux-arm64 yes |
| | OK Chrome for Testing M154: 154.0.8037.57, linux-arm64 yes |
| | OK Chrome for Testing M155: 155.0.8059.12, linux-arm64 yes |
| | OK Chrome for Testing M156: 156.0.8075.0, linux-arm64 yes |
| | INFO npm playwright dist-tags: latest 1.63.0 (2026-09-04), next 1.64.0-alpha-2026-09-27 |
| | |
| | == summary == |
| | FAILED checks: 0 |
| | </file> |
| | |
| | ==== What this refresh could not establish ==== |
| | |
| | * **The behaviour of the Chrome that users run.** Chrome for Testing 153–156 is Google-built and agrees with Chromium on every row. But it is not the auto-updating user binary, and no automation launch can see the field-trial state that removes the stubs for 1–10% of users. There is no Google-built arm64 152. |
| | * **Private Aggregation's behaviour.** Only its Permissions-Policy feature was probed (unknown from 153). A worklet-side ''privateAggregation'' call was not attempted. |
| | * **Related Website Sets' behaviour.** Not probed. The page carries its status labels and its CDP command only. |
| | * **Whether the October field-trial dates held.** The page gives them as requests made on 2026-09-24, not as events. |
| | * **Whether the M150 field-trial rejection ever reached stable users.** The plan says it would; no fetched message reports it. |
| | * **Whether servers still send ''Attribution-Reporting-Register-*'' or ''Observe-Browsing-Topics''.** Only our own servers were in the probe. The page says "whatever … servers may still send". |
| | * **Whether Puppeteer's default launch picks up a variations seed.** Puppeteer 25.5.0 passes ''%%--disable-background-networking%%'' but not ''%%--disable-field-trial-config%%''. The probe ran only through Playwright. |
| | * **Why full Chromium 151 refuses what headless shell 151 allows.** The page gives our reading, a settings layer the shell lacks, and flags it as untested. |
| | * **The Protected Audience and Topics stubs' own removal from the automation build.** No milestone is published for deleting the stub code, and the stubs are still in 156.0.8075.0, so the page tells the reader to re-run the probe. |
| | |
| | ==== Judgement calls, 2026-09-27 ==== |
| | |
| | * **Measure instead of restating.** The item asked for chromestatus to be re-fetched and the staircase restated. Re-fetching showed that chromestatus, the release notes and the status page disagree with each other and with the binaries. A fourth restatement would have repeated the M153 error in a new form. The page's status column now rests on the probe, and the three status sources are shown beside it as labels. |
| | * **A new subsection rather than a longer table.** The API table keeps one short status cell per API. The per-source evidence goes in "The removal staircase, measured", so a reader designing a crawl can skip it. |
| | * **Kept the 2026-09-01 measurement section**, labelled as pre-removal, rather than re-running it on 156. It documents the instruments as they were when they worked, and those instruments are what a retrospective crawl on a pinned binary needs. |
| | * **The two new blink-dev usage figures went into the existing telemetry table** with the same unaudited-vendor caveat. So did the "Fledge" use-counter redefinition, because it is a measurement pitfall in the only post-2025 series there is. |
| | * **Did not re-run the Puppeteer branch of ''ps_probe.mjs'' across the builds.** Puppeteer is what the corpus's Protected Audience crawl used, and its launch is the full Chromium that already disagreed with Playwright's in 151, so a reasonable reviewer would have added it. It was left out because the full-Chromium column is already covered by the Debian and Chrome for Testing builds. The flag-set difference is recorded as an unknown above. |
| | * **Two origins in one probe.** The calls table runs on ''https://localhost'', which is exempt from enrollment, with no extra flags. The auction runs on a mapped ''probe.example'' with the ads-API override and an enrollment override, the flag set of ''ps_cdp_probe.mjs''. The goal was to change one thing at a time against the 2026-09-01 probes, not to make the two tables comparable with each other. |
| | * **Did not edit [[privacy:cookie_syncing]].** It carries a dated sentence ("as of 2026-08-26 … a removal milestone of **Chrome 153** with status 'Proposed'") and quotes the status page's label as "Intent to deprecate and remove filed", which now reads "Deprecate and remove". That page is not this item's; it is listed in the run's outcome note instead. |
| | |
| | ==== Review log, 2026-09-27 refresh ==== |
| | |
| | Three focused ''sonnet'' passes ran in parallel on a frozen local draft (the page was not saved until they had reported). Each was told that the author's context may not be exhaustive, and each got the before and after page, the diff, this section, both scripts and their outputs. Each wrote its findings to a file as it went. |
| | |
| | ^ Pass ^ Finding ^ Disposition ^ |
| | | figures vs script | **MAJOR.** The top box and the staircase table dated the Protected Audience auction failure and the Shared Storage rejection "from M152". But build [2], full Chromium 151, already shows both, and the page's own next paragraph said so | **Accepted, fixed.** Both places now say the 152 date is a headless-shell-to-headless-shell comparison, and that full Chromium already refused both in 151. The table's intro paragraph states the rule once | |
| | | figures vs script | NIT: ''@@REVIEW_LOG@@'' placeholder unfilled in the draft | **Expected**: this table is what fills it | |
| | | figures vs script | Code: no bug found. ''lift()'' pulls the same strings; request logs are reset per build after the browser closes, so nothing leaks between builds; the exit gate fails under ''MUTATE=1''. The reviewer re-ran the four 2026-09-01 probes and reproduced their outputs | Noted | |
| | | citations and quotes | **MAJOR.** The CHIPS WebView footnote said "//Proposed// with no milestone"; the entry's ''browsers.chrome.webview'' is **128** | **Accepted, fixed.** The footnote now says WebView milestone 128, no desktop or Android milestone. The external-checks script printed only ''desktop''/''android'', so it could not have caught this, and it now prints ''webview'' too | |
| | | citations and quotes | All other quotes verbatim: the four-step plan and its "word for word" claim across four threads, the PrivAgg "no need … stub", the PA 09-23/09-24 figures, the Topics 09-24 message, the "Fledge" exchange (Garrett Johnson asked, Paul Jensen answered), the release-notes wording, and the status-page date. Links resolve to existing headings. Footnotes are balanced. No new citekeys | Noted | |
| | | external currency | **HIGH.** "Chrome for Testing is x86-64 only for Linux" was wrong: ''linux-arm64'' exists for 153.0.8010.52, 154.0.8037.57, 155.0.8059.12 (and 156.0.8075.0). The first pass had filtered the manifest on ''linux64'' | **Accepted, and it changed the result.** The four CfT arm64 builds were downloaded and added to the probe: 10 builds became 14. All four agree with Chromium on every row, and CfT 156.0.8075.0 also shows ''getRelatedWebsiteSets'' gone. The page no longer says "no Google Chrome binary was run". It says Google-built but not the user's Chrome. The external-checks script printed the arm64 availability; the generic pass pointed out that it did not assert it, and it now does | |
| | | external currency | LOW. OpenWPM is at v0.37.0 (2026-09-06), not v0.36.0. Its README still says "OpenWPM is built on top of Firefox" | **Accepted, fixed** (an unedited sentence outside this refresh's window; verified against the v0.37.0 README). The page's "README opens" became "README says", because the sentence is not the README's first | |
| | | external currency | Rejected secondary sources: a search-engine summary that dropped "planned" and claimed rSAFor was "removed in Chrome 153", and ''mdn/browser-compat-data'' PR #30659 ("Chrome 152 removed Shared Storage API"). That PR is contested in its own thread and spans 152/153/154 across its diff | **Agreed; neither cited.** They are recorded here so the next run does not re-add them | |
| | |
| | **What this round says about the slots.** The one finding that changed the measurement came from the currency pass, and it concerned the author's tooling, not the page's sources. The figures pass caught the page contradicting itself within one subsection. Both MAJOR fixes are new text, so they went to the generic pass below. |
| | |
| | **Generic ''fable'' pass**, on the draft with every fix above applied, frozen again. Same bundle plus this table. It reported 1 MAJOR, 21 MINOR and 7 NIT. It found more than the three focused passes combined, as it did on 2026-09-01. |
| | |
| | ^ Finding ^ Disposition ^ |
| | | **MAJOR A1.** "Puppeteer was pointed at the same Chromium binary … not of two browser builds", on the content page and in this page's run record. The refresh had just established that ''chromium.executablePath()'' is the full Chromium and Playwright's default the headless shell, and left the sentence standing | **Accepted, fixed** in both places, and added to [[#What the 2026-09-01 page said that did not hold]]. The result stands: builds [1] and [2] agree on presence | |
| | | A2. "Permissions-Policy feature unknown" was inferred from ''allowsFeature()'' = false, which is also the answer for a known but ungranted feature | **Accepted, and measured instead of reworded**: the probe now prints ''featurePolicy.features()'' membership. It matches ''allowsFeature()'' in all 14 builds, so "unknown" is now a measurement, and the staircase intro says how "known" is defined | |
| | | A3. "Stub from M152" for Protected Audience is the plan's word. No build says so, and the headless-shell failure at 152 is over-determined (the implementation could be gone, or the override switches could be) | **Accepted.** The cell now says "No auction runs from M152 … a stub per the blink-dev plan". The timeline says what was observed | |
| | | A4. "After field-trial users had started to get rejections" and "(1%, then 10%) have no method at all" state rollout facts no source gives | **Accepted.** The top box now says the October percentages are requests. "No method at all" is flagged as what the plan implies, which no automation build can show. The M150 rollout is listed as unknown | |
| | | A5. "The plan Chrome then followed" is contradicted by Shared Storage (IDL gone at 153 with no field trial); "posted to all five" is contradicted by the PrivAgg footnote | **Accepted, fixed.** Now "four of the five", and Shared Storage is named as not having followed its own plan | |
| | | A6. "The ''Register-*'' responses servers still send" was never observed | **Accepted, reworded** to "may still send; we did not measure whether any do" | |
| | | A7. The Topics headers were never provoked | **Accepted, and measured**: ''fetch(…, {browsingTopics: true})'' was added. ''Sec-Browsing-Topics'' is sent only by the two 151 builds, and the header section says so | |
| | | A8. "Chrome for Testing gets no field trials" is a property of the Playwright launch (''%%--disable-field-trial-config%%'', fresh profile), not of the binary | **Accepted.** The page now attributes it to the launch. We then checked Puppeteer 25.5.0's own launcher: it passes ''%%--disable-background-networking%%'' but not ''%%--disable-field-trial-config%%'' or ''%%--disable-component-update%%''. So the reviewer's own suggestion that Puppeteer "passes the same" flags was wrong, and the page says only what was verified | |
| | | B1–B5. "Ten Chromium binaries" left over; "this run had only Chromium 151"; "two status sources" against a list of three; "you need M151" without "as headless shell"; "156" not flagged as pre-branch | **All accepted, fixed** | |
| | | B7. The Fenced Frames entry is titled "Remove …", not "Deprecate and remove" | **Accepted**; the shortened top box no longer quotes the label | |
| | | C1–C5. Untouched sentences made stale: RWS "reachable via CDP"; "What to Read First" sending readers to the status pages as the primary sources; "the most actionable thing on the page"; present-tense CDP and override sentences; the ''.dat'' "moves with the component updater" (Playwright passes ''%%--disable-component-update%%'') | **All accepted, fixed.** C5 says Playwright only, for the reason in A8 | |
| | | D1. The answer to "can I measure this today" is scattered | **Accepted**: a five-sentence "If you start a crawl today" box at the top of the detection section | |
| | | D2. What to Report's example version needs the stub warning | **Accepted** | |
| | | E1. The top box grew from 477 to 746 words and held evidence, mechanism and the page's own history | **Accepted.** It is now 4 short bullets after the two unchanged ones. The four-step plan, the thread links and the October dates moved to the staircase section, and the "until 2026-09-27 this page said M153" history moved to this page | |
| | | F1. The external-checks script printed "OK" beside values the page states, e.g. "linux-arm64 NO" | **Accepted.** An ''EXPECT'' block now makes every stated value fail the run when it changes, and report-only lines print INFO. The mutation run shifts one expectation too, and prints 10 FAILED | |
| | | F2. "No message after July" rests on date stamps in one rendered page | **Accepted.** The stamp count per thread is printed, the caveat is in the source table and in the page's footnote, and a new newest date fails the run | |
| | | F3. "Could not establish" omitted three things the page states | **Accepted.** Two of them (policy-feature membership, the Topics header) were measured instead. The M150 rollout, third-party ''Register-*'' senders and Puppeteer's seed behaviour are listed | |
| | | F4. This page's run record repeated the A1 sentence | **Accepted, fixed** with a dated inline correction | |
| | | F5. "The summary status field is not evidence of anything" overstated, since stage milestones from the same endpoint are quoted | **Accepted, reworded** | |
| | | F6. Unrecorded decisions: no Puppeteer branch across builds, no persistent-profile launch, two origins in one probe | **Accepted, recorded** under [[#Judgement calls, 2026-09-27]]; not acted on | |
| | |
| | **Rejected: nothing**, except one detail inside A8 (Puppeteer's flags), which was checked and found wrong. As on 2026-09-01, the generic slot found the class of defect the checklists cannot see: advice that is well-sourced in each sentence and wrong in combination. Here that was the untouched Puppeteer sentence, which contradicted the refresh's own finding eighteen lines further down. |
| | |
| | **Re-check of the fixes** (''sonnet''), on a third frozen snapshot, told that fixes are unreviewed text. It found 0 MAJOR, 2 MINOR and 1 NIT, and confirmed the rest, including the Playwright and Puppeteer flag claims read from both packages' launchers. |
| | |
| | ^ Finding ^ Disposition ^ |
| | | MINOR. Section 1 of the checks script still printed "OK" for schedule dates the page prints (M152–M154 stable, M156 branch) without asserting them | **Accepted, fixed.** Those four dates are asserted; the other milestones print INFO | |
| | | MINOR. The main status table kept "Permissions-Policy feature unknown" after the staircase table had moved to the measured "no longer a known policy feature" | **Accepted, fixed** | |
| | | NIT. The "If you start a crawl today" box said "a pinned pre-152 binary", which is broader than the evidence (only the headless shell ran an auction in 151) | **Accepted, fixed**: it now says chrome-headless-shell, not full Chromium | |
| | |
| | These three fixes are one-clause edits and were not sent for a further pass. |
| |
| ====== 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. |
| |