Add MatrixTransport (A1) — step-2 PR B
CI / checks (push) Successful in 10s
CI / checks (pull_request) Successful in 10s

- matrix.py: Transport implementation over the Matrix client-server
  HTTP API directly (token auth, /sync long-poll, /send) using the
  existing httpx dependency — no Matrix SDK; four endpoints total.
  Deviation from the presented plan (matrix-nio) flagged in the PR
- First sync learns position and skips backlog, so room history is
  never delivered as context (A1); own messages and non-message
  events filtered; sender MXID passed through for the orchestrator's
  operator allowlist
- Sync loop backs off (capped at 60s) and retries indefinitely on
  homeserver errors, mirroring B2's polling posture
- Encrypted rooms unsupported: bot rooms are created unencrypted
  until E2E lands (operator decision; room recreated accordingly)
- NISSE_MATRIX_TEST_ROOM_ID added: the live smoke test binds only
  to the dedicated test room, never the production room
- 8 unit tests over a mocked HTTP layer; live integration test
  verified against the real homeserver

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
dongarandClaude Fable 5 committed 2026-09-06 23:52:45 +00:00
1 parent 5dad5cf90f
commit 5db6d9d96e
4 files changed
+380

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
"""Live smoke test against the real homeserver, bound strictly to the
dedicated test room (never the production room). Skips unless the Matrix env
vars, including NISSE_MATRIX_TEST_ROOM_ID, are present."""
import os
import uuid
from pathlib import Path
import pytest
from nisse_dev.envfile import load_env_file
from nisse_dev.matrix import MatrixConfig, MatrixTransport
load_env_file(Path(__file__).resolve().parents[2] / ".env")
REQUIRED = (
"NISSE_MATRIX_HOMESERVER",
"NISSE_MATRIX_USER_ID",
"NISSE_MATRIX_TOKEN",
"NISSE_MATRIX_TEST_ROOM_ID",
)
pytestmark = [
pytest.mark.integration,
pytest.mark.skipif(
not all(os.environ.get(var) for var in REQUIRED),
reason=f"live matrix config absent; set {', '.join(REQUIRED)}",
),
]
def test_send_lands_in_test_room() -> None:
config = MatrixConfig.from_env(room_var="NISSE_MATRIX_TEST_ROOM_ID")
marker = f"transport smoke test {uuid.uuid4().hex}"
transport = MatrixTransport(config)
try:
transport.send_message(marker)
response = transport._http.get(
f"/rooms/{config.room_id}/messages",
params={"dir": "b", "limit": "10"},
)
response.raise_for_status()
bodies = [
event.get("content", {}).get("body")
for event in response.json().get("chunk", [])
]
assert marker in bodies
finally:
transport.close()