Skip to content

Commit b4269a5

Browse files
committed
Use abbreviated type specifiers
As per the review, this commit introduces Reddit-style type specifiers for user ids (u/), room aliases (r/), and event ids (e/).
1 parent 246a97e commit b4269a5

File tree

1 file changed

+78
-45
lines changed

1 file changed

+78
-45
lines changed

proposals/2312-matrix-uri.md

Lines changed: 78 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ To cover the use cases above, the following scheme is proposed for Matrix URIs
3939
```text
4040
matrix:[//{authority}/]{type}/{id without sigil}[/{type}/{id without sigil}...][?{query}][#{fragment}]
4141
```
42-
with `{type}` defining the resource type (such as `user` or `roomid` - see
42+
with `{type}` defining the resource type (such as `r`, `u` or `roomid` - see
4343
the "Path" section in the proposal) and `{query}` containing additional hints
4444
or request details on the Matrix entity (see "Query" in the proposal).
4545
`{authority}` and `{fragment}` parts are reserved for future use; this proposal
@@ -65,11 +65,11 @@ pointing to an event in a room.
6565

6666
Examples:
6767
* Room `#someroom:example.org`:
68-
`matrix:room/someroom:example.org`
68+
`matrix:r/someroom:example.org`
6969
* User `@me:example.org`:
70-
`matrix:user/me:example.org`
70+
`matrix:u/me:example.org`
7171
* Event in a room:
72-
`matrix:room/someroom:example.org/event/Arbitrary_Event_Id`
72+
`matrix:r/someroom:example.org/e/Arbitrary_Event_Id`
7373
* [A commit like this](https://github.com/her001/steamlug.org/commit/2bd69441e1cf21f626e699f0957193f45a1d560f)
7474
could make use of a Matrix URI in the form of
7575
`<a href="{Matrix URI}">{Matrix identifier}</a>`.
@@ -187,7 +187,7 @@ be omitted. As can be seen below, Matrix URI rely heavily on [relative
187187
references](https://tools.ietf.org/html/rfc3986#section-4.2) and
188188
omitting the scheme name makes them indistinguishable from a local path
189189
that might have nothing to do with Matrix. Clients MUST NOT try to
190-
parse pieces like `room/MyRoom:example.org` as Matrix URIs; instead,
190+
parse pieces like `r/MyRoom:example.org` as Matrix URIs; instead,
191191
users should be encouraged to use Matrix identifiers for in-text references
192192
(`#MyRoom:example.org`) and client applications SHOULD turn them into
193193
hyperlinks to Matrix URIs.
@@ -232,29 +232,38 @@ This MSC only proposes mappings along `type-qualifier id-without-sigil` syntax;
232232
For the sake of integrity future `nonid-segment` extensions must follow
233233
[the ABNF for `segment-nz` as defined in RFC 3986](https://tools.ietf.org/html/rfc3986#appendix-A).
234234

235-
This MSC defines the following `type` specifiers:
236-
`user` (user id, sigil `@`), `roomid` (room id, sigil `!`),
237-
`room` (room alias, sigil `#`), and `event` (event id, sigil `$`). This MSC
238-
does not define a type specifier for sigil `+`
235+
This MSC defines the following `type` specifiers: `u` (user id, sigil `@`),
236+
`r` (room alias, sigil `#`), `roomid` (room id, sigil `!`), and
237+
`e` (event id, sigil `$`). This MSC does not define a type specifier for sigil `+`
239238
([groups](https://github.com/matrix-org/matrix-doc/issues/1513) aka communities
240239
or, in the more recent incarnation,
241240
[spaces](https://github.com/matrix-org/matrix-doc/pull/1772)); a separate MSC
242241
can introduce the specifier, along with the parsing/construction logic and
243242
relevant CS API invocations, following the framework of this proposal.
244243

245-
As of this MSC, `user`, `roomid`, and `room` can only be at the top
246-
level. The type `event` can only be used on the 2nd level and only under `room`
247-
or `roomid`; this is driven by the current shape of Client-Server API that
248-
does not provide a non-deprecated way to retrieve an event without knowing
244+
The following type specifiers proposed in earlier editions of this MSC and
245+
already in use in several implementations, are deprecated: `user`, `room`, and
246+
`event`. Client applications MAY parse these specifiers as if they were
247+
`u`, `r`, and `e` respectively; they MUST NOT emit URIs with the deprecated
248+
specifiers. The rationale behind the switch is laid out in "Alternatives".
249+
250+
As of this MSC, `u`, `r`, and `roomid` can only be at the top
251+
level. The type `e` (event) can only be used on the 2nd level and only under
252+
`r` or `roomid`; this is driven by the current shape of Client-Server API
253+
that does not provide a non-deprecated way to retrieve an event without knowing
249254
the room (see [MSC2695](https://github.com/matrix-org/matrix-doc/pull/2695) and
250255
[MSC2779](https://github.com/matrix-org/matrix-doc/issues/2779) that may
251-
change this).
256+
change this).
252257

253258
Further MSCs may introduce navigation to more top-level as well as
254259
non-top-level objects; see "Further evolution" for some ideas. These new
255260
proposals SHOULD follow the generic grammar laid out above, adding new `type`
256261
and `nonid-segment` specifiers and/or allowing them in other levels, rather
257-
than introduce a new grammar.
262+
than introduce a new grammar. It is recommended to only use abbreviated
263+
single-letter specifiers if they are expected to be user visible and convenient
264+
for type-in; if a URI for a given resource type is usually generated
265+
(e.g. because the corresponding identifier is not human-friendly), it's
266+
RECOMMENDED to use full (though short) words to avoid ambiguity and confusion.
258267

259268
`id-without-sigil` is defined as the `string` part of Matrix
260269
[Common identifier format](https://matrix.org/docs/spec/appendices#common-identifier-format)
@@ -377,9 +386,9 @@ comparisons are case-INsensitive.
377386

378387
a. Pick the leftmost segment of `path` until `/` (path segment) and match
379388
it against the following list to produce `sigil-1`:
380-
- `user` -> `@`
389+
- `u` (or, optionally, `user` - see "Path") -> `@`
390+
- `r` (or, optionally, `room`) -> `#`
381391
- `roomid` -> `!`
382-
- `room` -> `#`
383392
- any other string, including an empty one -> fail parsing:
384393
the Matrix URI is invalid.
385394

@@ -393,7 +402,7 @@ comparisons are case-INsensitive.
393402
point to an event inside the room identified by `mxid-1`:
394403

395404
a. Pick the next (3rd) path segment:
396-
- if the segment is exactly `event`, proceed;
405+
- if the segment is exactly `e` (or, optionally, `event`), proceed;
397406
- otherwise, including the case of an empty segment (trailing `/`, e.g.),
398407
fail parsing.
399408

@@ -431,11 +440,11 @@ performed on behalf (using the access token) of the user `@me:example.org`:
431440

432441
| URI class/example | Interactive operation | Non-interactive operation / Involved CS API |
433442
| ----------------- | --------------------- | --------------------------------------------- |
434-
| User Id (no `action` in URI):<br/>`matrix:user/her:example.org` | _Outside the room context_: show user profile<br/>_Inside the room context:_ mention the user in the current room (client-local operation) | No default non-interactive operation<br/>`GET /profile/@her:example.org/display_name`<br/>`GET /profile/@her:example.org/avatar_url` |
435-
| User Id (`action=chat`):<br/>`matrix:user/her:example.org?action=chat` | Open a direct chat with the user (see the next column on identifying the room) | If [canonical direct chats](https://github.com/matrix-org/matrix-doc/pull/2199) are supported: `GET /_matrix/client/r0/user/@me:example.org/dm?involves=@her:example.org`<br/>Without canonical direct chats:<br/>1. `GET /user/@me:example.org/account_data/m.direct`<br/>2. Find the room id for `@her:example.org` in the event content<br/>3. if found, return this room id; if not, `POST /createRoom` with `"is_direct": true` and return id of the created room |
436-
| Room (no `action` in URI):<br/>`matrix:roomid/rid:example.org`<br/>`matrix:room/us:example.org` | Attempt to "open" (usually: display the timeline at the latest or last remembered position) the room | No default non-interactive operation<br/>API: Find the respective room in the local `/sync` cache or<br/>`GET /rooms/!rid:example.org/...`<br/> |
437-
| Room (`action=join`):<br/>`matrix:roomid/rid:example.org?action=join&via=example2.org`<br/>`matrix:room/us:example.org?action=join` | Attempt to join the room | `POST /join/!rid:example.org?server_name=example2.org`<br/>`POST /join/#us:example.org` |
438-
| Event:<br/>`matrix:room/us:example.org/event/lol823y4bcp3qo4`<br/>`matrix:roomid/rid:example.org/event/lol823y4bcp3qo4?via=example2.org` | 1. For room aliases, resolve an alias to a room id (HOW?)<br/>2. Attempt to retrieve (see the next column) and display the event;<br/>3. If the event could not be retrieved due to access denial and the current user is not a member of the room, the client MAY offer the user to join the room and try to open the event again | Non-interactive operation: return event or event content, depending on context<br/>API: find the event in the local `/sync` cache or<br/>`GET /directory/room/%23us:example.org` (to resolve alias to id)<br/>`GET /rooms/!rid:example.org/event/lol823y4bcp3qo4?server_name=example2.org`<br/> |
443+
| User Id (no `action` in URI):<br/>`matrix:u/her:example.org` | _Outside the room context_: show user profile<br/>_Inside the room context:_ mention the user in the current room (client-local operation) | No default non-interactive operation<br/>`GET /profile/@her:example.org/display_name`<br/>`GET /profile/@her:example.org/avatar_url` |
444+
| User Id (`action=chat`):<br/>`matrix:u/her:example.org?action=chat` | Open a direct chat with the user (see the next column on identifying the room) | If [canonical direct chats](https://github.com/matrix-org/matrix-doc/pull/2199) are supported: `GET /_matrix/client/r0/user/@me:example.org/dm?involves=@her:example.org`<br/>Without canonical direct chats:<br/>1. `GET /user/@me:example.org/account_data/m.direct`<br/>2. Find the room id for `@her:example.org` in the event content<br/>3. if found, return this room id; if not, `POST /createRoom` with `"is_direct": true` and return id of the created room |
445+
| Room (no `action` in URI):<br/>`matrix:roomid/rid:example.org`<br/>`matrix:r/us:example.org` | Attempt to "open" (usually: display the timeline at the latest or last remembered position) the room | No default non-interactive operation<br/>API: Find the respective room in the local `/sync` cache or<br/>`GET /rooms/!rid:example.org/...`<br/> |
446+
| Room (`action=join`):<br/>`matrix:roomid/rid:example.org?action=join&via=example2.org`<br/>`matrix:r/us:example.org?action=join` | Attempt to join the room | `POST /join/!rid:example.org?server_name=example2.org`<br/>`POST /join/#us:example.org` |
447+
| Event:<br/>`matrix:r/us:example.org/e/lol823y4bcp3qo4`<br/>`matrix:roomid/rid:example.org/event/lol823y4bcp3qo4?via=example2.org` | 1. For room aliases, resolve an alias to a room id (HOW?)<br/>2. Attempt to retrieve (see the next column) and display the event;<br/>3. If the event could not be retrieved due to access denial and the current user is not a member of the room, the client MAY offer the user to join the room and try to open the event again | Non-interactive operation: return event or event content, depending on context<br/>API: find the event in the local `/sync` cache or<br/>`GET /directory/room/%23us:example.org` (to resolve alias to id)<br/>`GET /rooms/!rid:example.org/event/lol823y4bcp3qo4?server_name=example2.org`<br/> |
439448

440449

441450
#### URI construction algorithm
@@ -447,9 +456,9 @@ compliance of identifiers passed to this algorithm.
447456
For room and user identifiers (including room aliases):
448457
1. Remove the sigil character from the identifier and match it against
449458
the following list to produce `prefix-1`:
450-
- `@` -> `user/`
459+
- `@` -> `u/`
460+
- `#` -> `r/`
451461
- `!` -> `roomid/`
452-
- `#` -> `room/`
453462
2. Build the Matrix URI as a concatenation of:
454463
- literal `matrix:`;
455464
- `prefix-1`;
@@ -463,7 +472,7 @@ may change this):
463472
1. Take the event's room id or canonical alias and build a Matrix URI for them
464473
as described above.
465474
2. Append to the result of previous step:
466-
- literal `event/`;
475+
- literal `e/`;
467476
- the event id after removing the sigil (`$`) and percent-encoding.
468477

469478
Clients MUST implement proper percent-encoding of the identifiers; there's no
@@ -481,7 +490,7 @@ extensions. Here are a few ideas:
481490

482491
* Add specifying a segment of the room timeline (`from=$evtid1&to=$evtid2`).
483492

484-
* Unlock bare event ids (`matrix:event/$event_id`) - subject to change in
493+
* Unlock bare event ids (`matrix:e/$event_id`) - subject to change in
485494
other areas of the specification.
486495

487496
* Bring tangible semantics to the authority part. The main purpose of
@@ -516,12 +525,12 @@ extensions. Here are a few ideas:
516525
(also referred to in the previous section).
517526

518527
* One could conceive a URI mapping of avatars in the form of
519-
`matrix:user/uid:matrix.org/avatar/room:matrix.org`
528+
`matrix:u/uid:matrix.org/avatar/room:matrix.org`
520529
(a user’s avatar for a given room).
521530

522-
* As described in "Alternatives" and "Discussion points", respectively, one can introduce a synonymous
523-
system that uses Matrix identifiers with sigils by adding another path
524-
prefix (e.g., `matrix:id/%23matrix:matrix.org`).
531+
* As described in "Alternatives", a synonymous system can be introduced that
532+
uses Matrix identifiers with sigils by adding another path prefix (e.g.,
533+
`matrix:id/%23matrix:matrix.org`).
525534

526535

527536
### Past discussion points and tradeoffs
@@ -534,8 +543,10 @@ further discussion should happen in GitHub comments.
534543
`//` if the URI doesn't have an authority component. In other words,
535544
`//` implies a centre of authority, and the (public) Matrix
536545
federation is not supposed to have one; hence no `//` in most URIs.
537-
1. _Why do type specifiers use singular rather than plural
538-
as is common in RESTful APIs?_
546+
1. ~~_Why do type specifiers use singular rather than plural
547+
as is common in RESTful APIs?_~~
548+
This is no more relevant with single-letter type specifiers. The answer
549+
below is provided for history only.
539550
Unlike in actual RESTful APIs, this MSC does not see `rooms/` or
540551
`users/` as collections to browse. The type specifier completes
541552
the id specification in the URI, defining a very specific and
@@ -579,18 +590,40 @@ further discussion should happen in GitHub comments.
579590

580591
### Alternatives
581592

582-
#### Reddit-style URLs
583-
584-
Reddit style (`matrix:r/matrix:matrix.org`, `matrix:u/me:example.org` etc.)
585-
is almost as compact as original Matrix identifiers, while still rather
586-
clearly conveys the type and nicely avoids the singular vs. plural confusion
587-
described in the previous section. However, in the context of high requirements
588-
to URL grammar stability, Reddit-style prefixes would eventually produce
589-
bigger ambiguity as a primary notation; but they can be handy as shortcuts.
590-
As discussed in "Future evolution", the current proposal provides enough space
591-
to define synonyms; this may need some canonicalisation service from
592-
homeservers so that we don't have to enable synonyms at each client
593-
individually.
593+
#### Using full words for all types
594+
595+
During its draft state, this MSC was proposing type specifiers using full words
596+
(`user`, `room`, `event` etc.), arguing that abbreviations can be introduced
597+
separately as synonyms. Full words have several shortcomings pointed out in
598+
discussions across the whole period of preparation, namely:
599+
- The singular vs. plural choice (see also "Past discussion points")
600+
- Using English words raises a question about eventual support of localised
601+
URI variants (`matrix:benutzer/...`, `matrix:usuario/...` etc.) catering to
602+
international audience, that would add complication to the Matrix technology.
603+
- Abbreviated forms are popularised by Reddit and make URIs shorter which is
604+
crucial for the outbound integration case (see the introduction).
605+
606+
Meanwhile, using `u`/`r`/`e` for users, rooms and events has the following
607+
advantages:
608+
1. there's a strong Reddit legacy, with users across the world quite familiar
609+
with the abbreviated forms (and `r/` coincidentally standing for sub-Reddits
610+
links to which have basically the same place in the Reddit ecosystem as
611+
Matrix room aliases have in the Matrix ecosystem);
612+
2. matrix.to links to users and room aliases are heavily used throughout Matrix,
613+
specifically in end-user-facing contexts (see also use cases in the
614+
introductory section of this MSC);
615+
3. the singular vs. plural (`room` or `rooms`?) confusion is avoided;
616+
4. it's shorter, which is crucial for typing the URI in an external medium.
617+
618+
The rationale behind not abbreviating `roomid/` is a better distinction between
619+
room aliases and room ids; also, since room ids are almost never typed in
620+
manually, the advantages (3) and (4) above don't hold.
621+
622+
For these reasons, it was decided in the end to use the single-letter style
623+
for types most used in the outbound integration case. It's still possible to
624+
reinstate full words as synonyms some time down the road, with the caveat that
625+
a canonicalisation service from homeservers may be needed to avoid having
626+
to enable synonyms at each client individually.
594627

595628
#### URNs
596629

0 commit comments

Comments
 (0)