TR-069 CPEs routinely open a new TCP connection (new port) for the empty POST that follows InformResponse. ensureSessionForRemote() only did an exact remoteKey match, so hasSession() returned false and the state machine was never continued — GPN discovery was never triggered. Add IP-only fallback in ensureSessionForRemote(): when the exact remoteKey is not found, scan RUNNING machines for a unique IP match, rebind the new remoteKey, and remap sessionMachines to the new sessionId. Ambiguous cases (NAT/CGNAT with multiple active devices on same IP) return false safely.