← Commit history

1.8.72: demarcation gate — unpinned opens require CfT, pollable install instead of silent branded fallback; AD #204 filed for prewarm flip

John Lauer ·a8740db182 · ·parent 19bb74a
5 files changed +38−18
CHANGELOG.md+10
@@ -1,5 +1,15 @@ # Changelog — Adom Desktop Puppeteer Bridge +## 1.8.72 — 2026-07-18 — THE DEMARCATION GATE: no silent branded fallback, ever++1.8.71's "converge by the second session" still ran the FIRST session on branded Chrome — and the+first session is exactly the Aditya session. Now an unpinned new-window open REQUIRES cached CfT:+if absent, pup kicks the ~150 MB install in the background and returns the pollable+chrome_for_testing_installing (poll browser_readiness, retry) instead of silently driving the+user's browser. The installed Chrome/Edge is reachable ONLY by explicit browser_use pin (hints+carry the identity-bleed warning). Existing/live sessions exempt. Companion AD ask filed+(issue #204): flip prewarm_cft auto→always so install-time prewarm erases the first-use wait.+ ## 1.8.71 — 2026-07-18 — CfT-first hybrid pick order (#202) + auth-URL steering (the Aditya incident)  - **Pick order flipped to: cached CfT → installed Chrome → Edge → CfT-download-last-resort.**
adom-bridge-puppeteer-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "puppeteer",-  "version": "1.8.71",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.8.71/adom-bridge-puppeteer-v1.8.71.zip",-  "sha256": "cb0cf9c7636fe71e7d9b3e323827b3d2a838a8f9a27a0935dd1d7d7ad75bad7a",-  "size": 176234,+  "version": "1.8.72",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.8.72/adom-bridge-puppeteer-v1.8.72.zip",+  "sha256": "1af978937b836a19fd200f92611e14293dce1d7a488e688242bf19a103e79d88",+  "size": 176771,   "verbPrefixes": [     "browser_",     "desktop_recorder_",
src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.8.71\ No newline at end of file+1.8.72\ No newline at end of file
src/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "puppeteer",   "displayName": "Puppeteer (Chrome for Testing + Native)",-  "version": "1.8.71",+  "version": "1.8.72",   "description": "Drives a browser ALREADY on the machine \u2014 installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) \u2014 launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Binds its local server to LOOPBACK (127.0.0.1) only, so no Windows Firewall 'allow Node through the firewall' prompt ever pops. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome \u2192 Edge \u2192 CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. browser_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. browser_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, \u2026). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. pup is a GENERIC, non-profile browser only \u2014 every session is a fresh isolated Chrome/Edge process, never the user's real signed-in browser; profile defaults to sessionId. To drive the user's REAL Chrome/Edge (their profile, cookies, SSO), use the Adom browser EXTENSION's nbrowser_* verbs \u2014 a separate bridge, not pup's job.",   "homepage": "https://wiki.adom.inc/adom/adom-desktop",   "author": "Adom Inc.",
src/server.js+22−12
@@ -3715,23 +3715,31 @@ const server = http.createServer(async (req, res) => {             sendJSON(res, { success: false, error: 'sessionId is required. Example: browser_open_window { "sessionId": "dart2", "profile": "dart2", "url": "https://..." }' });             return;           }-          // ── Cold-start gate — READ-ONLY detect; never blocks ──-          // pup drives an ALREADY-INSTALLED browser (Chrome → Edge; EVERY Windows box-          // has Edge) with a fresh isolated profile — so readiness is almost always TRUE-          // instantly with NO download, and this gate just falls through. Only if the-          // machine has NO Chromium browser at all (no Chrome, no Edge, no cached CfT) —-          // rare — do we fetch Chrome for Testing as a fallback, kicked off in the-          // BACKGROUND here (non-blocking, pollable {installing:true}).+          // ── Cold-start gate (v1.8.72: THE DEMARCATION GATE) — READ-ONLY detect; never blocks ──+          // pup's browser is Chrome for Testing, PERIOD (the Aditya incident: a silent branded-+          // Chrome fallback let a Google sign-in trigger Chrome's profile-creation/consolidation+          // machinery and strand the user). An unpinned NEW-window open therefore REQUIRES cached+          // CfT: if it isn't there yet, kick the ~150 MB install in the BACKGROUND and return the+          // pollable {installing:true} — the caller polls browser_readiness and retries. This wait+          // is rare (AD prewarns CfT at install; flip of its skip-when-branded-exists default is+          // filed) and only ever hits a box's FIRST pup use. The user's installed Chrome/Edge is+          // available ONLY by explicit pin — browser_use {browser:"chrome"|"edge"} — eyes open.+          // Existing/live sessions are exempt (their browser is already running).           {             const rd = chrome.readiness();   // detect-only; never downloads-            if (!rd.ready) {+            const _def = (() => { try { return chrome.readDefault(); } catch (e) { return null; } })();+            const _pinnedBranded = !!(_def && _def.kind && !/chrome-for-testing|cft/i.test(_def.kind));+            const _cftCached = (() => { try { return chrome.detectChrome().installed; } catch (e) { return false; } })();+            const _sessionAlive = sessions.has(args.sessionId) || !!(browsers.get(args.profile || args.sessionId) && browsers.get(args.profile || args.sessionId).browser);+            const _needsCft = !_pinnedBranded && !_cftCached && !_sessionAlive;+            if (!rd.ready || _needsCft) {               if (rd.installPhase === 'failed') {                 sendJSON(res, {                   success: false,                   errorCode: rd.lastErrorCode || 'chrome_install_failed',                   error: `No Chrome/Edge installed and the Chrome-for-Testing fallback failed to install: ${rd.lastError}`,                   readiness: rd,-                  _hint: 'This machine has no Chrome or Edge, and the Chrome-for-Testing fallback download failed (usually no network / a proxy blocking storage.googleapis.com, or low disk). Fastest fix: have the user install Chrome or Edge (Edge ships with Windows) — pup will then use it instantly with no download. Or retry browser_prewarm.',+                  _hint: 'Chrome for Testing (pup\'s dedicated browser) failed to install — usually no network / a proxy blocking storage.googleapis.com, or low disk. Retry with browser_prewarm once the cause is fixed. If the user explicitly accepts driving their installed Chrome/Edge instead (identity-bleed risk — see the demarcation doctrine): browser_use {browser:"chrome"|"edge"}, then retry.',                 });                 return;               }@@ -3747,7 +3755,9 @@ const server = http.createServer(async (req, res) => {                 });                 return;               }-              // Otherwise fetch CfT as a last resort, in the background.+              // Fetch CfT in the background and tell the caller to poll+retry. This is+              // pup's dedicated browser being provisioned — NOT an error, and NOT a reason+              // to fall back to the user's branded browser.               if (!rd.installing) chrome.ensureChromeReady({ background: true });               sendJSON(res, {                 success: false,@@ -3755,8 +3765,8 @@ const server = http.createServer(async (req, res) => {                 installing: true,                 statusVerb: 'browser_readiness',                 readiness: rd,-                error: 'No Chrome/Edge installed on this machine — fetching Chrome for Testing as a fallback (~150 MB, one time).',-                _hint: 'RARE: this machine has neither Chrome nor Edge, so pup is downloading Chrome for Testing as a fallback (in the background — it did NOT block). Poll `browser_readiness` until {ready:true}, THEN re-issue this browser_open_window. Faster fix: have the user install Chrome or Edge (Edge ships with Windows) and pup uses it instantly with no download. Do NOT report a hard failure — this is the no-browser edge case.',+                error: 'Chrome for Testing (pup\'s dedicated sandboxed browser) is not cached yet — downloading it now (~150 MB, one time).',+                _hint: 'FIRST-USE PROVISIONING (not an error): pup deliberately drives Chrome for Testing, its OWN sandboxed browser — it does NOT silently fall back to the user\'s installed Chrome/Edge, whose profile/sign-in machinery bleeds into pup\'s anonymous windows (sign-in → "create a profile?" → duplicate profiles → lost user). The download runs in the BACKGROUND: tell the user pup is provisioning its browser (~a minute or two, one time ever), poll `browser_readiness` until {ready:true}, then re-issue this browser_open_window. Only if the user EXPLICITLY wants their installed browser driven (rare; identity-bleed risk): browser_use {browser:"chrome"|"edge"} pins it, then retry.',               });               return;             }