Skip to content

Release 2026.7.9

Latest

Choose a tag to compare

@github-actions github-actions released this 21 Jul 20:12
2026.7.9
eb2564f

Add - overlay auto-hide and click-to-dismiss

  • The on-page overlay can now hide itself after a set time. A new "Auto-hide
    after" select in the popup's Options section offers 3, 5, 10 or 20 seconds, or
    "never" (the default, permanent - unchanged behaviour). The timer is armed the
    first time the bar shows for a pageview; a soft navigation or new pageview
    shows it again and restarts the countdown. Stored in chrome.storage.local
    (fm_overlay_ttl) and applied live via storage.onChanged, like the other
    overlay options.
  • Click the overlay to dismiss it for the current pageview (the bar is now
    click-through-disabled and shows a pointer cursor). A soft-nav / new pageview
    brings it back. Changing an overlay option (toggle, position, timeout) also
    undoes a prior auto-hide or click-dismissal so the change is visible at once.

Add - smoxy page-cache verdict (S-Cache) per pageview

  • Documents served behind smoxy now show their page-cache verdict. The
    DevTools network listener additionally captures the response headers of
    document requests; when S-Cache is present (or Server: smoxy), the
    verdict is stored keyed by document URL (host + path, query ignored - the
    tracker strips queries from u) and matched to pageviews by closest
    navigation timestamp, so a reload keeps each pageview's own HIT/MISS.
  • Shown as a smoxy HIT|MISS|… badge in the pageview list and an
    S-Cache line in the detail head (with S-Cache-Reason when present),
    color-coded like the popup's cache statuses (HIT good · MISS poor ·
    EXPIRED/STALE/REVALIDATED warn · BYPASS purple). On a HIT the cache
    Age follows in parens (HIT (5min)) - Age is only meaningful when
    the object actually came from the cache, and like every header here it is
    optional (absent header, no parens). Entirely optional overall: pages not
    behind smoxy render exactly as before. Works for tracked and basic-RUM
    fallback pageviews alike.
  • Opt-in. The whole smoxy feature sits behind a popup toggle ("smoxy
    s-cache", chrome.storage.local key fm_smoxy, default off): it gates
    the panel's DevTools capture and display, the service worker's webRequest
    storage, and the overlay cell - applied live, and switching it off sweeps
    every stored verdict. While a smoxy verdict is shown, the CDN cache
    row/cell is suppressed
    in popup and overlay: smoxy IS the page cache in
    front of the origin here, showing both would be redundant. The popup's
    toggles (overlay + smoxy) now live in a collapsed "Options" <details>
    section
    , keeping the popup compact until expanded; the UI labels the
    header lower-case ("s-cache").
  • Popup and on-page overlay show the verdict too - without DevTools open.
    New webRequest permission (+ <all_urls> host permissions, no new install
    warning beyond the existing all-sites one): the service worker observes the
    top-level document response and keeps only Server / S-Cache /
    S-Cache-Reason / Age per tab (doc:<tabId> in session storage; a
    non-smoxy document clears the entry, tab close reclaims it). The popup adds
    a "smoxy page cache" row to its cache section; the overlay (tap-relay.js)
    pulls the verdict from the SW at document_start (__fmDocGet, with retries
    for the async write) and renders a smoxy HIT (5min)|MISS cell next to
    CDN/Origin - the overlay now also appears on smoxy pages without fastmon.
    Bodies are never read on this path; PRIVACY.md documents the header
    observation.
  • Overlay polish. The vitals cells are always rendered (n/a until
    measured) so the bar keeps a stable width instead of jumping as values pop
    in. Basic-RUM fallback snapshots now feed the overlay too (display-only
    __fm_rum__ event from rum-tap.js; the records still reach the service
    worker exactly once), so TTFB/LCP/CLS fill in on pages without fastmon. The
    "fastmon" brand text is gone; instead the fastmon logo appears - and
    ONLY when a real collector beacon proved fastmon runs on the page, so the
    logo doubles as the "fastmon detected" indicator (RUM-fallback/smoxy-only
    overlays carry no branding). The asset is the white logo mark without the
    dark tile
    (logos/logo-dark.svg minus its background rect) - the tiled icon
    read as a dark blob on the dark overlay bar - inlined as an SVG data URI:
    chrome.runtime.getURL() would require web_accessible_resources, which
    lets any page probe for the extension.

Add - overlay position option

  • The on-page overlay's corner is now configurable: top-left, top-right,
    bottom-right (default), or bottom-left, via a select in the popup's Options
    section (chrome.storage.local key fm_overlay_pos). tap-relay.js applies
    the corner live through storage.onChanged - no reload needed. Invalid
    stored values fall back to bottom-right.

Fix - "Unchecked runtime.lastError: No tab with id: …"

  • Fire-and-forget chrome.runtime.sendMessage calls in tap-relay.js and
    rum-tap.js now pass a callback that reads runtime.lastError (marking it
    checked). Without one, Chrome logs the error whenever the implicit response
    cannot be delivered back to the sending tab - which happens routinely,
    because the terminal beacon/snapshot fires during pagehide and the tab is
    gone a moment later. The service worker's __fmDocGet sendResponse is
    guarded the same way (the asking document can vanish while the storage read
    is in flight).
  • chrome.action.setIcon/setTitle switched from promise+.catch to the
    callback form reading lastError - the promise variant still produced
    "Unchecked runtime.lastError" logs on some Chrome versions when the tab id
    was already gone. And tap-relay's smoxy pull no longer messages from
    prerendered documents (it waits for prerenderingchange): discarded
    prerenders were a steady source of vanishing synthetic tab ids.
  • Note: "Uncaught (in promise) TypeError: Failed to fetch" entries in the
    extension error list are the PAGE's own failed fetches, attributed to us
    because tap-main.js wraps window.fetch - known and deliberately not
    silenced (see 2026.7.6 / 2026.7.7).

Add - basic-RUM fallback for pages without the fastmon snippet

  • Pages without a fastmon snippet now show basic RUM data plus Server-Timing
    instead of an empty panel.
    A new ISOLATED-world content script
    (rum-tap.js) measures a minimal picture straight from the browser's
    Performance APIs - navigation timing (TTFB/DNS/TCP/response/DOM-interactive/
    load/transfer size/protocol/nav type), FCP/first-paint, LCP, session-window
    CLS, a web-vitals-style INP estimate, connection info, and the navigation
    entry's Server-Timing - and ships snapshots through the same
    service-worker path as real beacons. Snapshots are shaped like collector
    beacons (same wire keys, synthetic rum-… pvid, lifecycle
    init → loaded → update → hidden → terminated), so vitals scorecards, the
    field table, charts, compare, and overview render them unchanged.
  • Fallback pageviews are clearly marked: a basic RUM badge in the list and
    a hint banner in the detail explain that the values are measured locally
    by the inspector, not by tracker beacons. The popup shows the same fallback
    summary (CWV + cache status + Server-Timing) with a matching hint; the
    toolbar icon stays gray (it still signals "fastmon active" only).
  • Real beacons always win: fastmon presence is detected via the in-page
    tap's event, collection stops immediately, and if fallback snapshots were
    already emitted, a one-shot rum-drop retracts the fallback pageview and
    popup summary. As a belt-and-braces, the panel also drops a still-open
    fallback pageview when a real beacon for the same document arrives via the
    network path (e.g. the pixel fallback).
  • Everything stays local (chrome.storage.session); PRIVACY.md documents the
    Performance-API read. Tests cover ingest, merge, banner/badge, supersede, and
    the rum-drop retraction.