Skip to content

responder.py / sas_verification.py: three gaps blocking the matrix-bot-setup skill #40

@amiller

Description

@amiller

Surfaced while building dmarzzz/shape-rotator-field-kit#20 (the matrix-bot-setup skill). The skill walks an end-user through /signup/api/signup/api/crosssign → launch the prod-served landing/responder.py → click Verify in Element. End-state should be: bot signed by the user's USK, no red shields, full E2EE round-trip.

Three issues in landing/{responder.py,sas_verification.py} block that. Listed in priority order.

1. sas_verification.SASVerificationManager is to-device-only (load-bearing)

SASVerificationManager.__init__ (lines ~200–210) registers handlers exclusively under EventType.Class.TO_DEVICE. Modern Element initiates verification in-room when both parties share an E2EE room — m.key.verification.request arrives as an m.room.message content type in the DM, not as a to-device event.

That's exactly the path a user hits when they click "Verify" on the bot from their DM. The event reaches responder.py's on_msg handler, which matches only !ping/!whoami/!help and drops everything else. The SAS state machine never enters.

Repro: spin up a bot via the matrix-bot-setup skill, click Verify on the bot in Element (matrix.org account). Element shows "waiting for verification" forever. No SAS log entries on the responder side.

Fix sketch: extend SASVerificationManager to also listen for in-room m.key.verification.* (treating an m.room.message with msgtype=m.key.verification.request as the same entry point), and have responder.py's on_msg defer those to the manager before its command-dispatch path.

tests/sas_prod.py passes because its _SASInitiator sends to-device directly — but a real Element user never goes through that path.

2. responder.py crashes on the auto-intro post path

landing/responder.py:132:

resp = await client.send_message_event(DM_ROOM, EventType.ROOM_MESSAGE, content)
print(f"POSTED:{resp.event_id}", flush=True)

In current mautrix-python (0.21.0), send_message_event returns a str (the event_id), not an object. The .event_id access raises AttributeError and kills the responder right after a successful send.

Triggers whenever both DM_ROOM and INTRO env vars are set — i.e. anyone trying to use the documented auto-intro feature. The matrix-bot-setup skill bootstrap.py deliberately omits those env vars to dodge it, at the cost of leaving the new bot's auto-DM to the inviter empty (regression of UX in service of not crashing).

Fix: print(f"POSTED:{resp}", flush=True).

3. No logging.basicConfig() in responder.py

sas_verification.py uses logger = logging.getLogger("gateway.platforms.matrix.sas") and calls logger.info(...) for every SAS protocol step — request received, ready sent, accept, key, MAC, done, cancel reason. Without an explicit basicConfig, Python's root logger defaults to WARNING and all of that is silently dropped.

Made the SAS debugging in the field-kit-skill development session pure guesswork until I patched the local copy of responder.py to add logging.basicConfig(level=logging.INFO). Anyone running the prod-served responder will hit the same silent-failure UX.

Fix: one line near the top of responder.py —

logging.basicConfig(
    level=os.environ.get("LOG_LEVEL", "INFO"),
    format="%(name)s: %(message)s",
)

Severity

(1) is the load-bearing one. Without it the matrix-bot-setup skill produces a bot that's E2EE-capable for !ping/!whoami round-trip but shows as unverified in Element forever, because the Verify click silently no-ops on the bot side. (2) and (3) are quality-of-life — (2) is a regression of a documented feature, (3) is a debug-experience hit.

Happy to PR any/all of these if useful.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions