fix!: keep primary transport device-local

Devices no longer implicitely use the From address of sync messages
to determine their primary transport. Receivers have no concept of it and own devices
may disagree on which relay is reachable because of VPN or different networks:

1. Make setting a primary transport (`configured_addr`) a per-device non-synced operation.

2. Transport rows (add/remove/unpublish) keep syncing like before.

3. A device reelects a primary if a sync message unpublished/removed the current primary
   if there is a better candidate.

4. `TransportsModified` event is emitted at most once on an incoming transport sync message.

Users will notice the change in that changing primary transport in settings/advanced/relays
will not synchronize to other devices anymore.
This commit is contained in:
holger krekel
2026-07-31 17:25:23 +02:00
parent 2cacdbfd4b
commit cd42efb36d
5 changed files with 158 additions and 80 deletions

View File

@@ -150,12 +150,9 @@ def test_transport_synchronization(acfactory, log) -> None:
log.section("ac1 changes the primary transport")
ac1.set_config("configured_addr", transport3["addr"])
# One event for updated `add_timestamp` of the new primary transport,
# one event for the `configured_addr` update.
ac1_clone.wait_for_event(EventType.TRANSPORTS_MODIFIED)
ac1_clone.wait_for_event(EventType.TRANSPORTS_MODIFIED)
[transport1, transport3] = ac1_clone.list_transports()
assert ac1_clone.get_config("configured_addr") == addr3
assert ac1_clone.get_config("configured_addr") == transport1["addr"]
log.section("ac1 removes the first transport")
ac1.delete_transport(transport1["addr"])
@@ -174,7 +171,7 @@ def test_transport_synchronization(acfactory, log) -> None:
def test_transport_sync_new_as_primary(acfactory, log) -> None:
"""Test synchronization of new transport as primary between devices."""
"""Test that a transport promoted on one device is usable on other devices."""
ac1, bob = acfactory.get_online_accounts(2)
ac1_clone = ac1.clone()
ac1_clone.bring_online()
@@ -193,10 +190,9 @@ def test_transport_sync_new_as_primary(acfactory, log) -> None:
ac1.set_config("configured_addr", transport2["addr"])
ac1_clone.wait_for_event(EventType.TRANSPORTS_MODIFIED)
ac1_clone.wait_for_event(EventType.TRANSPORTS_MODIFIED)
assert ac1_clone.get_config("configured_addr") == transport2["addr"]
assert ac1_clone.get_config("configured_addr") == transport1["addr"]
log.section("ac1_clone receives a message via the new primary transport")
log.section("ac1_clone receives a message via the new transport")
ac1_chat = ac1.create_chat(bob)
ac1_chat.send_text("Hello!")
bob_chat_id = bob.wait_for_incoming_msg_event().chat_id