public/matrix.md
2024-05-22 04:03:59 -07:00

301 lines
14 KiB
Markdown

::: header
# thoughts on matrix
:::
::: section
I've used matrix for a while now. While the core idea is excellent and
there's so many good ideas, there's so many bad parts and annoyances
with it. Parts of the protocol feel like they were patched together by
someone until they went "eh looks about right", while other parts are
incoherent or give off strong design-by-comittee vibes. I'm going to
keep using matrix, but because of these problems I won't suggest it to
any other people.
This critique looks at matrix from an end user's perspecive as well as
from a more technical perspective and is mostly a thought dump, so it
may be hard to follow.
## threads
Threads are implemented as fancy replies. This makes it easy for people
using clients without threads to accidentally reply to a threaded message
from outside of a thread, causing things to break. It also causes
per-thread typing notifications and read receipts to be chronically
broken. Once you send a message in a thread it's permanently added to
"my threads" with no way of removing it later. There's also pretty much
no qol features, like thread titles/names or being able to archive old
threads. There's no way to lock threads (though this is fairly niche and
to my knowledge would be extremely difficult to implement). On top of all
that, there's no way disable threads in a room. Thread only rooms would
be nice and technically only need special ui, but don't currently exist.
Making threads their own rooms (threads as rooms) would solve some of
these problems, but would cause problems elsewhere. Searching messages
across the main room and threads would be harder to implement. Access
control would need to be synced, and "rogue threads" which don't set
power levels for the parent room's moderators could be created. There's
no way to add other people to threads (ie. in the case of "reply in
thread"). Letting people peek in threads without joining would rely on
features that don't exist currently, like federated peeking as well as
a version of history_visibility for peeking. This could also lead to
amplification: currently, creating a thread is as expensive as sending
a message, wheras each thread as room would need its own set of state
(m.room.create, m.room.member, m.room.join_rules, etc)
(Aside: it looks like having a "main thread/chat" and "threads" are
fundementally incompatible. Most people would like messages would be
properly threaded, but there's an easier to use main thread and ui
encouraging its use. There's a fundemental tension and neither option
is quite correct.)
## push rules
Push rules are how a matrix client and server decides whether a message
sends a push notification, makes a sound, and so forth.
All push rules go in one giant blob in global account data, which I
think some of which should have been split out into per-room account
data. Push rules have seemingly arbitrary groupings: muting
a room goes in the `overrides` group, but receiving notifications for
all messages goes in the `rooms` group.
When changing a lot of room-specific push rules, the rules can overwrite
each other in flight, causing some room-specific push rules to reset/be
dropped. This is technically an issue with all push rules, but most of the
time it isn't noticable to end users. Push rules get around this by having
an entire separate set of apis for changing fine-grained account data.
The rules are written in a json <abbr title="domain specific
language">dsl</abbr>-like thing that is needlessly flexible. This causes
performance issues. Simultaneously, they're somehow extremely rigid. It
is only possible to use one of the 6 predefined conditions and the only
counters that exist are `notify_count` and `highlight_count`. Notably,
there's no `unread_count`. My workaround for now is to patch clients
to not notify unless the highlight tweak is set, and use `notify_count`
as an unread count.
Mentions are currently implemented as searching the message body for a
display name/username, which can cause accidental notifications. Saying
people's names without notifying them needs workarounds like
1337speek. This is slated to be fixed with intentional mentions,
where mentions are extracted to their own json field. Unfortunately,
it looks like encrypted messages will put the mentions in encrypted
content, breaking rules (todo: heard this from somewhere, but need a
source). Ironically, the one time metadata is made less leaky, it also
happens to be the one time where it makes sense and is needed for good ux.
The `/notifications` endpoint paginates through a list of pings/mentions,
though due to the above paragraph won't show any mentions in encrypted
rooms. There's no way to filter mentions per room/space or if it's @room.
Although "list of mentions" makes sense naively, it would be much better
to have an inbox where messages be added and removed.
No client supports marking rooms, threads, or events as unread.
There's no way to temporarily mute rooms (or all notifications). Since a
room can be in multiple spaces, there's no easy way to mute all rooms in
a space. There's no way to only mute @room notifications while allowing
user mentions.
## e2ee
Matrix's implementation of end to end encryption leaks a lot of metadata,
including but not limited to room name/topic/avatar, member per-room
displaynames/avatars, and reactions.
Newly joined members can't view old e2ee messages. This is fixable,
but not yet fixed.
It's also remarkably easy to get undecryptable messages by accident,
and is the **single biggest reason** why I'm not recommending matrix to
anyone else for now. It needs to be more robust and have a better ux.
## apis
Syncing is slow and sends tons of extra data, though sliding sync is
aiming to fix it. No comment will be made on sliding sync, as its apis
are currently in flux. EDIT: Sliding sync is shaping up quite nicely,
but I think there are some mistakes, like `room_name_like` and sorting.
Similarily, the authentication mess is slated to be replaced with OIDC,
so no comment there until it's fleshed out more properly. The current
system isn't terrible, but isn't great either. Getting a seamless ux,
both for users and server admins, looks like it will be pretty difficult
to achieve.
A lot of apis are unergonomic or difficult to use. For example, every
event/message needs to be sent with a random transaction id, which is
annoying when trying to use webhooks. The api doesn't use one event model:
there are events, events without room_id, stripped state events, and
stripped state events with `origin_server_ts`. The application service
api doesn't support e2ee without workarounds *yet*.
The media repository (media repo) lets users store blobs, but it feels
tacked on instead of part of the protocol. Each piece of media is stored
on a single canonicical and trusted server (aka point of failure), unlike
rooms. There is no way to delete uploaded blobs from the media repo.
The apis are trying to be generic while geared towards instant messaging:
`/search` is only indexes blessed keys and even types, which are
different per server. This could be fixed by having a blessed `body`
property that is always indexed, regardless of event type. Events are
able to form graphs but can't be recursively queried. Rooms didn't
have types until relatively recently, and most clients will display
all rooms regardless of type anyway. There also isn't any subtyping
(mutable types, ie. to convert a room between a normal room and dm).
I know instant messaging is the main puropse of matrix,
but for medium-large communities I *really* wish there
was some form of forum system. Something similar to
tildes.net would be ideal, especially the [hierarchical
tagging](https://docs.tildes.net/instructions/hierarchical-tags)
and [comment
labelling](https://docs.tildes.net/instructions/commenting-on-tildes#labelling-comments),
though the extra sorting/filtering is probably too much to ask.
## bots
Bots are hard to get right, as there's no way to use structured commands
(ie. discord and telegram slash commands). Bots need to parse the
message's body. This has problems, since reply fallbacks exist. Parsing
mentions and other things from the body is also difficult, requiring
parsing html.
There's no way to specify interactions, like buttons, menus, canned
responses, preset reactions, etc. Reaction-based uis are the best to
currently exist, but it takes n + 1 events where n is the number of
"buttons".
Matrix seems to be heading towards a widget-based ui system, where
widgets are embedded webpages/webapps. Clients that want to support
widgets would need to embed an entire web browser. Even though it could
be more flexible, it would be much more annoying for bot developers to
learn an entirely separate widget api as well as well as use html/css/js
instead of matrix events and json. Since widgets seem to be able to do
interactions on behalf of the user(?), clients need to take extra care
in implementing sandboxing and access control. Widget ui would also
wouldn't fit in as well with the rest of the client. Widgets might
have issues with privacy and tracking because they can use arbitrary
html/js/css.
Bots can use the full set of html, including tables and
details/summary. However, different clients may only support certain
subsets of html.
## potpourri
Matrix can be generalized as logs of arbitrary json events combined
with a crdt of map<(type, state), event>. Although this could be led
to *so many* use cases, the official client-server api isn't flexible
enough as mentioned above. However, it's entirely possible to use the
core matrix protocol with a custom client-server api + custom client,
activitypub style.
Messages can either be text or a single file, but not both (like a file
with a comment) or multiple attachments.
Clients are missing features or are buggy. A lot of spec is dictated by
synapse and element, even when spec.matrix.org says otherwise. Old and
buggy room versions exist in the wild, with no incentive to upgrade.
Federation is excellent in theory, but in practice servers tend to drop
events.
Power levels are pretty rudimentary. There's no way allow/deny specific
rel_types, only event types. There is no role based access control.
There's no way to peek into dms. (Or federated rooms, for that matter.)
There are many msc (matrix spec change) proposals that seem to have
gotten stuck, like custom emoji/stickers.
Room-specific user displaynames/avatars can be overwritten when the
global displayname/avatar is changed.
Anything added to spec can't be removed later, which is to be expected
for a protocol. But when mscs are opened, events are sent with unstable
identifiers. Clients later will need to support both the official type
and unstable identifier to support past events.
Moderation is lacking, and it's pretty much required to use a bot
([mjolnir](https://github.com/matrix-org/mjolnir)) (not that bad,
but a bit annoying for smaller rooms). When cleaning up spam, a
redaction event must be sent for each message/event - bulk redactions
([msc2244](https://github.com/matrix-org/matrix-spec-proposals/pull/2244))
have been merged but isn't in spec and doesn't seem to be implemented
by any server.
`GET /state` returns the content of a state event, not the full event
itself.
## conclusion
7.8/10 too much water
## wishlist
In no particular order. These requests shouldn't be too difficult
to implement, but would improve usability by *so* much. These aren't
nearly fleshed out to be full mscs.
- Cleanup threads and improve usability
- ~~`DELETE /rooms/{roomId}/threads/{eventId}` to stop participating in
a thread~~
- `PUT /rooms/{roomId}/threads/{eventId}/participation` to change
whether you're participating in or aren't participating in a thread.
- Thread-only rooms.
- Redo power levels
- Base them on `(from_event_type, rel_type, to_event_type)` tuples rather
than `(event_type)` alone.
- Implement rbac (roles). Ideally, it would use explicit deny as the
permission model. May be blocked on "give every member a role" use cases.
- Add a way to make spaces sync subsets of state with the child
rooms. msc3216 and msc2962 exist for power levels, which may be enough
for most use cases
- Add a way to mute rooms temporarily. Maybe add a push rule condition
for this, or better yet redo push rules entirely. (I know the whole
"don't rewrite what works", but seriously...)
- Make aliases and visibility less confusing. There's room visibility,
history visibility, local/published/main alias(es), and the
room directory. In ui, room directory could be merged into room
visibility. I'm not sure how to simplify aliases without reducing
functionality.
- Improve /notifications to be more like a proper inbox
- Use intentional mentions (even in encrypeted rooms) to populate the list
- `DELETE /notifications` + `DELETE /notifications/{eventId}` along
with automatically removing old notifications to enhance usability
- `PUT /notifications/{eventId}` to bookmark an event for later (though,
this may be better served with "starred/bookmarked messages")
- Some way to reorder notifications? Maybe the `PUT` endpoint could
take an "order" key.
- Add a `m.preset_reactions` or `m.interactions` key for bots.
- Bot supplied edits or annotations?
- `unread_count` to view the number of unread messages in a room, see msc2654
- This might only be something I want, but another presence/status type
different from online for when you're explicitly available to talk to
woul be nice. I really want to be able to have a clear split between
"being on the internet" and "willing to have my attention taken"
<!--
## the far future?
Some random ideas on how matrix could look in the far future...
Memberships could be made ephemeral. A user's membership could be
`allow` (invite, join) or `deny` (kick, leave, ban). In private rooms,
the default membership would be `deny` and in public rooms it would
be `allow`. When a member's membership is explicitly set to `allow`,
they are invited to the room. A member can send a special ephemeral
(or timeline) event to tell other servers they have acknowledged the
membership change and are now joined. Of course in practice, more
memberships/states would need to be added, like `null`/`default` or
`knock`. The main problem would be making restricted rooms work.
No matter how many apis you try to add, some use case will need something
special. I wonder how feasable it would be to use wasm instead of
room versions for permissions, custom sorting/filtering/indexing,
and deriving custom unsigned/state. It could even do state resolution,
although this is extremely difficult, may have security issues, and is
probably impractical. The main problem is wasm would need to be embedded
in the event or be placed in the media repo.
-->
:::