← Commit history

nb 0.4.7: register a host on first DATA not on connect (kills pending-N churn from port probers); battery guard matches 0.4.6 own-window semantics

John Lauer ·8da2081696 ·2mo ago ·parent f8d61b8
6 files changed +21−12
bridge/BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.4.6+0.4.7
bridge/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "native-browser",   "displayName": "Adom Native Browser",-  "version": "0.4.6",+  "version": "0.4.7",   "expectedExtensionVersion": "0.2.5",   "description": "Drives the user's REAL signed-in Chrome/Edge, in two layers. Layer 1 (nb) needs NOTHING installed and works on any machine: nbrowser_open_os_window (open a URL in the user's real profile, background+flashing, the OAuth/consent path), nbrowser_os_windows, nbrowser_profiles, nbrowser_wake_profile, nbrowser_force_close. Layer 2 (nbe, the Adom Native Browser Extension) unlocks the rest: CDP driving (navigate/click/read/screenshot) inside their logged-in profile. The bridge binds an ephemeral loopback port and the native-messaging host pumps stdio <-> bridge.",   "homepage": "https://wiki.adom.inc/adom/nb-bridge",
bridge/package.json+1−1
@@ -1,6 +1,6 @@ {   "name": "adom-native-browser-bridge",-  "version": "0.4.6",+  "version": "0.4.7",   "private": true,   "description": "Native-browser bridge for Bridge (ab): layer 1 (nb) plus layer 2 via nbe, the Adom Native Browser Extension (Chrome + Edge).",   "main": "server.js",
bridge/server.js+8−3
@@ -2597,11 +2597,16 @@ const hostSrv = net.createServer((sock) => {     try { sock.destroy(); } catch {}     return;   }-  // Register provisionally so this host is drivable immediately; the `hello` re-keys it to the real-  // profile. Several profiles can be connected at once.-  registerProvisional(sock);+  // REGISTER ON FIRST DATA, not on connect (2026-08-22). A bare TCP connect is NOT a native host:+  // ab's health checks / port probes open-and-close this port constantly, and registering each one+  // provisionally produced endless pending-N churn (ConfRoomROG reached provSeq 15749 with NO host+  // installed, and readiness read the corpses as "resolving"). A real host talks - its hello re-announce+  // goes out the moment it connects - so the first inbound byte is the earliest honest registration+  // point, and a silent prober now never enters conns at all.+  let registered = false;   let buf = '';   sock.on('data', (chunk) => {+    if (!registered) { registered = true; registerProvisional(sock); }     // ANY inbound byte proves something is alive behind this socket - clear its zombie strikes.     for (const [, c] of conns) if (c.sock === sock) { c.probeStrikes = 0; break; }     buf += chunk.toString('utf8');
native-browser-bridge-manifest.json+5−5
@@ -1,8 +1,8 @@ {   "manifest_version": 1,-  "version": "0.4.6",-  "url": "https://wiki.adom.inc/download/adom/nb-bridge/0.4.6/native-browser-bridge-v0.4.6.zip",-  "sha256": "1c1200b898c6806e9daf933e82e6baa0ad5c681eaf1e4fba2206b04d19899fdf",-  "size": 105694,-  "released_at": "2026-08-22T14:26:07Z"+  "version": "0.4.7",+  "url": "https://wiki.adom.inc/download/adom/nb-bridge/0.4.7/native-browser-bridge-v0.4.7.zip",+  "sha256": "bbcfedbc5240102ab83b6e53783e79f2f69f97fff2c47daeabe8a7766f23a034",+  "size": 105906,+  "released_at": "2026-08-22T14:30:58Z" }
tools/verb-battery.mjs+5−1
@@ -205,7 +205,11 @@ const T = {   guard_autologin: () => { const r = call('nbrowser_autologin', { sessionId: SID, host: 'wiki.adom.inc' }); return A(r.ok !== true && r.loggedIn !== true, 'refused without confirm:true', 'AUTOLOGIN RAN WITHOUT CONFIRM: ' + JSON.stringify(r).slice(0, 120)); },   guard_close_all: () => { const r = call('nbrowser_close'); return A(r.ok !== true || /confirm/i.test(JSON.stringify(r)), 'close-all demands confirmCloseAll', 'CLOSE-ALL RAN UNCONFIRMED: ' + JSON.stringify(r).slice(0, 120)); },   guard_record_fallback: () => { const r = call('nbrowser_record_start', { method: 'getdisplaymedia', sessionId: SID }); return A(r.ok !== true, 'picker fallback refused without fallbackConfirmed', 'FALLBACK RAN UNCONFIRMED: ' + JSON.stringify(r).slice(0, 140)); },-  guard_force_close: () => { const r = call('nbrowser_force_close', { hwnd: ctx.hwnd }); const refused = r.errorCode === 'owned_by_other' || /owned_by_other|Only that thread/i.test(JSON.stringify(r)); return A(refused && r.closed !== true, 'live-session hwnd refused (owned_by_other) - ownership absolute even via force path', 'FORCE_CLOSE DID NOT REFUSE A LIVE SESSION WINDOW: ' + JSON.stringify(r).slice(0, 140)); },+  // Since 0.4.6: force_close on YOUR OWN live session's hwnd yields the two-step attestation ticket+  // (the owner may clean up their own OS window - the open_os_window cleanup path depends on it), while+  // ANOTHER thread's window still refuses owned_by_other. The battery runs as the owner, so the pass is:+  // ticket offered, nothing closed by a single call. An outright closed:true here is the failure.+  guard_force_close: () => { const r = call('nbrowser_force_close', { hwnd: ctx.hwnd }); const refused = r.errorCode === 'owned_by_other' || /owned_by_other|Only that thread/i.test(JSON.stringify(r)); const ticketed = r.errorCode === 'attestation_required' || /needsAttestation|overrideTicket/i.test(JSON.stringify(r)); return A((refused || ticketed) && r.closed !== true, ticketed ? 'own-window ticket offered, nothing closed without attestation' : 'live-session hwnd refused (owned_by_other)', 'FORCE_CLOSE CLOSED (or mishandled) A LIVE SESSION WINDOW IN ONE CALL: ' + JSON.stringify(r).slice(0, 140)); },   profile_block: () => { const b = call('nbrowser_profile_block', { profile: PROFILE }); const g = call('nbrowser_open_tab', { sessionId: SID, url: `${HARNESS}?blocked=1` }); const u = call('nbrowser_profile_unblock', { profile: PROFILE }); const blockedWorked = g.ok !== true || /block/i.test(JSON.stringify(g)); return A(b.ok !== false && u.ok !== false && blockedWorked, 'block refused a drive; unblock restored', `block:${JSON.stringify(b).slice(0, 80)} drive-under-block:${JSON.stringify(g).slice(0, 80)}`); },   profile_unblock: () => { const r = call('nbrowser_open_tab', { sessionId: SID, url: `${HARNESS}?after-unblock=1&cb=${CB}` }); if (r.tabId) call('nbrowser_close_tab', { sessionId: SID, tabId: r.tabId }); return A(r.ok !== false, 'driving works again after unblock', JSON.stringify(r).slice(0, 140)); },