Follow-up from the dual-interface refactor (ea2e57e on feat/enable-tunnel-flip-flag).
Current behaviour
AppServices.registerTunnelInterface() only fires on TunnelManager.onStatusChange(.connected). Once the tunnel interface is registered with a given (host, port), it stays bound to those values until deregisterTunnelInterface() fires on .disconnected / .invalid.
If the user is mid-session and edits the foreground TCP entry in Settings (new host or port) — or removes it and adds a different one — the tunnel interface continues pointing at the old (host, port). The extension's NWConnection for TUNNEL_TCP_INTERFACE_ID also stays bound to the old endpoint (the app didn't re-publish tunnelTCPEndpointsKey). Bot → phone packets routed via the tunnel path either land at the wrong rnsd or fail.
What it should do
When InterfaceRepository writes a fresh interfaces JSON to App Group prefs (which posts configChangedNotificationName for the extension), the app side should also tear down and re-register the TunnelTCPInterface against the new foreground config. The new endpoint should re-publish to tunnelTCPEndpointsKey, the extension's Darwin observer for tunnelTCPEndpointsChangedNotificationName is already wired to reapply.
Suggested implementation sketch
AppServices could:
- Observe
InterfaceRepository.objectWillChange (or wrap the repository's mutation methods).
- Diff the new foreground TCP endpoints against
tunnelTCPInterface?.config.
- If different, call
deregisterTunnelInterface() then registerTunnelInterface() to remount.
Could also be done as a unified reconcileTunnelInterface() that's safe to call any time and computes the desired tunnel-mirror state from the current foreground config + tunnel-status.
Why deferred
For Phase B's MVP, the test scenarios don't edit the TCP config mid-run, so the bug doesn't surface in smoke. In real use it'd be reachable via "change my TCP relay while Background Transport is on" — uncommon but real.
Follow-up from the dual-interface refactor (
ea2e57eonfeat/enable-tunnel-flip-flag).Current behaviour
AppServices.registerTunnelInterface()only fires onTunnelManager.onStatusChange(.connected). Once the tunnel interface is registered with a given(host, port), it stays bound to those values untilderegisterTunnelInterface()fires on.disconnected/.invalid.If the user is mid-session and edits the foreground TCP entry in Settings (new host or port) — or removes it and adds a different one — the tunnel interface continues pointing at the old
(host, port). The extension'sNWConnectionforTUNNEL_TCP_INTERFACE_IDalso stays bound to the old endpoint (the app didn't re-publishtunnelTCPEndpointsKey). Bot → phone packets routed via the tunnel path either land at the wrong rnsd or fail.What it should do
When
InterfaceRepositorywrites a fresh interfaces JSON to App Group prefs (which postsconfigChangedNotificationNamefor the extension), the app side should also tear down and re-register theTunnelTCPInterfaceagainst the new foreground config. The new endpoint should re-publish totunnelTCPEndpointsKey, the extension's Darwin observer fortunnelTCPEndpointsChangedNotificationNameis already wired to reapply.Suggested implementation sketch
AppServicescould:InterfaceRepository.objectWillChange(or wrap the repository's mutation methods).tunnelTCPInterface?.config.deregisterTunnelInterface()thenregisterTunnelInterface()to remount.Could also be done as a unified
reconcileTunnelInterface()that's safe to call any time and computes the desired tunnel-mirror state from the current foreground config + tunnel-status.Why deferred
For Phase B's MVP, the test scenarios don't edit the TCP config mid-run, so the bug doesn't surface in smoke. In real use it'd be reachable via "change my TCP relay while Background Transport is on" — uncommon but real.