mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-18 14:52:04 +00:00
fix(matrix): device_id fallback prevents E2EE init failure on fresh bot accounts
- Resolve device_id via query_keys({mxid: []}) when whoami() returns None
- Guard _verify_device_keys_on_server and _reverify_keys_after_upload
against None/unverified device_id to prevent 'device_keys values must
be a list of strings' serialization failure
- Disconnect existing client before reconnect to prevent dual OlmMachine
instances on the same crypto store
Re-targeted from #39779 (legacy gateway/platforms/matrix.py) onto the
migrated plugins/platforms/matrix/adapter.py path following the
2026-06-20 adapter migration. Logic unchanged from original fix.
242 tests passing (233 upstream + 9 new).
This commit is contained in:
parent
2d8d08cae6
commit
9048457eab
2 changed files with 440 additions and 0 deletions
|
|
@ -806,6 +806,7 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
self._device_id: str = config.extra.get("device_id", "") or os.getenv(
|
||||
"MATRIX_DEVICE_ID", ""
|
||||
)
|
||||
self._device_id_unverified: bool = False
|
||||
|
||||
self._client: Any = None # mautrix.client.Client
|
||||
self._crypto_db: Any = None # mautrix.util.async_db.Database
|
||||
|
|
@ -1039,6 +1040,12 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
self, client: Any, local_ed25519: str
|
||||
) -> bool:
|
||||
"""Re-query the server after share_keys() and verify our ed25519 key matches."""
|
||||
if not client.device_id or self._device_id_unverified:
|
||||
logger.warning(
|
||||
"Matrix: skipping post-upload key verification — "
|
||||
"device_id not yet established"
|
||||
)
|
||||
return True
|
||||
try:
|
||||
resp = await client.query_keys({client.mxid: [client.device_id]})
|
||||
dk = getattr(resp, "device_keys", {}) or {}
|
||||
|
|
@ -1065,6 +1072,12 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
Returns True if keys are valid or were successfully re-uploaded.
|
||||
Returns False if verification fails (caller should refuse E2EE).
|
||||
"""
|
||||
if not client.device_id or self._device_id_unverified:
|
||||
logger.warning(
|
||||
"Matrix: skipping device key verification — "
|
||||
"device_id not yet established"
|
||||
)
|
||||
return True
|
||||
try:
|
||||
resp = await client.query_keys({client.mxid: [client.device_id]})
|
||||
except Exception as exc:
|
||||
|
|
@ -1139,6 +1152,12 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
|
||||
async def connect(self, *, is_reconnect: bool = False) -> bool:
|
||||
"""Connect to the Matrix homeserver and start syncing."""
|
||||
if self._client is not None:
|
||||
try:
|
||||
await self.disconnect()
|
||||
except Exception as exc:
|
||||
logger.warning("Matrix: error disconnecting before reconnect: %s", exc)
|
||||
|
||||
from mautrix.api import HTTPAPI
|
||||
from mautrix.client import Client
|
||||
from mautrix.client.state_store import MemoryStateStore, MemorySyncStore
|
||||
|
|
@ -1189,6 +1208,36 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
if effective_device_id:
|
||||
client.device_id = effective_device_id
|
||||
|
||||
if not client.device_id:
|
||||
try:
|
||||
dev_resp = await client.query_keys({client.mxid: []})
|
||||
all_devices = (
|
||||
(getattr(dev_resp, "device_keys", {}) or {})
|
||||
.get(str(client.mxid)) or {}
|
||||
)
|
||||
if len(all_devices) == 1:
|
||||
client.device_id = next(iter(all_devices))
|
||||
elif len(all_devices) == 0:
|
||||
logger.warning(
|
||||
"Matrix: no devices found for %s — "
|
||||
"key verification will be skipped",
|
||||
client.mxid,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"Matrix: device list query failed: %s", exc
|
||||
)
|
||||
|
||||
if not client.device_id:
|
||||
logger.warning(
|
||||
"Matrix: device_id could not be resolved for %s. "
|
||||
"Set MATRIX_DEVICE_ID for full key verification. "
|
||||
"E2EE will proceed without server-side device "
|
||||
"key confirmation.",
|
||||
client.mxid,
|
||||
)
|
||||
self._device_id_unverified = True
|
||||
|
||||
logger.info(
|
||||
"Matrix: using access token for %s%s",
|
||||
self._user_id or "(unknown user)",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue