NVIDIA / NVIDIA/Personal-AI-Router

[Bug]: macOS M4 cannot obtain Local Network permission (no prompt, missing NSLocalNetworkUsageDescription) — cross-host discovery and EC-peer routing fail

Aperta
#3 5 commenti 0 reazioni 1 assegnatario Vedi su GitHub

@Noah-Tervalon-Nvidia ci sta già lavorando.

Dal 11/9/2026.

Lingua principale
Go
Stelle
1.4k
Fork
250
Merge medio
23h 27m
PR unite (30g)
1

Descrizione

PAIR version

v0.1.1 (both nodes), from the official release assets:

  • Linux amd64 .deb (devbox, x86_64)
  • macOS arm64 .dmg (Apple M4)
Host OS (exact)
  • macOS node: macOS 27.0 (build 26A5388g), Apple M4, 16 GB
  • Linux node: Omarchy 4.0.2 (/etc/os-release: ID=omarchy, VERSION_ID=4.0.2), x86_64, NVIDIA RTX 2000 Ada (8 GB)
Summary

macOS M4 node cannot obtain Local Network permission, so cross-host discovery and EC-peer registration fail. The shipped macOS bundle lacks NSLocalNetworkUsageDescription, and no permission prompt ever appears on this macOS version.

Verified (2026-09-04): plist keys alone are insufficient on macOS 27.0

We rebuilt PAIR from source applying the exact config fix from the (now-closed)
PR #12: added NSLocalNetworkUsageDescription and
NSBonjourServices: ["_nvpair-node._tcp"] to mac.extendInfo in
electron-builder.config.ts, built all modular Go binaries for darwin/arm64,
and produced a fresh .app whose Info.plist verifiably contains both keys.
Launched under the original com.nvidia.nvpair identity:

  • No Local Network consent prompt appears.
  • mDNS multicast still fails identically: sendto: no route to host on en0.
  • Unified logs show the LocalNetwork subsystem finding the bundle by PID/UUID
    each attempt, but no prompt and no explicit verdict.

Conclusion: the two plist keys are necessary but not sufficient. Leading
hypothesis: PAIR's scanner sends raw UDP multicast via Go's net package,
which does not traverse the API path (Bonjour/DNSService) that macOS TCC Local
Network enforcement associates with the declared NSBonjourServices — so no
consent is ever solicited. A fix likely needs the discovery layer to use the
system Bonjour API, not just the plist declaration.

What works (verified)
  • Single-node routing on the Linux node: model pull + chat through PAIR's proxy (11434) with Jobs telemetry (devbox→devbox).
  • Cluster membership via manual Add-node-by-IP: both nodes appear as member in members.json with the same clusterId.
  • TCP connectivity between nodes after opening firewall ports.
  • Privileged firewall helper (com.nvidia.nvpair.helper) loads from the signed bundle once approved in Login Items.
What fails (observed)
  1. Mac node-scanner mDNS multicast blocked. Log repeats every ~5 s:

    [nvpair-node-scanner] WARN mdns send: query did not leave any interface
    service=_nvpair-node._tcp failed=2 errors="en0 write: write udp4
    192.168.1.42:...->224.0.0.251:5353: sendto: no route to host"
    

    A direct Python UDP multicast from Terminal to 224.0.0.251:5353 succeeds on the same host — so the block is app-specific.

  2. No Local Network permission prompt ever appears on macOS for com.nvidia.nvpair, and the app never appears under System Settings → Privacy & Security → Local Network. NSLocalNetworkUsageDescription is absent from the shipped Info.plist (only legacy NSAllowsLocalNetworking is present). macOS will not show the consent prompt or list the app without that key.

  3. Patched-copy test: inconclusive. Added NSLocalNetworkUsageDescription, re-signed (ad-hoc, then Apple Development identity), reset TCC (tccutil reset All com.nvidia.nvpair), launched from Finder/LaunchServices — still no prompt, multicast still denied. Caveat: this copy was made by editing only the outer Info.plist/CFBundleIdentifier; nested Mach-O binaries retained the original team/signing identity. This test did not establish a fresh TCC identity, so it cannot determine whether the key alone fixes prompting.

  4. Cross-node engine-control fails. Both nodes log node X is not a discovered ec peer (engine-manager remote.go). Manual node admission creates cluster membership but does not populate the EC peer directory, which is fed only from discovery relay snapshots.

  5. Cross-node model routing fails. Devbox PAIR proxy returns no available node advertises the requested model for a Mac-only model; Mac proxy likewise for a devbox-only model. Manual-node model probing appears limited to plaintext engine endpoints, which PAIR's proxy rejects for remote peers (loopback-only, mTLS ingress required).

Expected behavior
  • macOS node should be able to receive Local Network permission (prompt appears; app listed in Privacy → Local Network), enabling mDNS discovery of _nvpair-node._tcp.
  • With mDNS working, discovery snapshots should populate the EC peer directory so cross-node engine status and routing work, as they do for same-LAN Linux nodes.
Suggested fix (actionable)
  • Add NSLocalNetworkUsageDescription to the macOS Info.plist and
    _nvpair-node._tcp under NSBonjourServices in mac.extendInfo
    (electron-builder.config.ts) — done in the closed PR #12 and verified in a
    source rebuild, but this alone does not restore the prompt.
  • Migrate the discovery layer's mDNS from raw Go net UDP sockets to the
    system Bonjour API (DNSServiceBrowse/DNSServiceRegister), which is the
    path macOS TCC associates with the declared Bonjour service and uses to
    solicit Local Network consent.
  • Verify the notarized build's first-use prompt on a clean macOS install.
Environment notes
  • tccutil reset for LocalNetwork service names returns RC 70 on this macOS version ("unsupported service"); tccutil reset All com.nvidia.nvpair succeeds.
  • Tailscale on/off both tested — not the cause.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.