Files
obsidian-vault/work/projects/cpm-wake-init-detection-tech-design-2026-11-10.md
T

3.6 KiB

tags, updated, status
tags updated status
work
cpm
tech-design
pixel
web-extension
2026-11-11 draft

TD: Pixel Definition: CPM Wake Init Detection (macOS/iOS + embedded web extension)

Author: Alex M Reviewer: TBD (previous CPM pixel designs: Michal) Stakeholders: Michal, Konrad, Russell (from the previous Tech Designs; confirm). Extension change: the privacy-extension owners. Project: CPM: root-cause the stuck embedded extension messaging (macOS/iOS)

Background & Requirements

Failures after a background wake are the largest group with no fix: on macOS 1.214, 39% of all failures (0.68% of DAU); on iOS 7.244, 22% (0.06% of DAU).

For one page, startup is: page script sends init → background receives it → reads configuration → reads the user setting → checks the site → answers the page and refreshes the app's dashboard. The app sees only the last step, so every failure looks the same: no answer.

Requirements: find where the chain stopped, without changing what the extension does for the page or collecting URLs or persistent identifiers.

Problem Statement

For every tab the permanent breakage metric reports as silent, record the furthest init step the extension reported.

  1. The extension sends the app a fire-and-forget notification at each init step (PR #3727). It never waits, throws or changes what the page receives.
  2. The app keeps the furthest step per tab, for its current page only. A notification does not count as the extension answering: the tab is still reported silent unless the dashboard refresh arrives.
  3. web_extension_cpm_breakage gets one parameter, last_stage [1]:
last_stage The chain stopped
none nothing reached the app [3]
page_init_sent the page script sent init; the background never processed it
received init arrived; configuration or storage read did not finish
config_read waiting for the user setting from the app
settings_checked waiting for the site check
site_checked all checks passed; no answer arrived
response_sent the answer was sent to the page, but no dashboard refresh followed [2]
response_failed sending the answer to the page failed
  1. The extension ships inside the app, so the app side can ship first. The notifications and last_stage are removed when the wake group has a fix or is closed.

Notes

[1] Each stage follows a separate wait in the extension's init handling: the cached configuration, the user setting and the site check (the last two are native round trips). A stall at each has a different cause and fix.

[2] WebKit can report a send as done when nobody was listening, so response_sent does not prove the page got the answer.

[3] Notifications pass through the background we study, so the earliest failures end as none.

Testing

Unit tests in the app and in the extension. Not done: a real-WebKit run showing the right last_stage for a stall at each step.

Additional Considerations

  1. Privacy
    1. One new enumerated parameter. Tab number and URL stay inside the app. Privacy Triage not filed yet.
  2. Security
    1. No new private WebKit selectors; the new message is read-only.
  3. Site Breakage
    1. No intended change.
  4. Experimentation
    1. None.
  5. Operational
    1. First data comes about two release cycles after the work, because the extension ships with the app.
  6. Localization / Internationalization
    1. Not affected.