diff --git a/gateway/platforms/matrix.py b/gateway/platforms/matrix.py index a5f9352b5..15589d991 100644 --- a/gateway/platforms/matrix.py +++ b/gateway/platforms/matrix.py @@ -532,6 +532,20 @@ class MatrixAdapter(BasePlatformAdapter): ) await crypto_store.open() + # Bind the store to the runtime device_id before any + # put_account() runs. PgCryptoStore defaults _device_id + # to "" and its crypto_account UPSERT never updates the + # device_id column on conflict — so once put_account + # writes blank, it stays blank forever. That breaks + # every downstream device-scoped olm operation: peer + # to-device ciphertext can't find our identity key and + # no megolm sessions ever land. Setting _device_id here + # (in-memory; the on-disk row may not exist yet) makes + # the first put_account write the correct value. + # DeviceID is a NewType(str) so plain str works at runtime. + if client.device_id: + await crypto_store.put_device_id(client.device_id) + crypto_state = _CryptoStateStore(state_store, self._joined_rooms) olm = OlmMachine(client, crypto_store, crypto_state) diff --git a/tests/gateway/test_matrix.py b/tests/gateway/test_matrix.py index a088ad9ba..50a8a6675 100644 --- a/tests/gateway/test_matrix.py +++ b/tests/gateway/test_matrix.py @@ -197,10 +197,14 @@ def _make_fake_mautrix(): self.account_id = account_id self.pickle_key = pickle_key self.db = db + self._device_id = "" async def open(self): pass + async def put_device_id(self, device_id): + self._device_id = device_id + mautrix_crypto_store_asyncpg.PgCryptoStore = PgCryptoStore # --- mautrix.util ---