Let the channel mount open an attachment, not just name it #111

Closed
opened 2026-08-25 06:47:52 +00:00 by jlxq0 · 0 comments
Owner

CHANNEL_TOOLS in src/channel.rs:182 is seven tools:

whoami, list_joined_rooms, read_recent_messages, read_thread,
send_text_message, send_reaction, mark_read

download_attachment is not among them, and /channel offers only that list.
So once #110 ships the attachment-carrying fix (#107), a session on the channel
mount learns that a file arrived — attachment="m.image", filename="...", and
the caption as prose when the sender wrote one — and has no way to open it.

That is the actual answer to "am I receiving the pictures you send": after #110,
the notice, never the bytes. Worth fixing in the same stretch, because a
screenshot is how Julian shows a session what he is looking at, and a filename
is not a screenshot.

What to add

Add download_attachment to CHANNEL_TOOLS. Routing already scopes the channel
mount to one authenticated identity, and DownloadAttachmentParams takes a
room_id and an event_id, so the tool cannot reach a room the identity is not
joined to. The existing download_max_bytes cap (checked against the event's
declared info.size before any media I/O) applies unchanged.

Check while you are in there:

  • Does it decrypt? The rooms in use are E2EE and the m.image content
    carries a file object with the AES key rather than a plain url.
    DownloadAttachmentResult documents body_base64 as "file contents", which
    reads as decrypted, but confirm it against a real encrypted event rather than
    against the doc comment.
  • Does the channel instructions string need to say the tool exists? The
    model is told how to reply and how to mark read; if it is not told it can
    fetch an attachment it will report the filename and stop.

Acceptance

Julian sends one screenshot into !nJqaJVNKzmgkUjjSLE:kampong.social, and the
session reports what is visibly in the image. Not that the tool is listed, and
not that it returned bytes — a deferred schema can be present while the fetch
fails, and base64 of a still-encrypted blob is bytes too.

Then the negative control: an event_id in a room the identity is not joined to
is refused, and an event whose declared size exceeds download_max_bytes is
refused before any media I/O.

  • #107 carries attachments (merged, unreleased)
  • #110 releases it
  • #109 permission relay, same mount
`CHANNEL_TOOLS` in `src/channel.rs:182` is seven tools: whoami, list_joined_rooms, read_recent_messages, read_thread, send_text_message, send_reaction, mark_read `download_attachment` is not among them, and `/channel` offers only that list. So once #110 ships the attachment-carrying fix (#107), a session on the channel mount learns that a file arrived — `attachment="m.image"`, `filename="..."`, and the caption as prose when the sender wrote one — and has no way to open it. That is the actual answer to "am I receiving the pictures you send": after #110, the notice, never the bytes. Worth fixing in the same stretch, because a screenshot is how Julian shows a session what he is looking at, and a filename is not a screenshot. ## What to add Add `download_attachment` to `CHANNEL_TOOLS`. Routing already scopes the channel mount to one authenticated identity, and `DownloadAttachmentParams` takes a `room_id` and an `event_id`, so the tool cannot reach a room the identity is not joined to. The existing `download_max_bytes` cap (checked against the event's declared `info.size` before any media I/O) applies unchanged. Check while you are in there: - **Does it decrypt?** The rooms in use are E2EE and the `m.image` content carries a `file` object with the AES key rather than a plain `url`. `DownloadAttachmentResult` documents `body_base64` as "file contents", which reads as decrypted, but confirm it against a real encrypted event rather than against the doc comment. - **Does the channel instructions string need to say the tool exists?** The model is told how to reply and how to mark read; if it is not told it can fetch an attachment it will report the filename and stop. ## Acceptance Julian sends one screenshot into `!nJqaJVNKzmgkUjjSLE:kampong.social`, and the session reports what is visibly in the image. Not that the tool is listed, and not that it returned bytes — a deferred schema can be present while the fetch fails, and base64 of a still-encrypted blob is bytes too. Then the negative control: an `event_id` in a room the identity is not joined to is refused, and an event whose declared size exceeds `download_max_bytes` is refused before any media I/O. ## Related - #107 carries attachments (merged, unreleased) - #110 releases it - #109 permission relay, same mount
jlxq0 closed this issue 2026-08-25 07:11:40 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jlxq0/matrix-mcp#111
No description provided.