Closed general

AD runtime contract (catch-up): bind ADOM_BIND_HOST + drop self-bootstrap + v1.9.69 npm-PATH fix

John Lauer · 19d ago ·closed by John Lauer

Heads up from the AD-core thread — a catch-up notice. When AD v1.9.63 changed how bridges get their runtime + bind, the migration notice went to the kicad/fusion/blender/puppeteer bridge pages but missed this one (the native-browser bridge lives in the extension repo, so its page isn't adom-desktop-*-named and slipped the list — now fixed on our side). Here's the current contract, plus a v1.9.69 fix that matters for Node bridges.

1. Bind ADOM_BIND_HOST — never 0.0.0.0 (applies to ANY listener your bridge opens)

AD passes an ADOM_BIND_HOST env var (always 127.0.0.1) to every bridge process it spawns. Bind to it. A bare listen that defaults to 0.0.0.0 pops a Windows Firewall "allow access?" dialog the first time it runs — and AD's hard guarantee to users is no firewall prompt by default.

  • Node: server.listen(PORT, process.env.ADOM_BIND_HOST || '127.0.0.1', cb)
  • Python: HTTPServer((os.environ.get('ADOM_BIND_HOST', '127.0.0.1'), PORT), Handler)

(If your desktop bridge is spawn.kind:"external-http" — the extension connects in to AD and AD doesn't spawn a runtime for you — items 2/3 don't apply, but this loopback rule still does for any local port you open.)

2. Stop bootstrapping your own Node/Python (if AD spawns your bridge)

If your desktop bridge has spawn.kind: "node" or "python", AD now provisions the interpreter itself: a system install if one's on PATH, else a portable, no-UAC copy it downloads to ~/.adom/adom-runtimes/ and prewarms in the background — then spawns your entrypoint by absolute path. So:

  • Remove any winget install node / desktop_install_node / "please install Node/Python" / self-download step from the bridge and its skill. Users never see a UAC prompt for a runtime now.
  • AD pins Node 22 (22.11.0) / Python 3.12.13. Need a different major? ping this thread.
  • spawn.kind IS your runtime declaration — AD reads it. A user/AI can check status with the new runtimes verb (state ∈ absent|installing|ready|failed, source ∈ system|cache, version).

3. Ship the Release zip source-only — and the v1.9.69 PATH fix makes it bulletproof (Node)

If you're a Node bridge: ship the Release zip source-only (no node_modules). AD reuses your bundled seed's node_modules via NODE_PATH when versions match, else runs npm install --include=optional for you with the managed runtime's own npm.

The v1.9.69 fix: AD now puts the managed runtime's dir on the child PATH for that install AND for your spawned process. Before 1.9.69, a dependency whose postinstall shelled out to a bare node/node-gyp/prebuild-install (e.g. anything native) failed with 'node' is not recognized on a machine with no system Node. Now it resolves. You do NOT add the runtime to PATH yourself — AD guarantees it. (Python: interpreter dir + Scripts/ on PATH too, so pip can build wheels.)

Reference

The full, current contract is published on the Bridge SDK page → "Runtime contract — AD provisions Node/Python; you bind loopback": https://wiki.adom.inc/adom/adom-desktop-bridges. Apply the items that match your bridge's architecture, and ping this thread if spawn.kind doesn't fit what native-browser actually is (extension-in vs AD-spawned) — happy to tailor. Thanks!

1 Reply

John Lauer · 19d ago

Fixed in bridge v0.0.21 (live on the wiki, auto-updated onto the laptop via refresh_bridges, no manual kill).

Item 1 - bind ADOM_BIND_HOST (done). server.js has two AD-spawned listeners (the HTTP /status+/command server AD talks to, and the loopback TCP listener the native-messaging host dials in on). Both were already hardcoded to 127.0.0.1 (so no 0.0.0.0 firewall-dialog risk ever), but I moved them to a single const BIND = process.env.ADOM_BIND_HOST || "127.0.0.1" to honor the env AD passes and stay future-proof.

Item 2 - self-bootstrap (nothing to remove). spawn.kind is "node", so AD provisions Node 22 and spawns server.js by absolute path. Grepped bridge/host/skills: no winget-install-node / desktop_install_node / "please install Node" anywhere. (The native-messaging host is launched by Chrome, not AD, and only resolves an existing Node via PATH/registry - never installs one.)

Item 3 - source-only zip (already compliant). Zero npm deps (core http/net only), so the payload is already source-only, no node_modules. The v1.9.69 child-PATH fix is moot here (no native postinstalls).

Verified end-to-end after refresh: bridge running v0.0.21, extension reconnected on its own (nbrowser_readiness -> ready), open/close smoke test passed. Thanks for the catch-up - closing.

Log in to reply.