mirror of
https://github.com/matrix-org/matrix-spec
synced 2025-12-26 10:58:38 +01:00
Compare commits
545 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f6867348f | ||
|
|
6b5ff04d00 | ||
|
|
ce5ae4d371 | ||
|
|
27315feb17 | ||
|
|
a1c930d0d1 | ||
|
|
9e959f3922 | ||
|
|
7c39427d8b | ||
|
|
54944e2866 | ||
|
|
13aa6e83ae | ||
|
|
705240da72 | ||
|
|
4dbe080570 | ||
|
|
7a1eb81c9c | ||
|
|
22c0952003 | ||
|
|
a5afe542c0 | ||
|
|
d28e05af87 | ||
|
|
b1fd2af72c | ||
|
|
f7a0d8d135 | ||
|
|
a2027a3985 | ||
|
|
ff1a39e36a | ||
|
|
add0f2232c | ||
|
|
8ebf4a4789 | ||
|
|
935c23485b | ||
|
|
fe3f43a905 | ||
|
|
4783619964 | ||
|
|
4cafe7d9f4 | ||
|
|
e2b2e56bd2 | ||
|
|
967b54195c | ||
|
|
9d063c8d2d | ||
|
|
74a0d5f289 | ||
|
|
974b0b721e | ||
|
|
fda3be5ee3 | ||
|
|
7f4072d993 | ||
|
|
58744f4734 | ||
|
|
dfdb1d09b8 | ||
|
|
f82d8ab15b | ||
|
|
b6a127b5cb | ||
|
|
0a649cb0db | ||
|
|
d8be2ad942 | ||
|
|
21109b4d5b | ||
|
|
d4d31a8894 | ||
|
|
d968774fb7 | ||
|
|
2aacc1feda | ||
|
|
2a8c0bc7b8 | ||
|
|
81a864545f | ||
|
|
671bc674cd | ||
|
|
72a2ebc7ad | ||
|
|
7bc016bda6 | ||
|
|
fea0b925a0 | ||
|
|
bfbeb5e257 | ||
|
|
d1a51f7b8c | ||
|
|
6e16a19ac9 | ||
|
|
4d4069166d | ||
|
|
b5ee6adc0f | ||
|
|
f97d2944ae | ||
|
|
c4bfd2feb8 | ||
|
|
04f42ac208 | ||
|
|
f6d5009959 | ||
|
|
9c313b099f | ||
|
|
67a2aa4761 | ||
|
|
7d2de48cb4 | ||
|
|
fb4a0d8f66 | ||
|
|
4c87e0e745 | ||
|
|
3e1e9fa8df | ||
|
|
c8380d9552 | ||
|
|
3877598b1e | ||
|
|
0e280ed014 | ||
|
|
625ed5c599 | ||
|
|
484a777572 | ||
|
|
6edb6ba1cd | ||
|
|
40065811a1 | ||
|
|
1c06ed9cf7 | ||
|
|
6353b46add | ||
|
|
0e05e45d84 | ||
|
|
b278a4e0ec | ||
|
|
ccd9e50eb1 | ||
|
|
e4740e36e8 | ||
|
|
9244c84a32 | ||
|
|
979264e923 | ||
|
|
51ccbbd240 | ||
|
|
a2a9a02efa | ||
|
|
32b1f0514d | ||
|
|
7bcc3ecb81 | ||
|
|
866c05f487 | ||
|
|
7470c72d94 | ||
|
|
643a6dca2d | ||
|
|
cbf1854b93 | ||
|
|
2c734c3c5b | ||
|
|
075d203ecd | ||
|
|
4ed55a60ec | ||
|
|
67743d5715 | ||
|
|
338047ec7b | ||
|
|
0439707624 | ||
|
|
f4e6e6dea9 | ||
|
|
73fcf366a0 | ||
|
|
0a1efd8c9c | ||
|
|
2c6ddafb43 | ||
|
|
fc81171081 | ||
|
|
c74befd111 | ||
|
|
ca9c376076 | ||
|
|
fe46e0c363 | ||
|
|
a8c326962a | ||
|
|
fca171427f | ||
|
|
81273df88e | ||
|
|
65b1db721d | ||
|
|
c39c7d0680 | ||
|
|
23ff7f1343 | ||
|
|
8a2c58b1b1 | ||
|
|
817ec5380f | ||
|
|
029be205b9 | ||
|
|
fe880fdaf4 | ||
|
|
71ce620fc0 | ||
|
|
cb6d039c57 | ||
|
|
c7581356bf | ||
|
|
7fd49a2808 | ||
|
|
e283c35dbd | ||
|
|
1916e53f8c | ||
|
|
02a1aeefbc | ||
|
|
3adbfa30da | ||
|
|
4ff9a851e6 | ||
|
|
844dd6f8ae | ||
|
|
dfc61ffc71 | ||
|
|
60339adb2d | ||
|
|
ae06f37470 | ||
|
|
10587366e9 | ||
|
|
eedecf863a | ||
|
|
cb83c5a76e | ||
|
|
c2ef38f0e5 | ||
|
|
dcb39c603a | ||
|
|
23e709ae9b | ||
|
|
cabe846d23 | ||
|
|
9e0f2aad94 | ||
|
|
cd6ae9e1a2 | ||
|
|
a1bdfaa167 | ||
|
|
d0d71d9997 | ||
|
|
ad17652fce | ||
|
|
b9b10c4920 | ||
|
|
42364c5155 | ||
|
|
b9f46d1d85 | ||
|
|
e341525e04 | ||
|
|
ba73e0d97a | ||
|
|
6f1e64cb12 | ||
|
|
baa60bf728 | ||
|
|
2df3f7a7bf | ||
|
|
1d98e96300 | ||
|
|
bc995e66d6 | ||
|
|
921c6becf1 | ||
|
|
35c3ddb33b | ||
|
|
2fd5bf10bb | ||
|
|
355f92ff99 | ||
|
|
96b32f68f9 | ||
|
|
846cc49eb2 | ||
|
|
9198182f1a | ||
|
|
f819403bd5 | ||
|
|
7867ebb250 | ||
|
|
1accb9e93f | ||
|
|
54d872e19b | ||
|
|
075a98d619 | ||
|
|
336b855d7a | ||
|
|
8ab2988824 | ||
|
|
7ec9b7f2e1 | ||
|
|
f64eec5a93 | ||
|
|
f8119f5336 | ||
|
|
c5eac010be | ||
|
|
f3130f70e6 | ||
|
|
c16788f991 | ||
|
|
69e162e5fe | ||
|
|
d67dd88457 | ||
|
|
b4c52ab7bd | ||
|
|
0657cc1848 | ||
|
|
0ce83512fc | ||
|
|
9882d95775 | ||
|
|
d5c56a4f17 | ||
|
|
c5d7eb7a2d | ||
|
|
bf8dee74eb | ||
|
|
b1f66d1b71 | ||
|
|
9799b892de | ||
|
|
74e8be3fd9 | ||
|
|
909c4614ac | ||
|
|
6cd7038d01 | ||
|
|
e0bd054373 | ||
|
|
f730987da6 | ||
|
|
1e0919ad12 | ||
|
|
88f0c56ad9 | ||
|
|
0b4d1c0237 | ||
|
|
611d6c3e7e | ||
|
|
3b8f3a09aa | ||
|
|
1f5f2c4d83 | ||
|
|
32f41f88bc | ||
|
|
b1ebbb9a1c | ||
|
|
285cd2bda2 | ||
|
|
69d7dbf703 | ||
|
|
48afe4faa5 | ||
|
|
1e47d7ec48 | ||
|
|
ae3673d2ef | ||
|
|
c74105db43 | ||
|
|
e972e29429 | ||
|
|
9e6233d0dd | ||
|
|
2d763b8a1f | ||
|
|
634c271654 | ||
|
|
871c10577e | ||
|
|
27b4cdcc9e | ||
|
|
9486237f1b | ||
|
|
c8ad740ba4 | ||
|
|
938022b1ff | ||
|
|
00af39ecca | ||
|
|
ace2712719 | ||
|
|
2cbf6067a6 | ||
|
|
75e77b96ff | ||
|
|
6d088e03a1 | ||
|
|
415fb43848 | ||
|
|
7f2f100420 | ||
|
|
215982abc2 | ||
|
|
dc017c2dd3 | ||
|
|
87de68c35e | ||
|
|
c6d974975e | ||
|
|
f9c4aeeea4 | ||
|
|
c2fd278da0 | ||
|
|
56914b72ef | ||
|
|
9bac118aec | ||
|
|
5d91b628c9 | ||
|
|
2017515ca9 | ||
|
|
d9c447e194 | ||
|
|
149d5d2a95 | ||
|
|
c8eb7f5526 | ||
|
|
cbe8092d8a | ||
|
|
40d5e48716 | ||
|
|
b1349dd06f | ||
|
|
e4589bbc8a | ||
|
|
2261c03bcd | ||
|
|
5abc31111f | ||
|
|
e53e6ea876 | ||
|
|
7d94efe136 | ||
|
|
7bbc6a0b38 | ||
|
|
d528ff684b | ||
|
|
d7299b5a32 | ||
|
|
7eda6ad299 | ||
|
|
7820771fdd | ||
|
|
9f2891d95c | ||
|
|
1fc8f8856f | ||
|
|
bed4ad589e | ||
|
|
e2cb3a739a | ||
|
|
3af77f0cb4 | ||
|
|
18628dc5d7 | ||
|
|
bd20d946c4 | ||
|
|
094e25b6cd | ||
|
|
8ef84d1cc7 | ||
|
|
27e71fff10 | ||
|
|
5fbfdd6821 | ||
|
|
560f29cff3 | ||
|
|
9c46fa3f35 | ||
|
|
4e32fca05f | ||
|
|
6dfab46268 | ||
|
|
7773716d18 | ||
|
|
5f47b96240 | ||
|
|
f434fdfba7 | ||
|
|
672af37cbd | ||
|
|
f38b052569 | ||
|
|
7a51ae879c | ||
|
|
4a280bcd87 | ||
|
|
cd8ce97563 | ||
|
|
eb49b28ea9 | ||
|
|
7916032a78 | ||
|
|
3517846916 | ||
|
|
da3e884aaa | ||
|
|
520b8398d8 | ||
|
|
784b8984f3 | ||
|
|
a7a7eadf2c | ||
|
|
acec09f567 | ||
|
|
c4b4c896b7 | ||
|
|
2f528029c9 | ||
|
|
08bc8e8a1f | ||
|
|
0a9ab956bd | ||
|
|
5704276981 | ||
|
|
96057638ce | ||
|
|
1b40a7789b | ||
|
|
7d5b506555 | ||
|
|
5a86e384dd | ||
|
|
1e303b3bbc | ||
|
|
e15a36b0a1 | ||
|
|
7ff785fc38 | ||
|
|
a17550648c | ||
|
|
722c2b1e9a | ||
|
|
49765e0e0a | ||
|
|
ea781ef7b2 | ||
|
|
500e83b9b7 | ||
|
|
3674985dd6 | ||
|
|
041be547d6 | ||
|
|
dac867dd6a | ||
|
|
b0df8e7fb5 | ||
|
|
df1e799c51 | ||
|
|
f4b34ba962 | ||
|
|
98d85cf421 | ||
|
|
48f4c4954f | ||
|
|
eea3dfa969 | ||
|
|
2d18aac201 | ||
|
|
1fc25d8d48 | ||
|
|
85ad0c767c | ||
|
|
625999a039 | ||
|
|
ae70b5fcf3 | ||
|
|
d3eca87389 | ||
|
|
d6b1d7300f | ||
|
|
b0115a9613 | ||
|
|
a0bc6e7f83 | ||
|
|
7201042894 | ||
|
|
2edfb21d5d | ||
|
|
26ce3929b4 | ||
|
|
1095179374 | ||
|
|
2b5f990f60 | ||
|
|
e82829d4a2 | ||
|
|
073ce659df | ||
|
|
f4e7b2aa97 | ||
|
|
521e555cf6 | ||
|
|
a81b720151 | ||
|
|
becc667672 | ||
|
|
2678370f2c | ||
|
|
2ea8e0f514 | ||
|
|
efe72d3b26 | ||
|
|
ee1a169121 | ||
|
|
e74c7c1540 | ||
|
|
d547154c91 | ||
|
|
8ff3623e37 | ||
|
|
eb7ac353e2 | ||
|
|
c25ff9e012 | ||
|
|
083e6ef25d | ||
|
|
bd122b35b0 | ||
|
|
4e51970c55 | ||
|
|
f7452e2bad | ||
|
|
7c19d24e3a | ||
|
|
eb22fac5dc | ||
|
|
6700f5ddd1 | ||
|
|
e5aa5235fe | ||
|
|
4247cff2fa | ||
|
|
15663d405e | ||
|
|
44c16918fd | ||
|
|
575c84d431 | ||
|
|
848c1e0348 | ||
|
|
bb4003afa8 | ||
|
|
38796de79a | ||
|
|
5c96f45556 | ||
|
|
4d7e33ec26 | ||
|
|
0b43b5a343 | ||
|
|
6634f73bff | ||
|
|
9068c336f4 | ||
|
|
9fdc7ac38f | ||
|
|
a1210ff6d1 | ||
|
|
542a219623 | ||
|
|
4e1b364015 | ||
|
|
976ebdca2f | ||
|
|
afda8b8f74 | ||
|
|
2cb70e6e3d | ||
|
|
38260aabcc | ||
|
|
b136b357e0 | ||
|
|
e2dc5a3826 | ||
|
|
4cfe2fbf8d | ||
|
|
9a1f0ad532 | ||
|
|
6096a28984 | ||
|
|
c4e69d8cb1 | ||
|
|
170626da67 | ||
|
|
650e691a22 | ||
|
|
9a5cacda90 | ||
|
|
1d35e7aac6 | ||
|
|
4a80df364a | ||
|
|
37ab151aad | ||
|
|
a843cad285 | ||
|
|
3b2146c875 | ||
|
|
59f8d632a3 | ||
|
|
d50929d46b | ||
|
|
0c099e3b79 | ||
|
|
62c377e19c | ||
|
|
6fe2ff4fa7 | ||
|
|
634b24fb25 | ||
|
|
25a9157f0a | ||
|
|
161a4a2cfb | ||
|
|
7b72c42ba6 | ||
|
|
91724e4aef | ||
|
|
7c19500da7 | ||
|
|
9fe119370b | ||
|
|
560d98ba9b | ||
|
|
c71b528148 | ||
|
|
7fb9e99071 | ||
|
|
72517c0f9c | ||
|
|
242b62ed55 | ||
|
|
c3098cc55c | ||
|
|
9a9221d8ef | ||
|
|
92cf662e3a | ||
|
|
e40d9ca186 | ||
|
|
5672bdbab7 | ||
|
|
f11c5600a2 | ||
|
|
99e2ff4927 | ||
|
|
df3f0af5d4 | ||
|
|
96f88e035c | ||
|
|
46447e0287 | ||
|
|
044a78730e | ||
|
|
838dec272c | ||
|
|
5e938f2b83 | ||
|
|
a1b832960c | ||
|
|
ca456a4f53 | ||
|
|
529cbf4ffc | ||
|
|
7f8606eb6c | ||
|
|
7aaeac0760 | ||
|
|
f65007476b | ||
|
|
06298e4d8d | ||
|
|
86ab57ec4f | ||
|
|
4f8b8a746c | ||
|
|
c0babbfc13 | ||
|
|
4abea9a6ca | ||
|
|
1b69e03793 | ||
|
|
05ca6c7392 | ||
|
|
f5035b8e02 | ||
|
|
1a11a7b998 | ||
|
|
4f39ad2a24 | ||
|
|
639caf057d | ||
|
|
50fe89d74b | ||
|
|
746524928c | ||
|
|
3ae6bb47d8 | ||
|
|
1405184765 | ||
|
|
67c9f814e0 | ||
|
|
bed9223610 | ||
|
|
6521411547 | ||
|
|
e9acece3ec | ||
|
|
414cc1ea52 | ||
|
|
42114406af | ||
|
|
903b206e3b | ||
|
|
b2ab339ba6 | ||
|
|
a6eb381ebb | ||
|
|
30845e189f | ||
|
|
b79fa06cfb | ||
|
|
564444d43e | ||
|
|
4a9bda9bed | ||
|
|
49957be1e3 | ||
|
|
adff3faa35 | ||
|
|
7a142936f5 | ||
|
|
3c5355a278 | ||
|
|
f4aa7c0327 | ||
|
|
45b6aaf07a | ||
|
|
c64a616d54 | ||
|
|
dd6af5bfb1 | ||
|
|
48459dee9b | ||
|
|
48ee507489 | ||
|
|
8b51f1c011 | ||
|
|
65d70e90b8 | ||
|
|
fbb8a789f6 | ||
|
|
089d209047 | ||
|
|
bdf574eeb2 | ||
|
|
db0fd30744 | ||
|
|
d028dc4b82 | ||
|
|
c6348c9f78 | ||
|
|
c94bebc983 | ||
|
|
4fd9f39966 | ||
|
|
17ebdf7c86 | ||
|
|
9dd9639dd7 | ||
|
|
f564c07e60 | ||
|
|
6496d374d2 | ||
|
|
cad4f78711 | ||
|
|
4fabef1c97 | ||
|
|
466acdfc46 | ||
|
|
9766b142f1 | ||
|
|
c1ac9a9ad7 | ||
|
|
188d568f3a | ||
|
|
dc5d95c242 | ||
|
|
ade2d29210 | ||
|
|
50757e61b7 | ||
|
|
e1dc5f8f53 | ||
|
|
283c5877fe | ||
|
|
6150f71ba1 | ||
|
|
cafb453545 | ||
|
|
c662976fab | ||
|
|
cdbf44eef0 | ||
|
|
1f729eef60 | ||
|
|
715f6a301d | ||
|
|
a225025cab | ||
|
|
64c61c2de2 | ||
|
|
e9fc66cf77 | ||
|
|
91b2f77e0e | ||
|
|
d222fc60d6 | ||
|
|
7670a74116 | ||
|
|
ac8d34bc81 | ||
|
|
a21b23dda8 | ||
|
|
a847ee3b57 | ||
|
|
d26794ee90 | ||
|
|
d6f38f157d | ||
|
|
acb631d3d6 | ||
|
|
bdc87784a1 | ||
|
|
09e2250a8d | ||
|
|
35f5439e00 | ||
|
|
53d7de2376 | ||
|
|
a481d6aafb | ||
|
|
afae1083aa | ||
|
|
b441b19cc3 | ||
|
|
c0955a6aee | ||
|
|
9ebcf5f257 | ||
|
|
10844fef8c | ||
|
|
f9ea0f9d9b | ||
|
|
a45138c3b4 | ||
|
|
a9e9202e89 | ||
|
|
427f472331 | ||
|
|
77d0f20226 | ||
|
|
71b2235868 | ||
|
|
ea47197930 | ||
|
|
5c7bb2fcd5 | ||
|
|
377e301c61 | ||
|
|
49b7414080 | ||
|
|
029e988835 | ||
|
|
97e353d26b | ||
|
|
a383698be5 | ||
|
|
b5566dbadb | ||
|
|
6b02e39308 | ||
|
|
ad94985754 | ||
|
|
e9a463d871 | ||
|
|
5c485ade2e | ||
|
|
a7790fcbbf | ||
|
|
05620913d5 | ||
|
|
d55af02738 | ||
|
|
d4586eba2e | ||
|
|
f06ffc8176 | ||
|
|
fdd3d94a94 | ||
|
|
eb656dfce3 | ||
|
|
b8411b5159 | ||
|
|
9e45037129 | ||
|
|
eb2456c7d4 | ||
|
|
94465fe93b | ||
|
|
7bd48ca9c7 | ||
|
|
966f3c443a | ||
|
|
05d2bc4c95 | ||
|
|
f386c903c0 | ||
|
|
8a555fb411 | ||
|
|
9555cbe5a9 | ||
|
|
5d40118116 | ||
|
|
2e789736cc | ||
|
|
60544a362b | ||
|
|
7af45a36fc | ||
|
|
6ffc5e6ed0 | ||
|
|
e481fd011a | ||
|
|
8d4a3bb912 | ||
|
|
84fbb611db | ||
|
|
3f3b5c39f0 | ||
|
|
07442876ce | ||
|
|
4534124742 | ||
|
|
eeb43043ad | ||
|
|
dfc8a2e184 | ||
|
|
b2c4abf567 | ||
|
|
24b95cbb89 | ||
|
|
8830314401 | ||
|
|
8d378cfd51 | ||
|
|
3a84ea7cf6 |
37
.github/ISSUE_TEMPLATE/release.md
vendored
Normal file
37
.github/ISSUE_TEMPLATE/release.md
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
name: '[SCT] Release checklist'
|
||||||
|
about: 'Used by the Spec Core Team to create a new release.'
|
||||||
|
title: 'Matrix 1.X'
|
||||||
|
labels: 'release-blocker'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- ------------------------------------------------------------------------ -->
|
||||||
|
<!-- Please asssign the release coordinator (probably yourself) to this issue -->
|
||||||
|
<!-- ------------------------------------------------------------------------ -->
|
||||||
|
|
||||||
|
Date: **Thursday, May 25, 2023** <!-- CHANGE ME -->
|
||||||
|
Previous release: <!-- LINK TO LAST RELEASE'S CHECKLIST -->
|
||||||
|
|
||||||
|
Preflight checklist ([release steps](https://github.com/matrix-org/matrix-spec/blob/main/meta/releasing.md)):
|
||||||
|
|
||||||
|
* [ ] Pin this issue to the repo.
|
||||||
|
* [ ] Ensure the social media account holders are available for the release day.
|
||||||
|
* [ ] Blog post written.
|
||||||
|
* [ ] Check for release blockers that may have been missed.
|
||||||
|
* [ ] Review/fix the changelog.
|
||||||
|
|
||||||
|
Release checklist ([release steps](https://github.com/matrix-org/matrix-spec/blob/main/meta/releasing.md)):
|
||||||
|
* [ ] Branch stuffs.
|
||||||
|
* [ ] Github release artifact.
|
||||||
|
* [ ] Published to spec.matrix.org.
|
||||||
|
* [ ] All links work.
|
||||||
|
* [ ] Publish blog post.
|
||||||
|
* [ ] Announce in #matrix-spec, client developers, HS developers, SCT office, and other rooms as warranted.
|
||||||
|
* [ ] Post to Twitter/Mastodon.
|
||||||
|
* [ ] Close this issue.
|
||||||
|
* [ ] Unpin this issue from the repo.
|
||||||
|
|
||||||
|
Known release blockers:
|
||||||
|
* [ ] <!-- Issue/PR link -->
|
||||||
1
.github/_typos.toml
vendored
1
.github/_typos.toml
vendored
|
|
@ -10,3 +10,4 @@ au1ba7o = "au1ba7o"
|
||||||
[default.extend-words]
|
[default.extend-words]
|
||||||
Appy = "Appy"
|
Appy = "Appy"
|
||||||
fo = "fo"
|
fo = "fo"
|
||||||
|
Iy = "Iy"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
---
|
|
||||||
name: Spec clarification/not a proposal
|
|
||||||
about: A change that's not a spec proposal, such as a clarification to the spec itself.
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Pull Request Checklist
|
### Pull Request Checklist
|
||||||
|
|
||||||
2
.github/workflows/checks.yaml
vendored
2
.github/workflows/checks.yaml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: scripts/check-newsfragments
|
- run: scripts/check-newsfragments
|
||||||
|
|
|
||||||
173
.github/workflows/main.yml
vendored
173
.github/workflows/main.yml
vendored
|
|
@ -1,4 +1,9 @@
|
||||||
name: "Spec"
|
name: "Spec"
|
||||||
|
|
||||||
|
env:
|
||||||
|
HUGO_VERSION: 0.148.1
|
||||||
|
PYTHON_VERSION: 3.13
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|
@ -18,33 +23,72 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: "➕ Setup Node"
|
- name: "➕ Setup Node"
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '20'
|
||||||
- name: "⚙️ npm"
|
|
||||||
working-directory: "./scripts"
|
|
||||||
run: |
|
|
||||||
npm install
|
|
||||||
- name: "🔎 Run validator"
|
- name: "🔎 Run validator"
|
||||||
working-directory: "./scripts"
|
|
||||||
run: |
|
run: |
|
||||||
node validator.js -s "../data/api/application-service"
|
npx @redocly/cli@latest lint data/api/*/*.yaml
|
||||||
node validator.js -s "../data/api/client-server"
|
|
||||||
node validator.js -s "../data/api/push-gateway"
|
|
||||||
|
|
||||||
check-examples:
|
check-event-examples:
|
||||||
name: "🔎 Check Event schema examples"
|
name: "🔎 Check Event schema examples"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: uhoreg/matrix-doc-build
|
|
||||||
steps:
|
steps:
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
- name: "➕ Setup Python"
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
cache: 'pip'
|
||||||
|
cache-dependency-path: scripts/requirements.txt
|
||||||
|
- name: "➕ Install dependencies"
|
||||||
|
run: |
|
||||||
|
pip install -r scripts/requirements.txt
|
||||||
- name: "🔎 Run validator"
|
- name: "🔎 Run validator"
|
||||||
run: |
|
run: |
|
||||||
/env/bin/python scripts/check-event-schema-examples.py
|
python scripts/check-event-schema-examples.py
|
||||||
|
|
||||||
|
check-openapi-examples:
|
||||||
|
name: "🔎 Check OpenAPI definitions examples"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "📥 Source checkout"
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: "➕ Setup Python"
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
cache: 'pip'
|
||||||
|
cache-dependency-path: scripts/requirements.txt
|
||||||
|
- name: "➕ Install dependencies"
|
||||||
|
run: |
|
||||||
|
pip install -r scripts/requirements.txt
|
||||||
|
- name: "🔎 Run validator"
|
||||||
|
run: |
|
||||||
|
python scripts/check-openapi-sources.py
|
||||||
|
|
||||||
|
check-schemas-examples:
|
||||||
|
name: "🔎 Check JSON Schemas inline examples"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "📥 Source checkout"
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: "➕ Setup Python"
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
cache: 'pip'
|
||||||
|
cache-dependency-path: scripts/requirements.txt
|
||||||
|
- name: "➕ Install dependencies"
|
||||||
|
run: |
|
||||||
|
pip install -r scripts/requirements.txt
|
||||||
|
- name: "🔎 Run validator"
|
||||||
|
run: |
|
||||||
|
python scripts/check-json-schemas.py
|
||||||
|
|
||||||
calculate-baseurl:
|
calculate-baseurl:
|
||||||
name: "⚙️ Calculate baseURL for later jobs"
|
name: "⚙️ Calculate baseURL for later jobs"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
@ -60,41 +104,65 @@ jobs:
|
||||||
# the asterisk matching behaviour, not the literal string.
|
# the asterisk matching behaviour, not the literal string.
|
||||||
run: |
|
run: |
|
||||||
if [ "${GITHUB_EVENT_NAME}" == "pull_request" ]; then
|
if [ "${GITHUB_EVENT_NAME}" == "pull_request" ]; then
|
||||||
echo ::set-output name=baseURL::/
|
echo "baseURL=/" >> "$GITHUB_OUTPUT"
|
||||||
elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
echo ::set-output name=baseURL::"/${GITHUB_REF/refs\/tags\//}"
|
echo "baseURL=/${GITHUB_REF/refs\/tags\//}" >> "$GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
echo ::set-output name=baseURL::/unstable
|
echo "baseURL=/unstable" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
build-openapi:
|
build-openapi:
|
||||||
name: "🐍 Build OpenAPI definitions"
|
name: "🐍 Build OpenAPI definitions"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: "python:3.9"
|
|
||||||
needs: [calculate-baseurl]
|
needs: [calculate-baseurl]
|
||||||
steps:
|
steps:
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
- name: "➕ Setup Python"
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
cache: 'pip'
|
||||||
|
cache-dependency-path: scripts/requirements.txt
|
||||||
|
- name: "➕ Install dependencies"
|
||||||
|
run: |
|
||||||
|
pip install -r scripts/requirements.txt
|
||||||
- name: "📦 Asset creation"
|
- name: "📦 Asset creation"
|
||||||
run: |
|
run: |
|
||||||
python3 -m venv env && . env/bin/activate
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
pip install -r scripts/requirements.txt
|
export RELEASE="${GITHUB_REF/refs\/tags\//}"
|
||||||
|
else
|
||||||
|
export RELEASE="unstable"
|
||||||
|
fi
|
||||||
# The output path matches the final deployment path at spec.matrix.org
|
# The output path matches the final deployment path at spec.matrix.org
|
||||||
scripts/dump-swagger.py \
|
scripts/dump-openapi.py \
|
||||||
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
||||||
--api application-service \
|
--api application-service \
|
||||||
|
-r "$RELEASE" \
|
||||||
-o spec/application-service-api/api.json
|
-o spec/application-service-api/api.json
|
||||||
scripts/dump-swagger.py \
|
scripts/dump-openapi.py \
|
||||||
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
||||||
--api client-server \
|
--api client-server \
|
||||||
|
-r "$RELEASE" \
|
||||||
-o spec/client-server-api/api.json
|
-o spec/client-server-api/api.json
|
||||||
scripts/dump-swagger.py \
|
scripts/dump-openapi.py \
|
||||||
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
||||||
--api push-gateway \
|
--api push-gateway \
|
||||||
|
-r "$RELEASE" \
|
||||||
-o spec/push-gateway-api/api.json
|
-o spec/push-gateway-api/api.json
|
||||||
|
scripts/dump-openapi.py \
|
||||||
|
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
||||||
|
--api server-server \
|
||||||
|
-r "$RELEASE" \
|
||||||
|
-o spec/server-server-api/api.json
|
||||||
|
scripts/dump-openapi.py \
|
||||||
|
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
|
||||||
|
--api identity \
|
||||||
|
-r "$RELEASE" \
|
||||||
|
-o spec/identity-service-api/api.json
|
||||||
tar -czf openapi.tar.gz spec
|
tar -czf openapi.tar.gz spec
|
||||||
- name: "📤 Artifact upload"
|
- name: "📤 Artifact upload"
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: openapi-artifact
|
name: openapi-artifact
|
||||||
path: openapi.tar.gz
|
path: openapi.tar.gz
|
||||||
|
|
@ -106,18 +174,20 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: "➕ Setup Python"
|
- name: "➕ Setup Python"
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
- name: "➕ Install towncrier"
|
- name: "➕ Install towncrier"
|
||||||
run: "pip install 'towncrier'"
|
run: "pip install 'towncrier'"
|
||||||
- name: "Generate changelog"
|
- name: "Generate changelog"
|
||||||
run: ./scripts/generate-changelog.sh vUNSTABLE
|
run: ./scripts/generate-changelog.sh vUNSTABLE
|
||||||
- name: "📤 Artifact upload"
|
- name: "📤 Artifact upload"
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: changelog-artifact
|
name: changelog-artifact
|
||||||
path: content/changelog/vUNSTABLE.md
|
path: content/changelog/unstable.md
|
||||||
|
|
||||||
build-spec:
|
build-spec:
|
||||||
name: "📖 Build the spec"
|
name: "📖 Build the spec"
|
||||||
|
|
@ -127,23 +197,23 @@ jobs:
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
steps:
|
steps:
|
||||||
- name: "➕ Setup Node"
|
- name: "➕ Setup Node"
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '20'
|
||||||
- name: "➕ Setup Hugo"
|
- name: "➕ Setup Hugo"
|
||||||
uses: peaceiris/actions-hugo@c03b5dbed22245418539b65eb9a3b1d5fdd9a0a6
|
uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3.0.0
|
||||||
with:
|
with:
|
||||||
hugo-version: '0.93.3'
|
hugo-version: ${{ env.HUGO_VERSION }}
|
||||||
extended: true
|
extended: true
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: "⚙️ npm"
|
- name: "⚙️ npm"
|
||||||
run: |
|
run: |
|
||||||
npm i
|
npm i
|
||||||
npm run get-proposals
|
npm run get-proposals
|
||||||
- name: "📥 Download generated changelog"
|
- name: "📥 Download generated changelog"
|
||||||
if: "needs.generate-changelog.result == 'success'"
|
if: "needs.generate-changelog.result == 'success'"
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: changelog-artifact
|
name: changelog-artifact
|
||||||
path: content/changelog
|
path: content/changelog
|
||||||
|
|
@ -154,7 +224,7 @@ jobs:
|
||||||
# https://spec.matrix.org/latest/client-server-api/api.json
|
# https://spec.matrix.org/latest/client-server-api/api.json
|
||||||
# Works for /unstable/ and /v1.1/ as well.
|
# Works for /unstable/ and /v1.1/ as well.
|
||||||
- name: "📥 Spec definition download"
|
- name: "📥 Spec definition download"
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: openapi-artifact
|
name: openapi-artifact
|
||||||
- name: "📝 Unpack the OpenAPI definitions in the right location"
|
- name: "📝 Unpack the OpenAPI definitions in the right location"
|
||||||
|
|
@ -164,7 +234,7 @@ jobs:
|
||||||
- name: "📦 Tarball creation"
|
- name: "📦 Tarball creation"
|
||||||
run: tar -czf spec.tar.gz spec
|
run: tar -czf spec.tar.gz spec
|
||||||
- name: "📤 Artifact upload"
|
- name: "📤 Artifact upload"
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: spec-artifact
|
name: spec-artifact
|
||||||
path: spec.tar.gz
|
path: spec.tar.gz
|
||||||
|
|
@ -175,10 +245,10 @@ jobs:
|
||||||
needs: [calculate-baseurl, build-spec]
|
needs: [calculate-baseurl, build-spec]
|
||||||
steps:
|
steps:
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: "📥 Fetch built spec"
|
- name: "📥 Fetch built spec"
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: spec-artifact
|
name: spec-artifact
|
||||||
|
|
||||||
|
|
@ -195,7 +265,7 @@ jobs:
|
||||||
- name: "Run htmltest"
|
- name: "Run htmltest"
|
||||||
uses: wjdp/htmltest-action@master
|
uses: wjdp/htmltest-action@master
|
||||||
with:
|
with:
|
||||||
config: .htmltest.yaml
|
config: .htmltest.yml
|
||||||
|
|
||||||
build-historical-spec:
|
build-historical-spec:
|
||||||
name: "📖 Build the historical backup spec"
|
name: "📖 Build the historical backup spec"
|
||||||
|
|
@ -204,28 +274,29 @@ jobs:
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||||
steps:
|
steps:
|
||||||
- name: "➕ Setup Node"
|
- name: "➕ Setup Node"
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '20'
|
||||||
- name: "➕ Setup Hugo"
|
- name: "➕ Setup Hugo"
|
||||||
uses: peaceiris/actions-hugo@c03b5dbed22245418539b65eb9a3b1d5fdd9a0a6
|
uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3.0.0
|
||||||
with:
|
with:
|
||||||
hugo-version: '0.93.3'
|
hugo-version: ${{ env.HUGO_VERSION }}
|
||||||
extended: true
|
extended: true
|
||||||
- name: "📥 Source checkout"
|
- name: "📥 Source checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: "⚙️ npm"
|
- name: "⚙️ npm"
|
||||||
run: |
|
run: |
|
||||||
npm i
|
npm i
|
||||||
npm run get-proposals
|
npm run get-proposals
|
||||||
- name: "⚙️ hugo"
|
- name: "⚙️ hugo"
|
||||||
|
env:
|
||||||
|
HUGO_PARAMS_VERSION_STATUS: "historical"
|
||||||
# Create a baseURL like `/v1.2` out of the `v1.2` tag
|
# Create a baseURL like `/v1.2` out of the `v1.2` tag
|
||||||
run: |
|
run: |
|
||||||
echo -e '[params.version]\nstatus="historical"' > historical.toml
|
hugo --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec"
|
||||||
hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec"
|
|
||||||
|
|
||||||
- name: "📥 Spec definition download"
|
- name: "📥 Spec definition download"
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: openapi-artifact
|
name: openapi-artifact
|
||||||
- name: "📝 Unpack the OpenAPI definitions in the right location"
|
- name: "📝 Unpack the OpenAPI definitions in the right location"
|
||||||
|
|
@ -235,7 +306,7 @@ jobs:
|
||||||
- name: "📦 Tarball creation"
|
- name: "📦 Tarball creation"
|
||||||
run: tar -czf spec-historical.tar.gz spec
|
run: tar -czf spec-historical.tar.gz spec
|
||||||
- name: "📤 Artifact upload"
|
- name: "📤 Artifact upload"
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: spec-historical-artifact
|
name: spec-historical-artifact
|
||||||
path: spec-historical.tar.gz
|
path: spec-historical.tar.gz
|
||||||
|
|
|
||||||
12
.github/workflows/netlify.yaml
vendored
12
.github/workflows/netlify.yaml
vendored
|
|
@ -25,17 +25,20 @@ jobs:
|
||||||
id: readctx
|
id: readctx
|
||||||
# we need to find the PR number that corresponds to the branch, which we do by
|
# we need to find the PR number that corresponds to the branch, which we do by
|
||||||
# searching the GH API
|
# searching the GH API
|
||||||
|
env:
|
||||||
|
OWNER_LOGIN: ${{ github.event.workflow_run.head_repository.owner.login }}
|
||||||
|
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||||
run: |
|
run: |
|
||||||
head_branch='${{github.event.workflow_run.head_repository.owner.login}}:${{github.event.workflow_run.head_branch}}'
|
head_branch="${OWNER_LOGIN}:${HEAD_BRANCH}"
|
||||||
echo "head branch: $head_branch"
|
echo "head branch: $head_branch"
|
||||||
pulls_uri="https://api.github.com/repos/${{ github.repository }}/pulls?head=$(jq -Rr '@uri' <<<$head_branch)"
|
pulls_uri="https://api.github.com/repos/${{ github.repository }}/pulls?head=$(jq -Rr '@uri' <<<$head_branch)"
|
||||||
pr_number=$(curl -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' "$pulls_uri" |
|
pr_number=$(curl -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' "$pulls_uri" |
|
||||||
jq -r '.[] | .number')
|
jq -r '.[] | .number')
|
||||||
echo "PR number: $pr_number"
|
echo "PR number: $pr_number"
|
||||||
echo "::set-output name=prnumber::$pr_number"
|
echo "prnumber=$pr_number" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: '📥 Download artifact'
|
- name: '📥 Download artifact'
|
||||||
uses: dawidd6/action-download-artifact@af92a8455a59214b7b932932f2662fdefbd78126 # v2.15.0
|
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
|
||||||
with:
|
with:
|
||||||
workflow: main.yaml
|
workflow: main.yaml
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
|
|
@ -46,8 +49,7 @@ jobs:
|
||||||
|
|
||||||
- name: "📤 Deploy to Netlify"
|
- name: "📤 Deploy to Netlify"
|
||||||
id: netlify
|
id: netlify
|
||||||
# v1.2.2
|
uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0.0
|
||||||
uses: nwtgck/actions-netlify@f517512ae75beec8896aa7b027c1c72f01816200
|
|
||||||
with:
|
with:
|
||||||
publish-dir: spec
|
publish-dir: spec
|
||||||
deploy-message: "Deploy from GitHub Actions"
|
deploy-message: "Deploy from GitHub Actions"
|
||||||
|
|
|
||||||
43
.github/workflows/release.yaml
vendored
Normal file
43
.github/workflows/release.yaml
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
name: Release packages
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
jobs:
|
||||||
|
# Releases to npm after bumping the package.json version from 0.0.0 to $TAG.0 as the tags only contain MAJOR.MINOR
|
||||||
|
npm:
|
||||||
|
name: Publish to npm
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.release.prerelease == false
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: packages/npm
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- name: 🧮 Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 🔧 Yarn cache
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: "yarn"
|
||||||
|
cache-dependency-path: packages/npm/yarn.lock
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
|
# Ensure npm 11.5.1 or later is installed
|
||||||
|
- name: Update npm
|
||||||
|
run: npm install -g npm@latest
|
||||||
|
|
||||||
|
- name: 🔨 Install dependencies
|
||||||
|
run: "yarn install --frozen-lockfile"
|
||||||
|
|
||||||
|
# We bump the package.json version to git, we just need it for publish to do the right thing
|
||||||
|
- name: 🎖 Bump package.json version
|
||||||
|
run: "yarn version --new-version ${VERSION#v} --no-git-tag-version"
|
||||||
|
env:
|
||||||
|
VERSION: ${{ github.event.release.tag_name }}.0
|
||||||
|
|
||||||
|
- name: 🚀 Publish to npm
|
||||||
|
run: npm publish --provenance --access public --tag latest
|
||||||
6
.github/workflows/spell-check.yaml
vendored
6
.github/workflows/spell-check.yaml
vendored
|
|
@ -11,9 +11,9 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Actions Repository
|
- name: Checkout Actions Repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Check spelling of proposals
|
- name: Check spelling of proposals
|
||||||
uses: crate-ci/typos@9be36f97fdbe645ee9a12449fb13aca856c2516a
|
uses: crate-ci/typos@f2c1f08a7b3c1b96050cb786baaa2a94797bdb7d # v1.20.10
|
||||||
with:
|
with:
|
||||||
config: ${{github.workspace}}/.github/_typos.toml
|
config: ${{github.workspace}}/.github/_typos.toml
|
||||||
|
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -2,7 +2,7 @@ node_modules
|
||||||
/data/msc
|
/data/msc
|
||||||
/env*
|
/env*
|
||||||
/resources
|
/resources
|
||||||
/scripts/swagger
|
/scripts/openapi
|
||||||
/scripts/tmp
|
/scripts/tmp
|
||||||
/hugo-config.toml
|
/hugo-config.toml
|
||||||
/public
|
/public
|
||||||
|
|
@ -14,3 +14,4 @@ _rendered.rst
|
||||||
/spec/
|
/spec/
|
||||||
changelogs/rendered.*
|
changelogs/rendered.*
|
||||||
.hugo_build.lock
|
.hugo_build.lock
|
||||||
|
hugo_stats.json
|
||||||
|
|
|
||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
[submodule "themes/docsy"]
|
|
||||||
path = themes/docsy
|
|
||||||
url = https://github.com/matrix-org/docsy.git
|
|
||||||
branch = master
|
|
||||||
|
|
@ -4,3 +4,4 @@
|
||||||
IgnoreDirectoryMissingTrailingSlash: true
|
IgnoreDirectoryMissingTrailingSlash: true
|
||||||
DirectoryPath: spec
|
DirectoryPath: spec
|
||||||
CheckExternal: false
|
CheckExternal: false
|
||||||
|
IgnoreInternalEmptyHash: true
|
||||||
|
|
@ -12,7 +12,7 @@ The documentation style is described at
|
||||||
https://github.com/matrix-org/matrix-spec/blob/main/meta/documentation_style.rst.
|
https://github.com/matrix-org/matrix-spec/blob/main/meta/documentation_style.rst.
|
||||||
|
|
||||||
Matrix-spec workflows
|
Matrix-spec workflows
|
||||||
--------------------
|
---------------------
|
||||||
|
|
||||||
Specification changes
|
Specification changes
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -72,7 +72,7 @@ ask.
|
||||||
Adding to the changelog
|
Adding to the changelog
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
All API specifications require a changelog entry. Adding to the changelog can only
|
All changes to the contents of this repository require a changelog entry. Adding to the changelog can only
|
||||||
be done after you've opened your pull request, so be sure to do that first.
|
be done after you've opened your pull request, so be sure to do that first.
|
||||||
|
|
||||||
The changelog is managed by `Towncrier <https://github.com/twisted/towncrier>`_ in the
|
The changelog is managed by `Towncrier <https://github.com/twisted/towncrier>`_ in the
|
||||||
|
|
@ -99,6 +99,8 @@ the ``newsfragments`` directory. The ``type`` can be one of the following:
|
||||||
|
|
||||||
* ``deprecation`` - Used when deprecating something.
|
* ``deprecation`` - Used when deprecating something.
|
||||||
|
|
||||||
|
* ``removal`` - Used when removing something that was unused or previously deprecated.
|
||||||
|
|
||||||
All news fragments must have a brief summary explaining the change in the
|
All news fragments must have a brief summary explaining the change in the
|
||||||
contents of the file. The summary must end in a full stop to be in line with
|
contents of the file. The summary must end in a full stop to be in line with
|
||||||
the style guide and formatting must be done using Markdown.
|
the style guide and formatting must be done using Markdown.
|
||||||
|
|
@ -117,7 +119,7 @@ license - in our case, this is Apache Software License v2 (see LICENSE).
|
||||||
In order to have a concrete record that your contribution is intentional
|
In order to have a concrete record that your contribution is intentional
|
||||||
and you agree to license it under the same terms as the project's license, we've adopted the
|
and you agree to license it under the same terms as the project's license, we've adopted the
|
||||||
same lightweight approach used by the `Linux Kernel <https://www.kernel.org/doc/html/latest/process/submitting-patches.html>`_,
|
same lightweight approach used by the `Linux Kernel <https://www.kernel.org/doc/html/latest/process/submitting-patches.html>`_,
|
||||||
`Docker <https://github.com/docker/docker/blob/master/CONTRIBUTING.md`_, and many other
|
`Docker <https://github.com/docker/docker/blob/master/CONTRIBUTING.md>`_, and many other
|
||||||
projects: the `Developer Certificate of Origin <http://developercertificate.org/>`_
|
projects: the `Developer Certificate of Origin <http://developercertificate.org/>`_
|
||||||
(DCO). This is a simple declaration that you wrote
|
(DCO). This is a simple declaration that you wrote
|
||||||
the contribution or otherwise have the right to contribute it to Matrix::
|
the contribution or otherwise have the right to contribute it to Matrix::
|
||||||
|
|
@ -163,7 +165,6 @@ include the line in your commit or pull request comment::
|
||||||
|
|
||||||
Signed-off-by: Your Name <your@email.example.org>
|
Signed-off-by: Your Name <your@email.example.org>
|
||||||
|
|
||||||
...using your real name; unfortunately pseudonyms and anonymous contributions
|
Git allows you to add this signoff automatically when using the ``-s``
|
||||||
can't be accepted. Git makes this trivial - just use the -s flag when you do
|
flag to ``git commit``, which uses the name and email set in your
|
||||||
``git commit``, having first set ``user.name`` and ``user.email`` git configs
|
``user.name`` and ``user.email`` git configs.
|
||||||
(which you should have done anyway :)
|
|
||||||
20
README.md
20
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
# Matrix Specification
|
# Matrix Specification
|
||||||
|
|
||||||
This repository contains the Matrix Specification, rendered at [spec.matrix.org](http://spec.matrix.org/).
|
This repository contains the Matrix Specification. The current release version is rendered at https://spec.matrix.org, while the latest available build of the `main` branch is at https://spec.matrix.org/unstable.
|
||||||
|
|
||||||
Developers looking to use Matrix should join [#matrix-dev:matrix.org](https://matrix.to/#/#matrix-dev:matrix.org)
|
Developers looking to use Matrix should join [#matrix-dev:matrix.org](https://matrix.to/#/#matrix-dev:matrix.org)
|
||||||
on Matrix for help.
|
on Matrix for help.
|
||||||
|
|
@ -22,7 +22,7 @@ The Matrix spec is compiled with [Hugo](https://gohugo.io/) (a static site gener
|
||||||
|
|
||||||
* `/data`: this can contain TOML, YAML, or JSON files. Files kept here are directly available to template code as
|
* `/data`: this can contain TOML, YAML, or JSON files. Files kept here are directly available to template code as
|
||||||
[data objects](https://gohugo.io/templates/data-templates/), so templates don't need to load them from a file and
|
[data objects](https://gohugo.io/templates/data-templates/), so templates don't need to load them from a file and
|
||||||
parse them. This is also where our Swagger/OpenAPI definitions and schemas are.
|
parse them. This is also where our OpenAPI definitions and schemas are.
|
||||||
|
|
||||||
* `/layouts`: this contains [Hugo templates](https://gohugo.io/templates/). Some templates define the overall layout of
|
* `/layouts`: this contains [Hugo templates](https://gohugo.io/templates/). Some templates define the overall layout of
|
||||||
a page: for example, whether it has header, footer, sidebar, and so on.
|
a page: for example, whether it has header, footer, sidebar, and so on.
|
||||||
|
|
@ -52,6 +52,7 @@ Additionally, the following directories may be of interest:
|
||||||
* `/data-definitions`: Bits of structured data consumable by Matrix implementations.
|
* `/data-definitions`: Bits of structured data consumable by Matrix implementations.
|
||||||
* `/meta`: Documentation relating to the spec's processes that are otherwise untracked (release instructions, etc).
|
* `/meta`: Documentation relating to the spec's processes that are otherwise untracked (release instructions, etc).
|
||||||
* `/scripts`: Various scripts for generating the spec and validating its contents.
|
* `/scripts`: Various scripts for generating the spec and validating its contents.
|
||||||
|
* `/packages`: Various packages for shipping spec files like OpenAPI bindings and data definitions.
|
||||||
|
|
||||||
## Authoring changes to the spec
|
## Authoring changes to the spec
|
||||||
|
|
||||||
|
|
@ -60,13 +61,12 @@ place after an MSC has been accepted, not as part of a proposal itself.
|
||||||
|
|
||||||
1. Install the extended version (often the OS default) of Hugo:
|
1. Install the extended version (often the OS default) of Hugo:
|
||||||
<https://gohugo.io/getting-started/installing>. Note that at least Hugo
|
<https://gohugo.io/getting-started/installing>. Note that at least Hugo
|
||||||
v0.93.0 is required.
|
v0.146.0 is required.
|
||||||
|
|
||||||
Alternatively, use the Docker image at
|
Alternatively, use the Docker image at
|
||||||
https://hub.docker.com/r/klakegg/hugo/. (The "extended edition" is required
|
https://hub.docker.com/r/klakegg/hugo/. (The "extended edition" is required
|
||||||
to process the SCSS.)
|
to process the SCSS.)
|
||||||
2. Run `npm i` to install the dependencies and fetch the docsy git submodule.
|
2. Run `npm i` to install the dependencies. Note that this will require NodeJS to be installed.
|
||||||
Note that this will require NodeJS to be installed.
|
|
||||||
3. Run `npm run get-proposals` to seed proposal data. This is merely for populating the content of the "Spec Change Proposals"
|
3. Run `npm run get-proposals` to seed proposal data. This is merely for populating the content of the "Spec Change Proposals"
|
||||||
page and is not required.
|
page and is not required.
|
||||||
4. Run `hugo serve` (or `docker run --rm -it -v $(pwd):/src -p 1313:1313
|
4. Run `hugo serve` (or `docker run --rm -it -v $(pwd):/src -p 1313:1313
|
||||||
|
|
@ -86,13 +86,13 @@ steps for authoring changes to the specification and instead of `hugo serve` run
|
||||||
spec to `/spec`. If you'd like to serve the spec off a path instead of a domain root (eg: `/unstable`), add `--baseURL "/unstable"`
|
spec to `/spec`. If you'd like to serve the spec off a path instead of a domain root (eg: `/unstable`), add `--baseURL "/unstable"`
|
||||||
to the `hugo -d "spec"` command.
|
to the `hugo -d "spec"` command.
|
||||||
|
|
||||||
For building the swagger definitions, create a python3 virtualenv and activate it. Then run `pip install -r ./scripts/requirements.txt`
|
For building the OpenAPI definitions, create a python3 virtualenv and activate it. Then run `pip install -r ./scripts/requirements.txt`
|
||||||
and finally `python ./scripts/dump-swagger.py` to generate it to `./scripts/swagger/api-docs.json`. To make use of the generated file,
|
and finally `python ./scripts/dump-openapi.py` to generate it to `./scripts/openapi/api-docs.json`. To make use of the generated file,
|
||||||
there are a number of options:
|
there are a number of options:
|
||||||
|
|
||||||
* You can open `./scripts/swagger-preview.html` in your browser, and then open the file by clicking on `Local JSON File`.
|
* You can open `./scripts/openapi-preview.html` in your browser, and then open the file by clicking on `Local JSON File`.
|
||||||
* You can run a local HTTP server by running `./scripts/swagger-http-server.py`, and then view the documentation by
|
* You can run a local HTTP server by running `./scripts/openapi-http-server.py`, and then view the documentation by
|
||||||
opening `./scripts/swagger-preview.html` in your browser.
|
opening `./scripts/openapi-preview.html` in your browser.
|
||||||
|
|
||||||
## Issue tracking
|
## Issue tracking
|
||||||
|
|
||||||
|
|
|
||||||
63
assets/css/fonts/Inter.css
Normal file
63
assets/css/fonts/Inter.css
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* cyrillic-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-cyrillic-ext-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||||
|
}
|
||||||
|
/* cyrillic */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-cyrillic-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
|
}
|
||||||
|
/* greek-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-greek-ext-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+1F00-1FFF;
|
||||||
|
}
|
||||||
|
/* greek */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-greek-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||||
|
}
|
||||||
|
/* vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-vietnamese-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||||
|
}
|
||||||
|
/* latin-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-latin-ext-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
/* latin */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: local('Inter'), url(../../fonts/Inter-latin-normal.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
## Inter.css
|
## Inter.css
|
||||||
|
|
||||||
`Inter.css` is a local copy of
|
`Inter.css` is a local copy of
|
||||||
https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i, modified to pull
|
https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,100..900&display=swap, modified to pull
|
||||||
font files (`.woff2`) from local sources. It was created
|
font files (`.woff2`) from local sources. It was created
|
||||||
using `download_google_fonts_css.py`.
|
using `download_google_fonts_css.py`.
|
||||||
|
|
||||||
|
|
@ -15,9 +15,9 @@ load them. Example call:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
python3 download_google_fonts_css.py \
|
python3 download_google_fonts_css.py \
|
||||||
"https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i" \
|
"https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,100..900&display=swap" \
|
||||||
../../fonts \
|
../../../static/fonts \
|
||||||
../../fonts
|
../../fonts
|
||||||
```
|
```
|
||||||
|
|
||||||
Which would pop out a `Inter.css` file that should be `@import url("Inter.css")`d
|
Which would pop out a `Inter.css` file that should be `@import url("Inter.css")`d
|
||||||
|
|
@ -84,7 +84,6 @@ new_css_file_lines = []
|
||||||
font_lang = None
|
font_lang = None
|
||||||
font_family = None
|
font_family = None
|
||||||
font_style = None
|
font_style = None
|
||||||
font_weight = 0
|
|
||||||
for line in original_contents:
|
for line in original_contents:
|
||||||
# Check if this line contains a font URL
|
# Check if this line contains a font URL
|
||||||
match = re.match(r".*url\((.*)\) format.*", line)
|
match = re.match(r".*url\((.*)\) format.*", line)
|
||||||
|
|
@ -96,16 +95,17 @@ for line in original_contents:
|
||||||
resp = requests.get(font_url)
|
resp = requests.get(font_url)
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
# Save the font file
|
# Save the font file
|
||||||
filename = "%s-%s-%s-%d.woff2" % (
|
filename = "%s-%s-%s.woff2" % (
|
||||||
font_family, font_lang, font_style, font_weight
|
font_family, font_lang, font_style
|
||||||
)
|
)
|
||||||
font_filepath = font_output_dir + filename
|
font_filepath = font_output_dir + filename
|
||||||
with open(font_filepath, "wb") as f:
|
with open(font_filepath, "wb") as f:
|
||||||
print("Writing font file:", font_filepath)
|
print("Writing font file:", font_filepath)
|
||||||
f.write(resp.content)
|
f.write(resp.content)
|
||||||
|
|
||||||
# Replace google URL with local URL
|
# Replace google URL with local URL and allow the browser to load the
|
||||||
line = re.sub(r"url\(.+\)", f"url({css_font_path + filename})", line)
|
# local font if it exists.
|
||||||
|
line = re.sub(r"url\(.+?\)", f"local('{font_family}'), url({css_font_path + filename})", line)
|
||||||
else:
|
else:
|
||||||
print("Warning: failed to download font file:", font_url)
|
print("Warning: failed to download font file:", font_url)
|
||||||
|
|
||||||
|
|
@ -121,9 +121,6 @@ for line in original_contents:
|
||||||
font_style_match = re.match(r".*font-style: (.+);$", line)
|
font_style_match = re.match(r".*font-style: (.+);$", line)
|
||||||
if font_style_match:
|
if font_style_match:
|
||||||
font_style = font_style_match.group(1)
|
font_style = font_style_match.group(1)
|
||||||
font_weight_match = re.match(r".*font-weight: (.+);$", line)
|
|
||||||
if font_weight_match:
|
|
||||||
font_weight = int(font_weight_match.group(1))
|
|
||||||
|
|
||||||
# Append the potentially modified line to the new css file
|
# Append the potentially modified line to the new css file
|
||||||
new_css_file_lines.append(line)
|
new_css_file_lines.append(line)
|
||||||
|
|
@ -7,11 +7,17 @@ https://www.diagrams.net/ is a great ([open source](https://github.com/jgraph/dr
|
||||||
tool for these sorts of things - include your `.drawio` file next to your diagram.
|
tool for these sorts of things - include your `.drawio` file next to your diagram.
|
||||||
|
|
||||||
Suggested settings for diagrams.net:
|
Suggested settings for diagrams.net:
|
||||||
* Export as PNG.
|
* Export as WebP.
|
||||||
* 100% size.
|
* 200% size.
|
||||||
* `20` for a border width.
|
* `20` for a border width.
|
||||||
* No transparent background, shadow, or grid.
|
* Light appearance.
|
||||||
* Include a copy of the diagram.
|
* No shadow, or grid.
|
||||||
|
|
||||||
To reference a diagram, use the absolute path when compiled. For example,
|
To reference a diagram, use the `diagram` shortcode. For example:
|
||||||
``
|
|
||||||
|
```
|
||||||
|
{{% diagram name="membership" alt="Diagram presenting the possible membership state transitions" %}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `name` is the file name without extension, and `alt` is a textual
|
||||||
|
replacement for the image, useful for accessibility.
|
||||||
BIN
assets/diagrams/membership.webp
Normal file
BIN
assets/diagrams/membership.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
assets/diagrams/threaded-dag-threads.webp
Normal file
BIN
assets/diagrams/threaded-dag-threads.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
assets/diagrams/threaded-dag.webp
Normal file
BIN
assets/diagrams/threaded-dag.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
assets/icons/favicon.ico
Normal file
BIN
assets/icons/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
12
assets/icons/favicon.svg
Normal file
12
assets/icons/favicon.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<style>
|
||||||
|
path { fill: #000000; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
path { fill: #ffffff; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path d="M 30,2.0000001 V 30 h -1 -2 v 2 h 5 V -3.3333334e-8 L 27,0 v 2 z"/>
|
||||||
|
<path d="M 9.9515939,10.594002 V 12.138 h 0.043994 c 0.3845141,-0.563728 0.8932271,-1.031728 1.4869981,-1.368 0.580003,-0.322998 1.244999,-0.485 1.993002,-0.485 0.72,0 1.376999,0.139993 1.971998,0.42 0.595,0.279004 1.047001,0.771001 1.355002,1.477001 0.338003,-0.500001 0.795999,-0.941 1.376999,-1.323001 0.579999,-0.382998 1.265998,-0.574 2.059998,-0.574 0.602003,0 1.160002,0.074 1.674002,0.220006 0.514,0.148006 0.953998,0.382998 1.321999,0.706998 0.36601,0.322999 0.653001,0.746 0.859,1.268002 0.205001,0.521998 0.307994,1.15 0.307994,1.887001 v 7.632997 h -3.127 v -6.463997 c 0,-0.383002 -0.01512,-0.743002 -0.04399,-1.082003 -0.02079,-0.3072 -0.103219,-0.607113 -0.242003,-0.881998 -0.133153,-0.25081 -0.335962,-0.457777 -0.584001,-0.596002 -0.257008,-0.146003 -0.605998,-0.220006 -1.046997,-0.220006 -0.440002,0 -0.796003,0.085 -1.068,0.253002 -0.272013,0.170003 -0.485001,0.390002 -0.639001,0.662003 -0.159119,0.287282 -0.263585,0.601602 -0.307994,0.926997 -0.05197,0.346923 -0.07801,0.697217 -0.07801,1.048002 v 6.353999 h -3.128005 v -6.398 c 0,-0.338003 -0.0072,-0.673001 -0.02116,-1.004001 -0.01134,-0.313663 -0.07487,-0.623229 -0.187994,-0.915999 -0.107943,-0.276623 -0.300435,-0.512126 -0.550001,-0.673001 -0.25799,-0.168 -0.636,-0.253002 -1.134999,-0.253002 -0.198123,0.0083 -0.394383,0.04195 -0.584002,0.100006 -0.258368,0.07446 -0.498455,0.201827 -0.704999,0.373985 -0.227981,0.183987 -0.421999,0.449 -0.583997,0.794003 -0.161008,0.345978 -0.242003,0.797998 -0.242003,1.356998 v 6.618999 H 6.99942 V 10.590001 Z"/>
|
||||||
|
<path d="M 2,2.0000001 V 30 h 3 v 2 H 0 V 9.2650922e-8 L 5,0 v 2 z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
169
assets/js/toc.js
Normal file
169
assets/js/toc.js
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Only call the given function once every 250 milliseconds to avoid impacting
|
||||||
|
the performance of the browser.
|
||||||
|
Source: https://remysharp.com/2010/07/21/throttling-function-calls
|
||||||
|
*/
|
||||||
|
function throttle(fn) {
|
||||||
|
const threshold = 250;
|
||||||
|
let last = null;
|
||||||
|
let deferTimer = null;
|
||||||
|
|
||||||
|
return function (...args) {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
if (last && now < last + threshold) {
|
||||||
|
// Hold on to it.
|
||||||
|
clearTimeout(deferTimer);
|
||||||
|
deferTimer = setTimeout(() => {
|
||||||
|
last = now;
|
||||||
|
fn.apply(this, args);
|
||||||
|
}, threshold);
|
||||||
|
} else {
|
||||||
|
last = now;
|
||||||
|
fn.apply(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the list of headings that appear in the ToC.
|
||||||
|
This is not as simple as querying all the headings in the content, because
|
||||||
|
some headings are not rendered in the ToC (e.g. in the endpoint definitions).
|
||||||
|
*/
|
||||||
|
function getHeadings() {
|
||||||
|
let headings = [];
|
||||||
|
|
||||||
|
// First get the anchors in the ToC.
|
||||||
|
const toc_anchors = document.querySelectorAll("#toc nav a");
|
||||||
|
|
||||||
|
for (const anchor of toc_anchors) {
|
||||||
|
// Then get the heading from its selector in the anchor's href.
|
||||||
|
const selector = anchor.getAttribute("href");
|
||||||
|
if (!selector) {
|
||||||
|
console.error("Got ToC anchor without href");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const heading = document.querySelector(selector);
|
||||||
|
if (!heading) {
|
||||||
|
console.error("Heading not found for selector:", selector);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
headings.push(heading);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the heading of the text visible at the top of the viewport.
|
||||||
|
This is the first heading above or at the top of the viewport.
|
||||||
|
*/
|
||||||
|
function getCurrentHeading(headings, headerOffset) {
|
||||||
|
const scrollTop = document.documentElement.scrollTop;
|
||||||
|
let prevHeading = null;
|
||||||
|
let currentHeading = null;
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
for (const heading of headings) {
|
||||||
|
// Compute the position compared to the viewport.
|
||||||
|
const rect = heading.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (rect.top >= headerOffset && rect.top <= headerOffset + 30) {
|
||||||
|
// This heading is at the top of the viewport, this is the current heading.
|
||||||
|
currentHeading = heading;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rect.top >= headerOffset) {
|
||||||
|
// This is in or below the viewport, the current heading should be the
|
||||||
|
// previous one.
|
||||||
|
if (prevHeading) {
|
||||||
|
currentHeading = prevHeading;
|
||||||
|
} else {
|
||||||
|
// The first heading does not have a prevHeading.
|
||||||
|
currentHeading = heading;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevHeading = heading;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At the bottom of the page we might not have a heading.
|
||||||
|
if (!currentHeading) {
|
||||||
|
currentHeading = prevHeading;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentHeading;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Select the ToC entry that points to the given ID.
|
||||||
|
Clear any previously highlighted ToC items, select the new one,
|
||||||
|
and adjust the ToC scroll position.
|
||||||
|
*/
|
||||||
|
function selectTocEntry(id) {
|
||||||
|
// Deselect previously selected entries.
|
||||||
|
const activeEntries = document.querySelectorAll("#toc nav a.active");
|
||||||
|
for (const activeEntry of activeEntries) {
|
||||||
|
activeEntry.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the new entry and select it.
|
||||||
|
const newEntry = document.querySelector(`#toc nav a[href="#${id}"]`);
|
||||||
|
if (!newEntry) {
|
||||||
|
console.error("ToC entry not found for ID:", id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newEntry.classList.add('active');
|
||||||
|
|
||||||
|
// Don't scroll the sidebar nav if the main content is not scrolled
|
||||||
|
const nav = document.querySelector("#td-section-nav");
|
||||||
|
const content = document.querySelector("html");
|
||||||
|
if (content.scrollTop !== 0) {
|
||||||
|
nav.scrollTop = newEntry.offsetTop - 100;
|
||||||
|
} else {
|
||||||
|
nav.scrollTop = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Track when the view is scrolled, and use this to update the highlight for the
|
||||||
|
corresponding ToC entry.
|
||||||
|
*/
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Part of the viewport is below the header so we should take it into account.
|
||||||
|
const headerOffset = document.querySelector("body > header > nav").clientHeight;
|
||||||
|
const headings = getHeadings();
|
||||||
|
|
||||||
|
const onScroll = throttle((_e) => {
|
||||||
|
// Update the ToC.
|
||||||
|
let heading = getCurrentHeading(headings, headerOffset);
|
||||||
|
selectTocEntry(heading.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize the state of the ToC.
|
||||||
|
onScroll();
|
||||||
|
|
||||||
|
// Listen to scroll and resizing changes.
|
||||||
|
document.addEventListener('scroll', onScroll, false);
|
||||||
|
document.addEventListener('resize', onScroll, false);
|
||||||
|
});
|
||||||
114
assets/js/versions.template.js
Normal file
114
assets/js/versions.template.js
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Determine the current version as defined in hugo.toml. This will either be
|
||||||
|
// "unstable" or "vX.X" and doesn't depend on the current URL.
|
||||||
|
//
|
||||||
|
// The oddity below is an attempt at producing a readable Hugo template while
|
||||||
|
// avoiding JS syntax errors in your IDE.
|
||||||
|
const currentVersion = `{{ if eq .Site.Params.version.status "unstable" }}
|
||||||
|
{{- /**/ -}}
|
||||||
|
unstable
|
||||||
|
{{- /**/ -}}
|
||||||
|
{{ else }}
|
||||||
|
{{- /**/ -}}
|
||||||
|
{{ printf "v%s.%s" .Site.Params.version.major .Site.Params.version.minor }}
|
||||||
|
{{- /**/ -}}
|
||||||
|
{{ end }}`;
|
||||||
|
|
||||||
|
// Determine the current version segment by regex matching the URL. This will either
|
||||||
|
// be "unstable", "latest", "vX.X" (production) or undefined (local & netlify).
|
||||||
|
const href = window.location.href;
|
||||||
|
const segmentMatches = href.match(/(?<=\/)unstable|latest|v\d+.\d+(?=\/)/);
|
||||||
|
const currentSegment = segmentMatches ? segmentMatches[0] : undefined;
|
||||||
|
|
||||||
|
// Determine the selected menu element. If we were able to obtain the version
|
||||||
|
// segment from the URL (production), use that. Otherwise (local & netlify),
|
||||||
|
// fall back to the version as defined in Hugo.
|
||||||
|
const selected = currentSegment ?? currentVersion;
|
||||||
|
|
||||||
|
function appendVersion(parent, name, segment, url) {
|
||||||
|
// The list item
|
||||||
|
const li = document.createElement("li");
|
||||||
|
if (segment === selected) {
|
||||||
|
li.classList.add("version-picker-selected");
|
||||||
|
}
|
||||||
|
if (segment === "latest") {
|
||||||
|
li.classList.add("version-picker-latest");
|
||||||
|
}
|
||||||
|
parent.appendChild(li);
|
||||||
|
|
||||||
|
// The link
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.classList.add("dropdown-item");
|
||||||
|
a.setAttribute("href", url);
|
||||||
|
li.appendChild(a);
|
||||||
|
|
||||||
|
// Handle clicks manually to preserve the current path / fragment
|
||||||
|
a.addEventListener("click", (ev) => {
|
||||||
|
// If the URL is a relative link (i.e. the historical versions changelog), just
|
||||||
|
// let the browser load it
|
||||||
|
if (url.startsWith("/")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we couldn't determine the current segment, we cannot safely replace
|
||||||
|
// it and have to let the browser load the (root) URL instead
|
||||||
|
if (!currentSegment) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, stop further event handling and replace the segment
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
window.location.href = href.replace(`/${currentSegment}/`, `/${segment}/`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// The link text
|
||||||
|
const text = document.createTextNode(name);
|
||||||
|
a.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're in the unstable version, we're the latest thing and can just load
|
||||||
|
// versions.json from our own resources. Otherwise, we fall back to loading it
|
||||||
|
// from /unstable/versions.json, assuming we are on the spec.matrix.org deployment.
|
||||||
|
const url = currentVersion === "unstable"
|
||||||
|
? '{{ .Site.Home.Permalink }}versions.json'
|
||||||
|
: "/unstable/versions.json";
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(versions => {
|
||||||
|
// Find the surrounding list element
|
||||||
|
const ul = document.querySelector("ul#version-selector");
|
||||||
|
if (!ul) {
|
||||||
|
console.error("Cannot populate version selector: ul element not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a entries for the unstable version and the "latest" shortcut
|
||||||
|
appendVersion(ul, "unstable", "unstable", "https://spec.matrix.org/unstable");
|
||||||
|
const latestName = versions?.length ? `latest (${versions[0].name})` : "latest";
|
||||||
|
appendVersion(ul, latestName, "latest", "https://spec.matrix.org/latest");
|
||||||
|
|
||||||
|
// Add an entry for each proper version
|
||||||
|
for (const version of versions) {
|
||||||
|
appendVersion(ul, version.name, version.name, `https://spec.matrix.org/${version.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For historical versions, simply link to the changelog
|
||||||
|
appendVersion(ul, "historical", "historical", '{{ (site.GetPage "changelog/historical").RelPermalink }}');
|
||||||
|
});
|
||||||
|
|
@ -18,9 +18,6 @@ limitations under the License.
|
||||||
Custom SCSS for the Matrix spec
|
Custom SCSS for the Matrix spec
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "variables_project";
|
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
/* Import the CSS classes for the syntax highlighter.
|
/* Import the CSS classes for the syntax highlighter.
|
||||||
*
|
*
|
||||||
* This is generated with:
|
* This is generated with:
|
||||||
|
|
@ -29,12 +26,6 @@ Custom SCSS for the Matrix spec
|
||||||
*/
|
*/
|
||||||
@import "syntax.scss";
|
@import "syntax.scss";
|
||||||
|
|
||||||
/* Workaround for https://github.com/google/docsy/issues/1116:
|
|
||||||
* fix scroll-anchoring */
|
|
||||||
.td-outer {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overrides for the navbar */
|
/* Overrides for the navbar */
|
||||||
.td-navbar {
|
.td-navbar {
|
||||||
box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25);
|
box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25);
|
||||||
|
|
@ -43,15 +34,36 @@ Custom SCSS for the Matrix spec
|
||||||
.navbar-brand {
|
.navbar-brand {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
|
|
||||||
|
/* Allow the text to wrap if it is wider than the viewport */
|
||||||
|
text-align: center;
|
||||||
|
white-space: normal;
|
||||||
|
|
||||||
.navbar-version {
|
.navbar-version {
|
||||||
color: $secondary;
|
color: $secondary;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make the version dropdown scroll if it's too large */
|
||||||
|
ul#version-selector {
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#version-selector li.version-picker-selected a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#version-selector li.version-picker-latest a {
|
||||||
|
color: $secondary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Styles for the sidebar nav */
|
/* Styles for the sidebar nav */
|
||||||
|
|
@ -68,9 +80,8 @@ Custom SCSS for the Matrix spec
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.td-sidebar-nav__section > li > a.td-sidebar-link {
|
.td-sidebar-nav__section .ul-1 ul {
|
||||||
font-weight: $font-weight-bold;
|
padding-left: 0;
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is to make the width of the items that have sub-items (like room versions)
|
/* This is to make the width of the items that have sub-items (like room versions)
|
||||||
|
|
@ -79,12 +90,20 @@ Custom SCSS for the Matrix spec
|
||||||
padding-right: 0 !important;
|
padding-right: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.indent-1 {
|
.ul-1 > li > a {
|
||||||
padding-left: 1rem !important;
|
padding-left: 1rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.indent-2 {
|
.ul-2 > li > a {
|
||||||
padding-left: 2rem;
|
padding-left: 2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.td-sidebar-link.tree-root {
|
||||||
|
color: $gray-800;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a, a.td-sidebar-link {
|
a, a.td-sidebar-link {
|
||||||
|
|
@ -103,12 +122,11 @@ Custom SCSS for the Matrix spec
|
||||||
|
|
||||||
&.active, &active:hover {
|
&.active, &active:hover {
|
||||||
background-color: $secondary-background;
|
background-color: $secondary-background;
|
||||||
font-weight: $font-weight-normal;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@include media-breakpoint-up(md) {
|
||||||
@supports (position: sticky) {
|
@supports (position: sticky) {
|
||||||
.td-sidebar-nav {
|
.td-sidebar-nav {
|
||||||
/* This overrides calc(100vh - 10rem);, which gives us a blank space at the bottom of the sidebar */
|
/* This overrides calc(100vh - 10rem);, which gives us a blank space at the bottom of the sidebar */
|
||||||
|
|
@ -118,8 +136,11 @@ Custom SCSS for the Matrix spec
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Customise footer */
|
/* Customise footer */
|
||||||
footer {
|
.td-footer {
|
||||||
box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25);
|
box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25);
|
||||||
|
padding-top: 2rem;
|
||||||
|
color: var(--bs-body-color);
|
||||||
|
background-color: var(--bs-body-color-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Auto numbering for headings */
|
/* Auto numbering for headings */
|
||||||
|
|
@ -165,6 +186,13 @@ footer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove some padding before the main content, when the sidebar is disabled */
|
||||||
|
.td-main main {
|
||||||
|
@include media-breakpoint-down(md) {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust the scroll margin for everything in the main content, so that
|
/* Adjust the scroll margin for everything in the main content, so that
|
||||||
* it doesn't disappear behind the header bar */
|
* it doesn't disappear behind the header bar */
|
||||||
.td-content * {
|
.td-content * {
|
||||||
|
|
@ -229,6 +257,69 @@ footer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.endpoints-toc {
|
||||||
|
summary {
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-list {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-list li {
|
||||||
|
margin: 0.2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-list a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
padding: 0.05rem 0.25rem;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $secondary-background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-list .http-api-method {
|
||||||
|
margin-right: 0.35rem;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-path {
|
||||||
|
font-family: $font-family-monospace;
|
||||||
|
color: $secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-deprecated {
|
||||||
|
color: $danger;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
margin-left: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-module {
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-module-title {
|
||||||
|
// font-weight: $font-weight-bold;
|
||||||
|
font-size: 1.20rem;
|
||||||
|
margin-bottom: 0.35rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-description {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Styles for alert boxes */
|
/* Styles for alert boxes */
|
||||||
.alert {
|
.alert {
|
||||||
&.note {
|
&.note {
|
||||||
|
|
@ -260,44 +351,25 @@ footer {
|
||||||
border-left-width: 5px;
|
border-left-width: 5px;
|
||||||
background: $warning-background;
|
background: $warning-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: See the added-in-paragraph.html shortcode for more information on these styles.
|
|
||||||
&.added-in-paragraph {
|
|
||||||
// Remove the padding and margin to remove the box look
|
|
||||||
margin: 0 !important; // !important on both to override table-related rules
|
|
||||||
padding: 0 !important;
|
|
||||||
|
|
||||||
// Make pairs of "added-in" and content inline to each other. We do pairs so authors can
|
|
||||||
// describe two paragraphs with added-in prefixes within a single box, reducing DOM
|
|
||||||
// complexity. Each paragraph is expected to be prefixed with an added-in, however.
|
|
||||||
//
|
|
||||||
// XXX: We assume the added-in and text will be rendered as paragraph elements.
|
|
||||||
> p {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
> p:nth-child(2n) { // "even" rule to target just the content paragraphs
|
|
||||||
// Force a paragraph break after the content (insert a couple <br /> tags)
|
|
||||||
&::after {
|
|
||||||
content: '\A\A';
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Styles for sections that are rendered from data, such as HTTP APIs and event schemas */
|
/* Styles for sections that are rendered from data, such as HTTP APIs and event schemas */
|
||||||
.rendered-data {
|
.td-content .rendered-data {
|
||||||
background-color: $secondary-lightest-background;
|
background-color: $secondary-lightest-background;
|
||||||
padding: 1rem;
|
padding: 0.85rem;
|
||||||
margin: 1rem 0;
|
margin: 0.85rem 0;
|
||||||
|
|
||||||
details {
|
details {
|
||||||
summary {
|
summary {
|
||||||
padding: .5rem 0;
|
h1 {
|
||||||
p {
|
margin: 0;
|
||||||
max-width: 80%;
|
/* Ensure the disclosure control is vertically centred with the header text. */
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
p {
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.deprecated-inline {
|
.deprecated-inline {
|
||||||
|
|
@ -321,13 +393,19 @@ footer {
|
||||||
h2 {
|
h2 {
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
margin: 3rem 0 .5rem 0;
|
margin: 1.5rem 0 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
margin: 1.5rem 0 .75rem 0;
|
margin: 1.5rem 0 1rem 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce top margin of h3 if previous sibling is a h2 */
|
||||||
|
h2 + h3 {
|
||||||
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
|
|
@ -336,27 +414,40 @@ footer {
|
||||||
}
|
}
|
||||||
|
|
||||||
p code, table code {
|
p code, table code {
|
||||||
background-color: inherit;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
/* Docsy makes all tables "responsive tables", which causes Bootstrap 4 to create
|
@media (max-width: 800px) {
|
||||||
* tables with a "display" property of "block".
|
/* Docsy by default applies `overflow-x: auto;` to tables, which
|
||||||
*
|
* results in annoying horizontal scrolling on mobile, so we instead
|
||||||
* However, for "table-layout: fixed" to be effective, an element must have a
|
* switch to a fixed table layout on a narrow browser width.
|
||||||
* "display" property of "table".
|
* (On a wider width the default auto table-layout provides better readability.)
|
||||||
*
|
*
|
||||||
* Thus, we override the "display" property here. This may no longer be necessary once
|
* Docsy makes all tables "responsive tables", which causes Bootstrap 4 to create
|
||||||
* Docsy updates to Bootstrap v5+: https://github.com/google/docsy/issues/470.
|
* tables with a "display" property of "block".
|
||||||
* For more details, see
|
* However, for "table-layout: fixed" to be effective, an element must have a
|
||||||
* https://github.com/matrix-org/matrix-spec/pull/1295/files#r1010759688 */
|
* "display" property of "table".
|
||||||
display: table;
|
*
|
||||||
table-layout: fixed;
|
* Thus, we override the "display" property here. This may no longer be necessary once
|
||||||
width: 100%;
|
* Docsy updates to Bootstrap v5+: https://github.com/google/docsy/issues/470.
|
||||||
|
* For more details, see
|
||||||
|
* https://github.com/matrix-org/matrix-spec/pull/1295/files#r1010759688 */
|
||||||
|
display: table;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
// add some space between two tables when they are right next to each other
|
.col-name, .col-type, .col-status {
|
||||||
& + table {
|
width: 25%;
|
||||||
margin-top: 4rem;
|
}
|
||||||
|
|
||||||
|
.col-description {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-status-description {
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
caption {
|
caption {
|
||||||
|
|
@ -368,9 +459,15 @@ footer {
|
||||||
|
|
||||||
th, td, caption {
|
th, td, caption {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
border-top: 1px $table-border-color solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.object-table, &.response-table {
|
td > p:last-child {
|
||||||
|
// Avoid unnecessary space at the bottom of the cells.
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.object-table, &.response-table, &.content-type-table {
|
||||||
border: 1px $table-border-color solid;
|
border: 1px $table-border-color solid;
|
||||||
|
|
||||||
caption {
|
caption {
|
||||||
|
|
@ -380,14 +477,12 @@ footer {
|
||||||
|
|
||||||
// ... but avoid double border between caption and table
|
// ... but avoid double border between caption and table
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
|
|
||||||
|
background-color: $secondary-lighter-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
caption, tbody tr {
|
tbody tr {
|
||||||
background-color: $table-row-default;
|
--bs-table-striped-bg: #{$secondary-lighter-background};
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) {
|
|
||||||
background-color: $table-row-alternate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,18 +495,41 @@ footer {
|
||||||
width: 15rem;
|
width: 15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-name, .col-type, .col-status {
|
/* Arrange rows vertically when horizontal space is constrained to avoid overflowing */
|
||||||
width: 25%;
|
@include media-breakpoint-down(sm) {
|
||||||
}
|
/* Make cells full width without vertical margin */
|
||||||
|
&.basic-info th, &.basic-info td {
|
||||||
|
width: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.col-description {
|
/* Remove border and padding between header & data cells to make them appear like a single cell */
|
||||||
width: 50%;
|
&.basic-info td {
|
||||||
}
|
padding-top: 0;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
&.basic-info th {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
.col-status-description {
|
/* Remove top border on all but the first header cell to prevent double borders between rows */
|
||||||
width: 75%;
|
&.basic-info tr + tr th {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Have consistent spacing around tables and examples */
|
||||||
|
table, .highlight {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
/* We don't need the margin on the last child of the .rendered-data block */
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
|
|
@ -456,12 +574,25 @@ of .td-content. This applies the same style to any blockquotes that descend from
|
||||||
Make padding symmetrical (this selector is used in the default styles to apply padding-left: 3rem)
|
Make padding symmetrical (this selector is used in the default styles to apply padding-left: 3rem)
|
||||||
*/
|
*/
|
||||||
.pl-md-5, .px-md-5 {
|
.pl-md-5, .px-md-5 {
|
||||||
padding-right: 3rem;
|
@include media-breakpoint-up(md) {
|
||||||
|
padding-right: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the width of math to match normal paragraphs */
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
.katex-display {
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust default styles for info banner */
|
/* Adjust default styles for info banner */
|
||||||
.pageinfo-primary {
|
.pageinfo-primary {
|
||||||
max-width: 80%;
|
@include media-breakpoint-up(lg) {
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
|
margin-top: 0;
|
||||||
|
margin-right: 0;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-left: solid 5px $secondary;
|
border-left: solid 5px $secondary;
|
||||||
|
|
@ -473,4 +604,44 @@ Make padding symmetrical (this selector is used in the default styles to apply p
|
||||||
background-position: left 1rem center;
|
background-position: left 1rem center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
padding-left: 100px;
|
padding-left: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adjust the styling of definition lists. */
|
||||||
|
|
||||||
|
/* Add a little spacing between the term and its definition. */
|
||||||
|
dt {
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _reboot.scss deliberately sets margin-left to 0. Undo this. */
|
||||||
|
dd {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* docsy's _code.scss does only styles <code> elements matching
|
||||||
|
* .td-content { p code, li > code, table code }.
|
||||||
|
* Copy those styles here to apply to code <elements> in definition terms too. */
|
||||||
|
|
||||||
|
.td-content {
|
||||||
|
dt code {
|
||||||
|
color: inherit;
|
||||||
|
padding: 0.2em 0.4em;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 85%;
|
||||||
|
word-break: normal;
|
||||||
|
background-color: rgba($black, 0.05);
|
||||||
|
border-radius: 0.25rem; // was $border-radius, but that var isn't accessible here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style for breadcrumbs */
|
||||||
|
.td-breadcrumbs {
|
||||||
|
padding: .75rem 1rem;
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: .25rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ $dark: #333;
|
||||||
$gray-100: #FBFBFB;
|
$gray-100: #FBFBFB;
|
||||||
|
|
||||||
$secondary-background: #E5F5FB;
|
$secondary-background: #E5F5FB;
|
||||||
$secondary-lighter-background: #F4FaFC;
|
$secondary-lighter-background: #F4FAFC;
|
||||||
$secondary-lightest-background: #FBFDFD;
|
$secondary-lightest-background: #FBFDFD;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,20 +33,24 @@ $warning-background: #FFE0E0;
|
||||||
// colours for definition tables.
|
// colours for definition tables.
|
||||||
// the border colour matches that used for "highlight" divs
|
// the border colour matches that used for "highlight" divs
|
||||||
$table-border-color: rgba(black, .125);
|
$table-border-color: rgba(black, .125);
|
||||||
$table-row-alternate: $secondary-lightest-background;
|
$table-bg: $secondary-lightest-background;
|
||||||
$table-row-default: $secondary-lighter-background;
|
|
||||||
|
|
||||||
/* Configure docsy to use the default system fonts instead of Google Fonts.
|
/* Configure docsy to use the default system fonts instead of Google Fonts.
|
||||||
* See https://www.docsy.dev/docs/adding-content/lookandfeel/#fonts */
|
* See https://www.docsy.dev/docs/adding-content/lookandfeel/#fonts */
|
||||||
$td-enable-google-fonts: false;
|
$td-enable-google-fonts: false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace the default font with Inter - we load it from a local copy, which is downloaded from
|
* The $font-family-sans-serif definition here overrides the default value set by docsy
|
||||||
* Google Fonts manually via a script:
|
* (https://github.com/matrix-org/docsy/blob/66a4e61d2d34edc7196b9df83a7d09cd4af14b47/assets/scss/_variables.scss#L68)
|
||||||
* https://github.com/matrix-org/matrix-spec/tree/main/static/css/fonts
|
*/
|
||||||
*
|
$font-family-sans-serif:
|
||||||
* The $font-family-sans-serif definition here overrides the default value set by docsy:
|
// Add "Inter" to the front, making it the default. The font itself is loaded via stylesheet
|
||||||
* https://github.com/matrix-org/docsy/blob/66a4e61d2d34edc7196b9df83a7d09cd4af14b47/assets/scss/_variables.scss#L68
|
// links in layouts/partials/hooks/head-end.html.
|
||||||
* and adds "Inter" to the front. */
|
"Inter",
|
||||||
@import url("../css/fonts/Inter.css");
|
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
|
||||||
$font-family-sans-serif: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
// Insert fonts suited for mathematical symbols on different platforms before "Arial"
|
||||||
|
"STIX Two Math", "Cambria Math", "Noto Sans Math", "Dejavu Sans",
|
||||||
|
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
|
||||||
|
// Disable smooth scrolling as it makes TOC highlighting jump during the transition.
|
||||||
|
$enable-smooth-scroll: false;
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ anyway.
|
||||||
In this arrangement there is now a room with both users may join but neither has
|
In this arrangement there is now a room with both users may join but neither has
|
||||||
the power to invite any others. Both users now have the confidence that (at
|
the power to invite any others. Both users now have the confidence that (at
|
||||||
least within the messaging system itself) their messages remain private and
|
least within the messaging system itself) their messages remain private and
|
||||||
cannot later be provably leaked to a third party. They can freely set the topic
|
cannot later be provably leaked to a third-party. They can freely set the topic
|
||||||
or name if they choose and add or edit any other state of the room. The update
|
or name if they choose and add or edit any other state of the room. The update
|
||||||
powerlevel of each of these fixed properties should be 1, to lock out the users
|
powerlevel of each of these fixed properties should be 1, to lock out the users
|
||||||
from being able to alter them.
|
from being able to alter them.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
======================
|
======================
|
||||||
Third Party Identities
|
Third-party Identities
|
||||||
======================
|
======================
|
||||||
|
|
||||||
A description of how email addresses, mobile phone numbers and other third
|
A description of how email addresses, mobile phone numbers and other third-party
|
||||||
party identifiers can be used to authenticate and discover users in Matrix.
|
identifiers can be used to authenticate and discover users in Matrix.
|
||||||
|
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
|
|
@ -15,16 +15,16 @@ and phone numbers for contacts in their address book. They want to communicate
|
||||||
with those contacts in Matrix without manually exchanging a Matrix User ID with
|
with those contacts in Matrix without manually exchanging a Matrix User ID with
|
||||||
them.
|
them.
|
||||||
|
|
||||||
Third Party IDs
|
Third-party IDs
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
[[TODO(markjh): Describe the format of a 3PID]]
|
[[TODO(markjh): Describe the format of a 3PID]]
|
||||||
|
|
||||||
|
|
||||||
Third Party ID Associations
|
Third-party ID Associations
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
An Associaton is a binding between a Matrix User ID and a Third Party ID (3PID).
|
An Associaton is a binding between a Matrix User ID and a Third-party ID (3PID).
|
||||||
Each 3PID can be associated with one Matrix User ID at a time.
|
Each 3PID can be associated with one Matrix User ID at a time.
|
||||||
|
|
||||||
[[TODO(markjh): JSON format of the association.]]
|
[[TODO(markjh): JSON format of the association.]]
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<!--
|
|
||||||
This is a header file for the generated changelog.
|
|
||||||
|
|
||||||
Variables:
|
|
||||||
VERSION = Replaced by the version number (eg: v1.2)
|
|
||||||
DATE = Replaced by the date (eg: April 01, 2021)
|
|
||||||
-->
|
|
||||||
|
|
||||||
## VERSION
|
|
||||||
|
|
||||||
<table class="release-info">
|
|
||||||
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/VERSION">https://github.com/matrix-org/matrix-spec/tree/VERSION</a></td>
|
|
||||||
<tr><th>Release date</th><td>DATE</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
|
||||||
1
changelogs/internal/newsfragments/2282.clarification
Normal file
1
changelogs/internal/newsfragments/2282.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Replace the Twitter link in the footer with our BlueSky and Mastodon socials.
|
||||||
|
|
@ -22,5 +22,5 @@ r0.1.0
|
||||||
|
|
||||||
This is the first release of the Application Service specification. It
|
This is the first release of the Application Service specification. It
|
||||||
includes support for application services being able to interact with
|
includes support for application services being able to interact with
|
||||||
homeservers and bridge third party networks, such as IRC, over to Matrix
|
homeservers and bridge third-party networks, such as IRC, over to Matrix
|
||||||
in a standard and accessible way.
|
in a standard and accessible way.
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ Backwards Compatible Changes
|
||||||
- Add a common standard for user, room, and group mentions in messages. (`#1547 <https://github.com/matrix-org/matrix-doc/issues/1547>`_)
|
- Add a common standard for user, room, and group mentions in messages. (`#1547 <https://github.com/matrix-org/matrix-doc/issues/1547>`_)
|
||||||
- Add server ACLs as an option for controlling federation in a room. (`#1550 <https://github.com/matrix-org/matrix-doc/issues/1550>`_)
|
- Add server ACLs as an option for controlling federation in a room. (`#1550 <https://github.com/matrix-org/matrix-doc/issues/1550>`_)
|
||||||
- Add new push rules for encrypted events and ``@room`` notifications. (`#1551 <https://github.com/matrix-org/matrix-doc/issues/1551>`_)
|
- Add new push rules for encrypted events and ``@room`` notifications. (`#1551 <https://github.com/matrix-org/matrix-doc/issues/1551>`_)
|
||||||
- Add third party network room directories, as provided by application services. (`#1554 <https://github.com/matrix-org/matrix-doc/issues/1554>`_)
|
- Add third-party network room directories, as provided by application services. (`#1554 <https://github.com/matrix-org/matrix-doc/issues/1554>`_)
|
||||||
- Document the ``validated_at`` and ``added_at`` fields on ``GET /acount/3pid``. (`#1567 <https://github.com/matrix-org/matrix-doc/issues/1567>`_)
|
- Document the ``validated_at`` and ``added_at`` fields on ``GET /acount/3pid``. (`#1567 <https://github.com/matrix-org/matrix-doc/issues/1567>`_)
|
||||||
- Add an ``inhibit_login`` registration option. (`#1589 <https://github.com/matrix-org/matrix-doc/issues/1589>`_)
|
- Add an ``inhibit_login`` registration option. (`#1589 <https://github.com/matrix-org/matrix-doc/issues/1589>`_)
|
||||||
- Recommend that servers set a Content Security Policy for the content repository. (`#1600 <https://github.com/matrix-org/matrix-doc/issues/1600>`_)
|
- Recommend that servers set a Content Security Policy for the content repository. (`#1600 <https://github.com/matrix-org/matrix-doc/issues/1600>`_)
|
||||||
|
|
@ -554,7 +554,7 @@ Since the draft stage, the following major changes have been made:
|
||||||
- Push notification
|
- Push notification
|
||||||
- History visibility
|
- History visibility
|
||||||
- Search
|
- Search
|
||||||
- Invites based on third party identifiers
|
- Invites based on third-party identifiers
|
||||||
- Room tagging
|
- Room tagging
|
||||||
- Guest access
|
- Guest access
|
||||||
- Client config
|
- Client config
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ r0.1.0
|
||||||
======
|
======
|
||||||
|
|
||||||
This is the first release of the Identity Service API. With this API, clients and
|
This is the first release of the Identity Service API. With this API, clients and
|
||||||
homeservers can store bindings between third party identifiers such as email addresses
|
homeservers can store bindings between third-party identifiers such as email addresses
|
||||||
and phone numbers, associating them with Matrix user IDs. Additionally, identity
|
and phone numbers, associating them with Matrix user IDs. Additionally, identity
|
||||||
servers offer the ability to invite third party users to Matrix rooms by storing
|
servers offer the ability to invite third-party users to Matrix rooms by storing
|
||||||
the invite until the identifier is bound.
|
the invite until the identifier is bound.
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,66 @@
|
||||||
[tool.towncrier]
|
[tool.towncrier]
|
||||||
version = "unused"
|
version = "unused"
|
||||||
filename = "../rendered.md"
|
filename = "rendered.md"
|
||||||
issue_format = "[#{issue}](https://github.com/matrix-org/matrix-spec/issues/{issue})"
|
template = "template.md.jinja"
|
||||||
title_format = "### {name}" # Matches rendered spec, even if awkward
|
|
||||||
underlines = " " # 3 spaces intentionally to hide RST headings
|
|
||||||
|
|
||||||
# Note: The names below have the <strong> tag built-in so the rendered spec *and* the generated
|
|
||||||
# changelog can benefit from sane headings.
|
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "breaking"
|
directory = "breaking"
|
||||||
name = "<strong>Breaking Changes</strong>"
|
name = "Breaking Changes"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "deprecation"
|
directory = "deprecation"
|
||||||
name = "<strong>Deprecations</strong>"
|
name = "Deprecations"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "new"
|
directory = "new"
|
||||||
name = "<strong>New Endpoints</strong>"
|
name = "New Endpoints"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "removal"
|
directory = "removal"
|
||||||
name = "<strong>Removed Endpoints</strong>"
|
name = "Removed Endpoints"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "feature"
|
directory = "feature"
|
||||||
name = "<strong>Backwards Compatible Changes</strong>"
|
name = "Backwards Compatible Changes"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[[tool.towncrier.type]]
|
[[tool.towncrier.type]]
|
||||||
directory = "clarification"
|
directory = "clarification"
|
||||||
name = "<strong>Spec Clarifications</strong>"
|
name = "Spec Clarifications"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Client-Server API"
|
||||||
|
path = "client_server"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Server-Server API"
|
||||||
|
path = "server_server"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Application Service API"
|
||||||
|
path = "application_service"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Identity Service API"
|
||||||
|
path = "identity_service"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Push Gateway API"
|
||||||
|
path = "push_gateway"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Room Versions"
|
||||||
|
path = "room_versions"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Appendices"
|
||||||
|
path = "appendices"
|
||||||
|
|
||||||
|
[[tool.towncrier.section]]
|
||||||
|
name = "Internal Changes/Tooling"
|
||||||
|
path = "internal"
|
||||||
|
|
|
||||||
24
changelogs/template.md.jinja
Normal file
24
changelogs/template.md.jinja
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{% for section_name, section in sections.items() %}
|
||||||
|
{% if section_name %}
|
||||||
|
|
||||||
|
## {{section_name}}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if section %}
|
||||||
|
{% for category, val in definitions.items() if category in section %}
|
||||||
|
**{{ definitions[category]['name'] }}**
|
||||||
|
|
||||||
|
{% for content, issues in section[category].items() %}
|
||||||
|
- {{ content }} (
|
||||||
|
{%- for issue in issues %}
|
||||||
|
[{{issue}}](https://github.com/matrix-org/matrix-spec/issues/{{issue|trim('#')}}){% if not loop.last %}, {% endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
)
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
109
config.toml
109
config.toml
|
|
@ -1,109 +0,0 @@
|
||||||
baseURL = "/"
|
|
||||||
title = "Matrix Specification"
|
|
||||||
|
|
||||||
# Prepends absolute URLs with the baseURL. Useful when hosting on non-root
|
|
||||||
# paths, such as /unstable.
|
|
||||||
canonifyURLs = true
|
|
||||||
|
|
||||||
enableRobotsTXT = true
|
|
||||||
|
|
||||||
# Hugo allows theme composition (and inheritance). The precedence is from left to right.
|
|
||||||
theme = ["docsy"]
|
|
||||||
|
|
||||||
# We disable RSS, because (a) it's useless, (b) Hugo seems to generate broken
|
|
||||||
# links to it when used with a --baseURL (for example, https://spec.matrix.org/v1.4/
|
|
||||||
# contains `<link rel="alternate" type="application/rss+xml" href="/v1.4/v1.4/index.xml">`).
|
|
||||||
disableKinds = ["taxonomy", "taxonomyTerm", "RSS"]
|
|
||||||
|
|
||||||
[languages]
|
|
||||||
[languages.en]
|
|
||||||
title = "Matrix Specification"
|
|
||||||
description = "Home of the Matrix specification for decentralised communication"
|
|
||||||
languageName ="English"
|
|
||||||
# Weight used for sorting.
|
|
||||||
weight = 1
|
|
||||||
|
|
||||||
[markup]
|
|
||||||
[markup.goldmark]
|
|
||||||
[markup.goldmark.renderer]
|
|
||||||
# Enables us to render raw HTML
|
|
||||||
unsafe = true
|
|
||||||
[markup.highlight]
|
|
||||||
# See a complete list of available styles at https://xyproto.github.io/splash/docs/all.html
|
|
||||||
# If the style is changed, remember to regenerate the CSS with:
|
|
||||||
#
|
|
||||||
# hugo gen chromastyles --style=<style> > assets/scss/syntax.scss
|
|
||||||
style = "tango"
|
|
||||||
|
|
||||||
# we enable CSS classes (instead of using inline styles) for compatibility with the CSP.
|
|
||||||
noClasses = false
|
|
||||||
|
|
||||||
# Everything below this are Site Params
|
|
||||||
|
|
||||||
[params]
|
|
||||||
copyright = "The Matrix.org Foundation CIC"
|
|
||||||
privacy_policy = "https://matrix.org/legal/privacy-notice"
|
|
||||||
|
|
||||||
[params.version]
|
|
||||||
# must be one of "unstable", "current", "historical"
|
|
||||||
# this is used to decide whether to show a banner pointing to the current release
|
|
||||||
status = "stable"
|
|
||||||
# A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner.
|
|
||||||
current_version_url = "https://spec.matrix.org/latest"
|
|
||||||
# The following is used when status = "stable", and is displayed in various UI elements on a released version
|
|
||||||
# of the spec. CI will set these values here automatically when a release git tag (i.e `v1.5`) is created.
|
|
||||||
major = "1"
|
|
||||||
minor = "5"
|
|
||||||
release_date = "November 17, 2022"
|
|
||||||
|
|
||||||
# User interface configuration
|
|
||||||
[params.ui]
|
|
||||||
# Set to true to disable the About link in the site footer
|
|
||||||
footer_about_disable = false
|
|
||||||
# Collapse HTTP API and event <details> elements
|
|
||||||
rendered_data_collapsed = false
|
|
||||||
|
|
||||||
[params.links]
|
|
||||||
# End user relevant links. These will show up on left side of footer and in the community page if you have one.
|
|
||||||
# [[params.links.user]]
|
|
||||||
# name = "User mailing list"
|
|
||||||
# url = "https://example.org/mail"
|
|
||||||
# icon = "fa fa-envelope"
|
|
||||||
# desc = "Discussion and help from your fellow users"
|
|
||||||
# Developer relevant links. These will show up on right side of footer and in the community page if you have one.
|
|
||||||
[[params.links.developer]]
|
|
||||||
name = "GitHub"
|
|
||||||
url = "https://github.com/matrix-org"
|
|
||||||
icon = "fab fa-github"
|
|
||||||
desc = "Matrix on GitHub"
|
|
||||||
[[params.links.developer]]
|
|
||||||
name = "GitLab"
|
|
||||||
url = "https://gitlab.matrix.org/matrix-org"
|
|
||||||
icon = "fab fa-gitlab"
|
|
||||||
desc = "Matrix on GitLab"
|
|
||||||
[[params.links.developer]]
|
|
||||||
name = "YouTube"
|
|
||||||
url = "https://www.youtube.com/channel/UCVFkW-chclhuyYRbmmfwt6w"
|
|
||||||
icon = "fab fa-youtube"
|
|
||||||
desc = "Matrix YouTube channel"
|
|
||||||
[[params.links.developer]]
|
|
||||||
name = "Twitter"
|
|
||||||
url = "https://twitter.com/matrixdotorg"
|
|
||||||
icon = "fab fa-twitter"
|
|
||||||
desc = "Matrix on Twitter"
|
|
||||||
|
|
||||||
|
|
||||||
# configuration for the hugo development server
|
|
||||||
[server]
|
|
||||||
|
|
||||||
# set HTTP response headers to match the production site. Compare the Apache config for `spec.matrix.org`.
|
|
||||||
[[server.headers]]
|
|
||||||
for = '/**'
|
|
||||||
[server.headers.values]
|
|
||||||
Content-Security-Policy = "default-src 'self'; style-src 'self'; script-src 'self'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:; media-src 'self'; child-src 'self'; form-action 'self'; object-src 'self'"
|
|
||||||
X-XSS-Protection = "1; mode=block"
|
|
||||||
X-Content-Type-Options = "nosniff"
|
|
||||||
# Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
|
|
||||||
X-Frame-Options = "sameorigin"
|
|
||||||
Access-Control-Allow-Origin = "*"
|
|
||||||
Access-Control-Allow-Methods = "GET"
|
|
||||||
168
config/_default/hugo.toml
Normal file
168
config/_default/hugo.toml
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
# Default settings.
|
||||||
|
|
||||||
|
baseURL = "/"
|
||||||
|
title = "Matrix Specification"
|
||||||
|
|
||||||
|
enableRobotsTXT = true
|
||||||
|
|
||||||
|
# We disable RSS, because (a) it's useless, (b) Hugo seems to generate broken
|
||||||
|
# links to it when used with a --baseURL (for example, https://spec.matrix.org/v1.4/
|
||||||
|
# contains `<link rel="alternate" type="application/rss+xml" href="/v1.4/v1.4/index.xml">`).
|
||||||
|
disableKinds = ["taxonomy", "rss"]
|
||||||
|
|
||||||
|
[languages]
|
||||||
|
[languages.en]
|
||||||
|
title = "Matrix Specification"
|
||||||
|
languageName ="English"
|
||||||
|
# Weight used for sorting.
|
||||||
|
weight = 1
|
||||||
|
[languages.en.params]
|
||||||
|
description = "Home of the Matrix specification for decentralised communication"
|
||||||
|
|
||||||
|
# Entries in the main menu in the header.
|
||||||
|
[menus]
|
||||||
|
[[menus.main]]
|
||||||
|
name = 'Foundation'
|
||||||
|
url = 'https://matrix.org/foundation/about/'
|
||||||
|
weight = 10
|
||||||
|
[[menus.main]]
|
||||||
|
name = 'User Docs'
|
||||||
|
url = 'https://matrix.org/docs/'
|
||||||
|
weight = 20
|
||||||
|
[[menus.main]]
|
||||||
|
name = 'Blog'
|
||||||
|
url = 'https://matrix.org/blog/'
|
||||||
|
weight = 30
|
||||||
|
|
||||||
|
[markup]
|
||||||
|
[markup.tableOfContents]
|
||||||
|
startLevel = 2
|
||||||
|
endLevel = 6
|
||||||
|
ordered = true
|
||||||
|
[markup.goldmark]
|
||||||
|
[markup.goldmark.renderer]
|
||||||
|
# Enables us to render raw HTML
|
||||||
|
unsafe = true
|
||||||
|
[markup.goldmark.extensions]
|
||||||
|
# Tell Goldmark to pass delimited blocks through the `render-passthrough` render hook.
|
||||||
|
# This is used to render the maths in the Olm spec.
|
||||||
|
# See: https://gohugo.io/functions/transform/tomath/#step-1.
|
||||||
|
[markup.goldmark.extensions.passthrough]
|
||||||
|
enable = true
|
||||||
|
[markup.goldmark.extensions.passthrough.delimiters]
|
||||||
|
block = [['\[', '\]']]
|
||||||
|
inline = [['\(', '\)']]
|
||||||
|
[markup.highlight]
|
||||||
|
# See a complete list of available styles at https://xyproto.github.io/splash/docs/all.html
|
||||||
|
# If the style is changed, remember to regenerate the CSS with:
|
||||||
|
#
|
||||||
|
# hugo gen chromastyles --style=<style> > assets/scss/syntax.scss
|
||||||
|
style = "tango"
|
||||||
|
|
||||||
|
# we enable CSS classes (instead of using inline styles) for compatibility with the CSP.
|
||||||
|
noClasses = false
|
||||||
|
|
||||||
|
# Everything below this are Site Params
|
||||||
|
|
||||||
|
[params]
|
||||||
|
copyright = "The Matrix.org Foundation CIC"
|
||||||
|
|
||||||
|
[params.version]
|
||||||
|
# must be one of "unstable", "current", "historical"
|
||||||
|
# this is used to decide whether to show a banner pointing to the current release
|
||||||
|
status = "unstable"
|
||||||
|
# A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner.
|
||||||
|
current_version_url = "https://spec.matrix.org/latest"
|
||||||
|
# The following is used when status = "stable", and is displayed in various UI elements on a released version
|
||||||
|
# of the spec.
|
||||||
|
#major = "1"
|
||||||
|
#minor = "17"
|
||||||
|
|
||||||
|
[[params.versions]]
|
||||||
|
# We must include this parameter to enable docsy's version picker in the navbar. The picker
|
||||||
|
# is populated automatically in navbar-version-selector.html.
|
||||||
|
|
||||||
|
# User interface configuration
|
||||||
|
[params.ui]
|
||||||
|
# Collapse HTTP API and event <details> elements
|
||||||
|
rendered_data_collapsed = false
|
||||||
|
# Hide the search entry in the sidebar
|
||||||
|
sidebar_search_disable = true
|
||||||
|
# Only show the current page's ancestors, siblings and direct descendants in the sidebar menu
|
||||||
|
sidebar_menu_compact = true
|
||||||
|
|
||||||
|
[params.links]
|
||||||
|
# End user relevant links. These will show up on left side of footer and in the community page if you have one.
|
||||||
|
# [[params.links.user]]
|
||||||
|
# name = "User mailing list"
|
||||||
|
# url = "https://example.org/mail"
|
||||||
|
# icon = "fa fa-envelope"
|
||||||
|
# desc = "Discussion and help from your fellow users"
|
||||||
|
# Developer relevant links. These will show up on right side of footer and in the community page if you have one.
|
||||||
|
# [[params.links.developer]]
|
||||||
|
# name = "GitHub"
|
||||||
|
# url = "https://github.com/matrix-org"
|
||||||
|
# icon = "fab fa-github"
|
||||||
|
# desc = "Matrix on GitHub"
|
||||||
|
# Custom links shown in the center of the footer. (Only supported by our fork of docsy's 'footer/central' partial.)
|
||||||
|
[[params.links.bottom]]
|
||||||
|
name = "GitHub"
|
||||||
|
url = "https://github.com/matrix-org"
|
||||||
|
icon = "fab fa-github"
|
||||||
|
desc = "Matrix on GitHub"
|
||||||
|
[[params.links.bottom]]
|
||||||
|
name = "GitLab"
|
||||||
|
url = "https://gitlab.matrix.org/matrix-org"
|
||||||
|
icon = "fab fa-gitlab"
|
||||||
|
desc = "Matrix on GitLab"
|
||||||
|
[[params.links.bottom]]
|
||||||
|
name = "YouTube"
|
||||||
|
url = "https://www.youtube.com/channel/UCVFkW-chclhuyYRbmmfwt6w"
|
||||||
|
icon = "fab fa-youtube"
|
||||||
|
desc = "Matrix YouTube channel"
|
||||||
|
[[params.links.bottom]]
|
||||||
|
name = "Mastodon"
|
||||||
|
url = "https://mastodon.matrix.org/@matrix"
|
||||||
|
icon = "fab fa-mastodon"
|
||||||
|
desc = "Matrix on Mastodon"
|
||||||
|
[[params.links.bottom]]
|
||||||
|
name = "Bluesky"
|
||||||
|
url = "https://bsky.app/profile/matrix.org"
|
||||||
|
icon = "fab fa-bluesky"
|
||||||
|
desc = "Matrix on Bluesky"
|
||||||
|
|
||||||
|
|
||||||
|
# configuration for the hugo development server
|
||||||
|
[server]
|
||||||
|
|
||||||
|
# set HTTP response headers to match the production site. Compare the Apache config for `spec.matrix.org`.
|
||||||
|
[[server.headers]]
|
||||||
|
for = '/**'
|
||||||
|
[server.headers.values]
|
||||||
|
# `style-src 'unsafe-inline'` is needed to correctly render the maths in the Olm spec:
|
||||||
|
# https://github.com/KaTeX/KaTeX/issues/4096
|
||||||
|
Content-Security-Policy = "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:; media-src 'self'; child-src 'self'; form-action 'self'; object-src 'self'"
|
||||||
|
X-XSS-Protection = "1; mode=block"
|
||||||
|
X-Content-Type-Options = "nosniff"
|
||||||
|
# Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
|
||||||
|
X-Frame-Options = "sameorigin"
|
||||||
|
Access-Control-Allow-Origin = "*"
|
||||||
|
Access-Control-Allow-Methods = "GET"
|
||||||
|
|
||||||
|
# hugo module configuration
|
||||||
|
|
||||||
|
[module]
|
||||||
|
[module.hugoVersion]
|
||||||
|
extended = true
|
||||||
|
min = "0.146.0"
|
||||||
|
[[module.imports]]
|
||||||
|
path = "github.com/matrix-org/docsy"
|
||||||
|
disable = false
|
||||||
|
|
||||||
|
# custom output formats
|
||||||
|
|
||||||
|
[outputFormats]
|
||||||
|
[outputFormats.Checklist]
|
||||||
|
mediaType = "text/markdown"
|
||||||
|
isPlainText = true
|
||||||
|
baseName = "checklist"
|
||||||
6
config/production/hugo.toml
Normal file
6
config/production/hugo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Settings only required when the website is built for production.
|
||||||
|
|
||||||
|
# Enable stats to use them to optimize the CSS.
|
||||||
|
[build]
|
||||||
|
[build.buildStats]
|
||||||
|
enable = true
|
||||||
|
|
@ -25,6 +25,7 @@ The specification consists of the following parts:
|
||||||
* [Identity Service API](/identity-service-api)
|
* [Identity Service API](/identity-service-api)
|
||||||
* [Push Gateway API](/push-gateway-api)
|
* [Push Gateway API](/push-gateway-api)
|
||||||
* [Room Versions](/rooms)
|
* [Room Versions](/rooms)
|
||||||
|
* [Olm & Megolm](/olm-megolm)
|
||||||
* [Appendices](/appendices)
|
* [Appendices](/appendices)
|
||||||
|
|
||||||
Additionally, this introduction page contains the key baseline
|
Additionally, this introduction page contains the key baseline
|
||||||
|
|
@ -56,9 +57,6 @@ The principles that Matrix attempts to follow are:
|
||||||
the global Matrix network
|
the global Matrix network
|
||||||
- Fully open standard - publicly documented standard with no IP or
|
- Fully open standard - publicly documented standard with no IP or
|
||||||
patent licensing encumbrances
|
patent licensing encumbrances
|
||||||
- Fully open source reference implementation - liberally-licensed
|
|
||||||
example implementations with no IP or patent licensing
|
|
||||||
encumbrances
|
|
||||||
- Empowering the end-user
|
- Empowering the end-user
|
||||||
- The user should be able to choose the server and clients they
|
- The user should be able to choose the server and clients they
|
||||||
use
|
use
|
||||||
|
|
@ -99,6 +97,20 @@ services - be that for instant messages, VoIP call setups, or any other
|
||||||
objects that need to be reliably and persistently pushed from A to B in
|
objects that need to be reliably and persistently pushed from A to B in
|
||||||
an interoperable and federated manner.
|
an interoperable and federated manner.
|
||||||
|
|
||||||
|
### Requirement levels
|
||||||
|
|
||||||
|
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||||
|
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" across all parts of the
|
||||||
|
specification are to be interpreted as described in
|
||||||
|
[RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).
|
||||||
|
|
||||||
|
Some entire sections of the specification might be optional depending on the
|
||||||
|
circumstances. For example, the
|
||||||
|
[modules of the client-server API](/client-server-api/#modules)
|
||||||
|
apply depending on the use case. The requirement level expressed by the above
|
||||||
|
key words appearing in such a section is only relevant if the section itself is
|
||||||
|
applicable.
|
||||||
|
|
||||||
### Spec Change Proposals
|
### Spec Change Proposals
|
||||||
|
|
||||||
To propose a change to the Matrix Spec, see the explanations at
|
To propose a change to the Matrix Spec, see the explanations at
|
||||||
|
|
@ -140,7 +152,7 @@ request.
|
||||||
|
|
||||||
How data flows between clients:
|
How data flows between clients:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{ Matrix client A } { Matrix client B }
|
{ Matrix client A } { Matrix client B }
|
||||||
^ | ^ |
|
^ | ^ |
|
||||||
| events | Client-Server API | events |
|
| events | Client-Server API | events |
|
||||||
|
|
@ -357,8 +369,8 @@ servers that are in the room that can be used to join via.
|
||||||
|
|
||||||
HTTP GET
|
HTTP GET
|
||||||
#matrix:example.org !aaabaa:matrix.org
|
#matrix:example.org !aaabaa:matrix.org
|
||||||
| ^
|
| ^
|
||||||
| |
|
| |
|
||||||
_______V____________________|____
|
_______V____________________|____
|
||||||
| example.org |
|
| example.org |
|
||||||
| Mappings: |
|
| Mappings: |
|
||||||
|
|
@ -372,7 +384,7 @@ servers that are in the room that can be used to join via.
|
||||||
Users in Matrix are identified via their Matrix user ID. However,
|
Users in Matrix are identified via their Matrix user ID. However,
|
||||||
existing 3rd party ID namespaces can also be used in order to identify
|
existing 3rd party ID namespaces can also be used in order to identify
|
||||||
Matrix users. A Matrix "Identity" describes both the user ID and any
|
Matrix users. A Matrix "Identity" describes both the user ID and any
|
||||||
other existing IDs from third party namespaces *linked* to their
|
other existing IDs from third-party namespaces *linked* to their
|
||||||
account. Matrix users can *link* third-party IDs (3PIDs) such as email
|
account. Matrix users can *link* third-party IDs (3PIDs) such as email
|
||||||
addresses, social network accounts and phone numbers to their user ID.
|
addresses, social network accounts and phone numbers to their user ID.
|
||||||
Linking 3PIDs creates a mapping from a 3PID to a user ID. This mapping
|
Linking 3PIDs creates a mapping from a 3PID to a user ID. This mapping
|
||||||
|
|
@ -419,9 +431,16 @@ into the `m.` namespace.
|
||||||
|
|
||||||
### Timestamps
|
### Timestamps
|
||||||
|
|
||||||
Unless otherwise stated, timestamps are measured as milliseconds since
|
Unless otherwise stated, timestamps are the number of milliseconds
|
||||||
the Unix epoch. Throughout the specification this may be referred to as
|
elapsed since the unix epoch (1970-01-01 00:00:00 UTC), but not counting
|
||||||
POSIX, Unix, or just "time in milliseconds".
|
leap seconds, so that each day is precisely 86,400,000 milliseconds.
|
||||||
|
|
||||||
|
This means that timestamps can repeat during leap seconds. Most
|
||||||
|
programming languages provide timestamps in that format natively, e.g.
|
||||||
|
[ECMAScript](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-time-range).
|
||||||
|
Throughout the specification this may be referred to as POSIX,
|
||||||
|
[Unix](https://en.wikipedia.org/wiki/Unix_time), or just "time in
|
||||||
|
milliseconds".
|
||||||
|
|
||||||
## Specification Versions
|
## Specification Versions
|
||||||
|
|
||||||
|
|
@ -486,18 +505,23 @@ For historical reference, the APIs were versioned as `rX.Y.Z` where `X`
|
||||||
roughly represents a breaking change, `Y` a backwards-compatible change, and
|
roughly represents a breaking change, `Y` a backwards-compatible change, and
|
||||||
`Z` a patch or insignificant alteration to the API.
|
`Z` a patch or insignificant alteration to the API.
|
||||||
|
|
||||||
`v1.0` of Matrix was released on June 10th, 2019 with the following API
|
The current global versioning system was introduced with `v1.1`.
|
||||||
versions:
|
[Matrix 1.0](https://matrix.org/blog/2019/06/11/introducing-matrix-1-0-and-the-matrix-org-foundation/)
|
||||||
|
did not correspond directly to a specification version; instead, it was based on
|
||||||
|
the following versions for the individual APIs:
|
||||||
|
|
||||||
| API/Specification | Version |
|
| API/Specification | Version |
|
||||||
|-------------------------|---------|
|
|--------------------------|---------------|
|
||||||
| Client-Server API | r0.5.0 |
|
| Client-Server API | r0.5.0 |
|
||||||
| Server-Server API | r0.1.2 |
|
| Server-Server API | r0.1.2 |
|
||||||
| Application Service API | r0.1.1 |
|
| Application Service API | r0.1.1 |
|
||||||
| Identity Service API | r0.1.1 |
|
| Identity Service API | r0.2.0 |
|
||||||
| Push Gateway API | r0.1.0 |
|
| Push Gateway API | r0.1.0 |
|
||||||
| Room Version | v5 |
|
| Room Versions | 1, 2, 3, 4, 5 |
|
||||||
|
|
||||||
|
`v1.0` should **not** be returned by servers in the
|
||||||
|
[`GET /_matrix/client/versions`](/client-server-api/#get_matrixclientversions)
|
||||||
|
response.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,15 @@ object.
|
||||||
|
|
||||||
### Canonical JSON
|
### Canonical JSON
|
||||||
|
|
||||||
We define the canonical JSON encoding for a value to be the shortest
|
To ensure that all implementations use the same JSON encoding we define
|
||||||
|
"Canonical JSON". This should not be confused with other uses of
|
||||||
|
"Canonical JSON" outside of the specification.
|
||||||
|
|
||||||
|
We define this encoding for a value to be the shortest
|
||||||
UTF-8 JSON encoding with dictionary keys lexicographically sorted by
|
UTF-8 JSON encoding with dictionary keys lexicographically sorted by
|
||||||
Unicode codepoint. Numbers in the JSON must be integers in the range
|
Unicode codepoint. Numbers in the JSON must be integers in the range
|
||||||
`[-(2**53)+1, (2**53)-1]`.
|
`[-(2**53)+1, (2**53)-1]`, represented without exponents or decimal
|
||||||
|
places, and negative zero `-0` MUST NOT appear.
|
||||||
|
|
||||||
We pick UTF-8 as the encoding as it should be available to all platforms
|
We pick UTF-8 as the encoding as it should be available to all platforms
|
||||||
and JSON received from the network is likely to be already encoded using
|
and JSON received from the network is likely to be already encoded using
|
||||||
|
|
@ -131,12 +136,12 @@ removing insignificant whitespace, fractions, exponents and redundant
|
||||||
character escapes.
|
character escapes.
|
||||||
|
|
||||||
value = false / null / true / object / array / number / string
|
value = false / null / true / object / array / number / string
|
||||||
false = %x66.61.6c.73.65
|
false = %x66.61.6C.73.65
|
||||||
null = %x6e.75.6c.6c
|
null = %x6E.75.6C.6C
|
||||||
true = %x74.72.75.65
|
true = %x74.72.75.65
|
||||||
object = %x7B [ member *( %x2C member ) ] %7D
|
object = %x7B [ member *( %x2C member ) ] %x7D
|
||||||
member = string %x3A value
|
member = string %x3A value
|
||||||
array = %x5B [ value *( %x2C value ) ] %5B
|
array = %x5B [ value *( %x2C value ) ] %x5D
|
||||||
number = [ %x2D ] int
|
number = [ %x2D ] int
|
||||||
int = %x30 / ( %x31-39 *digit )
|
int = %x30 / ( %x31-39 *digit )
|
||||||
digit = %x30-39
|
digit = %x30-39
|
||||||
|
|
@ -300,6 +305,21 @@ The following canonical JSON should be produced:
|
||||||
{"a":null}
|
{"a":null}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Given the following JSON object:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"a": -0,
|
||||||
|
"b": 1e10
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The following canonical JSON should be produced:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"a":0,"b":10000000000}
|
||||||
|
```
|
||||||
|
|
||||||
### Signing Details
|
### Signing Details
|
||||||
|
|
||||||
JSON is signed by encoding the JSON object without `signatures` or keys
|
JSON is signed by encoding the JSON object without `signatures` or keys
|
||||||
|
|
@ -502,10 +522,9 @@ The sigil characters are as follows:
|
||||||
- `@`: User ID
|
- `@`: User ID
|
||||||
- `!`: Room ID
|
- `!`: Room ID
|
||||||
- `$`: Event ID
|
- `$`: Event ID
|
||||||
- `+`: Group ID
|
|
||||||
- `#`: Room alias
|
- `#`: Room alias
|
||||||
|
|
||||||
User IDs, group IDs, room IDs, room aliases, and sometimes event IDs
|
User IDs, room IDs, room aliases, and sometimes event IDs
|
||||||
take the form:
|
take the form:
|
||||||
|
|
||||||
&localpart:domain
|
&localpart:domain
|
||||||
|
|
@ -517,10 +536,12 @@ allocated by that homeserver.
|
||||||
The precise grammar defining the allowable format of an identifier
|
The precise grammar defining the allowable format of an identifier
|
||||||
depends on the type of identifier. For example, event IDs can sometimes
|
depends on the type of identifier. For example, event IDs can sometimes
|
||||||
be represented with a `domain` component under some conditions - see the
|
be represented with a `domain` component under some conditions - see the
|
||||||
[Event IDs](#room-ids-and-event-ids) section below for more information.
|
[Event IDs](#event-ids) section below for more information.
|
||||||
|
|
||||||
#### User Identifiers
|
#### User Identifiers
|
||||||
|
|
||||||
|
{{% changed-in v="1.8" %}}
|
||||||
|
|
||||||
Users within Matrix are uniquely identified by their Matrix user ID. The
|
Users within Matrix are uniquely identified by their Matrix user ID. The
|
||||||
user ID is namespaced to the homeserver which allocated the account and
|
user ID is namespaced to the homeserver which allocated the account and
|
||||||
has the form:
|
has the form:
|
||||||
|
|
@ -529,13 +550,13 @@ has the form:
|
||||||
|
|
||||||
The `localpart` of a user ID is an opaque identifier for that user. It
|
The `localpart` of a user ID is an opaque identifier for that user. It
|
||||||
MUST NOT be empty, and MUST contain only the characters `a-z`, `0-9`,
|
MUST NOT be empty, and MUST contain only the characters `a-z`, `0-9`,
|
||||||
`.`, `_`, `=`, `-`, and `/`.
|
`.`, `_`, `=`, `-`, `/`, and `+`.
|
||||||
|
|
||||||
The `domain` of a user ID is the [server name](#server-name) of the
|
The `domain` of a user ID is the [server name](#server-name) of the
|
||||||
homeserver which allocated the account.
|
homeserver which allocated the account.
|
||||||
|
|
||||||
The length of a user ID, including the `@` sigil and the domain, MUST
|
The length of a user ID, including the `@` sigil and the domain, MUST
|
||||||
NOT exceed 255 characters.
|
NOT exceed 255 bytes.
|
||||||
|
|
||||||
The complete grammar for a legal user ID is:
|
The complete grammar for a legal user ID is:
|
||||||
|
|
||||||
|
|
@ -543,7 +564,7 @@ The complete grammar for a legal user ID is:
|
||||||
user_id_localpart = 1*user_id_char
|
user_id_localpart = 1*user_id_char
|
||||||
user_id_char = DIGIT
|
user_id_char = DIGIT
|
||||||
/ %x61-7A ; a-z
|
/ %x61-7A ; a-z
|
||||||
/ "-" / "." / "=" / "_" / "/"
|
/ "-" / "." / "=" / "_" / "/" / "+"
|
||||||
|
|
||||||
{{% boxes/rationale %}}
|
{{% boxes/rationale %}}
|
||||||
A number of factors were considered when defining the allowable
|
A number of factors were considered when defining the allowable
|
||||||
|
|
@ -590,10 +611,18 @@ characters permitted in user ID localparts. There are currently active
|
||||||
users whose user IDs do not conform to the permitted character set, and
|
users whose user IDs do not conform to the permitted character set, and
|
||||||
a number of rooms whose history includes events with a `sender` which
|
a number of rooms whose history includes events with a `sender` which
|
||||||
does not conform. In order to handle these rooms successfully, clients
|
does not conform. In order to handle these rooms successfully, clients
|
||||||
and servers MUST accept user IDs with localparts from the expanded
|
and servers MUST accept user IDs with localparts consisting of any legal
|
||||||
character set:
|
non-surrogate Unicode code points except for `:` and `NUL` (U+0000), including other control
|
||||||
|
characters and the empty string.
|
||||||
|
|
||||||
extended_user_id_char = %x21-39 / %x3B-7E ; all ASCII printing chars except :
|
User IDs with localparts containing characters outside the range U+0021 to U+007E, or with
|
||||||
|
an empty localpart, are considered non-compliant. For current room versions, servers must
|
||||||
|
still accept events using such user IDs over federation; however they SHOULD NOT forward
|
||||||
|
such user IDs to clients when referenced outside the context of an event. For example,
|
||||||
|
device list updates from non-compliant user IDs would be dropped by the receiving server.
|
||||||
|
|
||||||
|
A future room version may prevent users using a historical character set
|
||||||
|
from participating. Use of the historical character set is *deprecated*.
|
||||||
|
|
||||||
##### Mapping from other character sets
|
##### Mapping from other character sets
|
||||||
|
|
||||||
|
|
@ -626,24 +655,50 @@ allowing representation of *any* character (unlike punycode, which
|
||||||
provides no way to encode ASCII punctuation).
|
provides no way to encode ASCII punctuation).
|
||||||
{{% /boxes/rationale %}}
|
{{% /boxes/rationale %}}
|
||||||
|
|
||||||
#### Room IDs and Event IDs
|
#### Room IDs
|
||||||
|
|
||||||
A room has exactly one room ID. A room ID has the format:
|
{{% changed-in v="1.16" %}} Room IDs can now appear without a domain depending on
|
||||||
|
the room version.
|
||||||
|
|
||||||
|
A room has exactly one room ID. Room IDs take the form:
|
||||||
|
|
||||||
|
!opaque_id
|
||||||
|
|
||||||
|
However, the precise format depends upon the [room version specification](/rooms):
|
||||||
|
some room versions included a `domain` component, whereas more recent room versions
|
||||||
|
omit the domain and use a base64-encoded hash instead.
|
||||||
|
|
||||||
|
Room IDs are case-sensitive and not meant to be human-readable. They are intended
|
||||||
|
to be used as fully opaque strings by clients, even when a `domain` component is
|
||||||
|
present.
|
||||||
|
|
||||||
|
If the room version requires a `domain` component, room IDs take the following
|
||||||
|
form:
|
||||||
|
|
||||||
!opaque_id:domain
|
!opaque_id:domain
|
||||||
|
|
||||||
An event has exactly one event ID. The format of an event ID depends
|
In such a form, the `opaque_id` is a localpart. The localpart MUST only contain
|
||||||
upon the [room version specification](/rooms).
|
valid non-surrogate Unicode code points, including control characters, except `:`
|
||||||
|
and `NUL` (U+0000). The localpart SHOULD only consist of alphanumeric characters
|
||||||
|
(`A-Z`, `a-z`, `0-9`) when generating them. The `domain` is the [server name](#server-name)
|
||||||
|
of the homeserver which created the room - it is only used to reduce namespace
|
||||||
|
collisions. There is no implication that the room in question is still available
|
||||||
|
at the corresponding homeserver. Combined, the localpart, domain, and `!` sigil
|
||||||
|
MUST NOT exceed 255 bytes.
|
||||||
|
|
||||||
The `domain` of a room ID is the [server name](#server-name) of the
|
When a room version requires the `domain`-less format, room IDs are simply the
|
||||||
homeserver which created the room/event. The domain is used only for
|
[event ID](#event-ids) of the `m.room.create` event using `!` as the sigil instead
|
||||||
namespacing to avoid the risk of clashes of identifiers between
|
of `$`. The grammar is otherwise inherited verbatim.
|
||||||
different homeservers. There is no implication that the room or event in
|
|
||||||
question is still available at the corresponding homeserver.
|
|
||||||
|
|
||||||
Event IDs and Room IDs are case-sensitive. They are not meant to be
|
{{% boxes/note %}}
|
||||||
human-readable. They are intended to be treated as fully opaque strings
|
Applications which previously relied upon the `domain` in a room ID can instead
|
||||||
by clients.
|
parse the [user IDs](#user-identifiers) found in the `m.room.create` event's `sender`.
|
||||||
|
|
||||||
|
Though the `m.room.create` event's `additional_creators` (in `content`) may be
|
||||||
|
used when present, applications should take care when parsing or interpreting the
|
||||||
|
list. The user IDs in `additional_creators` will have correct grammar, but may
|
||||||
|
not be real users or may not belong to actual Matrix homeservers.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
#### Room Aliases
|
#### Room Aliases
|
||||||
|
|
||||||
|
|
@ -655,10 +710,29 @@ The `domain` of a room alias is the [server name](#server-name) of the
|
||||||
homeserver which created the alias. Other servers may contact this
|
homeserver which created the alias. Other servers may contact this
|
||||||
homeserver to look up the alias.
|
homeserver to look up the alias.
|
||||||
|
|
||||||
Room aliases MUST NOT exceed 255 bytes (including the `#` sigil and the
|
The localpart of a room alias may contain any valid non-surrogate Unicode codepoints
|
||||||
domain).
|
except `:` and `NUL`.
|
||||||
|
|
||||||
#### URIs
|
The length of a room alias, including the `#` sigil and the domain, MUST
|
||||||
|
NOT exceed 255 bytes.
|
||||||
|
|
||||||
|
#### Event IDs
|
||||||
|
|
||||||
|
An event has exactly one event ID. Event IDs take the form:
|
||||||
|
|
||||||
|
$opaque_id
|
||||||
|
|
||||||
|
However, the precise format depends upon the [room version
|
||||||
|
specification](/rooms): early room versions included a `domain` component,
|
||||||
|
whereas more recent versions omit the domain and use a base64-encoded hash instead.
|
||||||
|
|
||||||
|
In addition to the requirements of the room version, the length of an event ID,
|
||||||
|
including the `$` sigil and the domain where present, MUST NOT exceed 255 bytes.
|
||||||
|
|
||||||
|
Event IDs are case-sensitive. They are not meant to be human-readable. They are
|
||||||
|
intended to be treated as fully opaque strings by clients.
|
||||||
|
|
||||||
|
### URIs
|
||||||
|
|
||||||
There are two major kinds of referring to a resource in Matrix: matrix.to
|
There are two major kinds of referring to a resource in Matrix: matrix.to
|
||||||
and `matrix:` URI. The specification currently defines both as active/valid
|
and `matrix:` URI. The specification currently defines both as active/valid
|
||||||
|
|
@ -669,19 +743,19 @@ be used to reference particular objects in a given context, such as mentioning
|
||||||
a user in a message or linking someone to a particular point in the room's
|
a user in a message or linking someone to a particular point in the room's
|
||||||
history (a permalink).
|
history (a permalink).
|
||||||
|
|
||||||
##### Matrix URI scheme
|
#### Matrix URI scheme
|
||||||
|
|
||||||
{{% added-in v="1.2" %}}
|
{{% added-in v="1.2" %}}
|
||||||
|
|
||||||
The Matrix URI scheme is defined as follows (`[]` enclose optional parts, `{}`
|
The Matrix URI scheme is defined as follows (`[]` enclose optional parts, `{}`
|
||||||
enclose variables):
|
enclose variables):
|
||||||
```
|
```nohighlight
|
||||||
matrix:[//{authority}/]{type}/{id without sigil}[/{type}/{id without sigil}...][?{query}][#{fragment}]
|
matrix:[//{authority}/]{type}/{id without sigil}[/{type}/{id without sigil}...][?{query}][#{fragment}]
|
||||||
```
|
```
|
||||||
|
|
||||||
As a schema, this can be represented as:
|
As a schema, this can be represented as:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
MatrixURI = "matrix:" hier-part [ "?" query ] [ "#" fragment ]
|
MatrixURI = "matrix:" hier-part [ "?" query ] [ "#" fragment ]
|
||||||
hier-part = [ "//" authority "/" ] path
|
hier-part = [ "//" authority "/" ] path
|
||||||
path = entity-descriptor ["/" entity-descriptor]
|
path = entity-descriptor ["/" entity-descriptor]
|
||||||
|
|
@ -713,7 +787,7 @@ Specifically, the following mappings are used:
|
||||||
* `r` for room aliases.
|
* `r` for room aliases.
|
||||||
* `u` for users.
|
* `u` for users.
|
||||||
* `roomid` for room IDs (note the distinction from room aliases).
|
* `roomid` for room IDs (note the distinction from room aliases).
|
||||||
* `e` for events, when after a room reference (`r` or `roomid`).
|
* `e` for events, when after a room ID (`roomid`). Use of `e` after a room alias (`r`) is deprecated.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
During development of this URI format, types of `user`, `room`, and `event`
|
During development of this URI format, types of `user`, `room`, and `event`
|
||||||
|
|
@ -723,6 +797,13 @@ wish to consider handling them as `u`, `r`, and `e` respectively.
|
||||||
`roomid` was otherwise unchanged.
|
`roomid` was otherwise unchanged.
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% changed-in v="1.11" %}}
|
||||||
|
Referencing event IDs within a room identified by room alias (`r`) rather than room ID
|
||||||
|
(`roomid`) is now deprecated. We are not aware of these ever having been used in
|
||||||
|
practice, and are nonsensical given room aliases are mutable.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
The `id without sigil` is simply the identifier for the entity without the defined
|
The `id without sigil` is simply the identifier for the entity without the defined
|
||||||
sigil. For example, `!room:example.org` becomes `room:example.org` (`!` is the sigil
|
sigil. For example, `!room:example.org` becomes `room:example.org` (`!` is the sigil
|
||||||
for room IDs). The sigils are described under the
|
for room IDs). The sigils are described under the
|
||||||
|
|
@ -767,29 +848,28 @@ Examples of common URIs are:
|
||||||
<!-- Author's note: These examples should be consistent with the matrix.to counterparts. -->
|
<!-- Author's note: These examples should be consistent with the matrix.to counterparts. -->
|
||||||
* Link to `#somewhere:example.org`: `matrix:r/somewhere:example.org`
|
* Link to `#somewhere:example.org`: `matrix:r/somewhere:example.org`
|
||||||
* Link to `!somewhere:example.org`: `matrix:roomid/somewhere:example.org?via=elsewhere.ca`
|
* Link to `!somewhere:example.org`: `matrix:roomid/somewhere:example.org?via=elsewhere.ca`
|
||||||
* Link to `$event` in `#somewhere:example.org`: `matrix:r/somewhere:example.org/e/event`
|
|
||||||
* Link to `$event` in `!somewhere:example.org`: `matrix:roomid/somewhere:example.org/e/event?via=elsewhere.ca`
|
* Link to `$event` in `!somewhere:example.org`: `matrix:roomid/somewhere:example.org/e/event?via=elsewhere.ca`
|
||||||
* Link to chat with `@alice:example.org`: `matrix:u/alice:example.org?action=chat`
|
* Link to chat with `@alice:example.org`: `matrix:u/alice:example.org?action=chat`
|
||||||
|
|
||||||
A suggested client implementation algorithm is available in the
|
A suggested client implementation algorithm is available in the
|
||||||
[original MSC](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/2312-matrix-uri.md#recommended-implementation).
|
[original MSC](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/2312-matrix-uri.md#recommended-implementation).
|
||||||
|
|
||||||
##### matrix.to navigation
|
#### matrix.to navigation
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
This namespacing existed prior to a `matrix:` scheme. This is **not**
|
matrix.to is a Namespace URI which existed prior to a `matrix:` URI scheme.
|
||||||
meant to be interpreted as an available web service - see below for more
|
This is **not** meant to be interpreted as an available web service - see
|
||||||
details.
|
below for more details.
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
A matrix.to URI has the following format, based upon the specification
|
A matrix.to URI has the following format, based upon the specification
|
||||||
defined in [RFC 3986](https://tools.ietf.org/html/rfc3986):
|
defined in [RFC 3986](https://tools.ietf.org/html/rfc3986):
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
https://matrix.to/#/<identifier>/<extra parameter>?<additional arguments>
|
https://matrix.to/#/<identifier>/<extra parameter>?<additional arguments>
|
||||||
```
|
```
|
||||||
|
|
||||||
The identifier may be a room ID, room alias, user ID, or group ID. The
|
The identifier may be a room ID, room alias, or user ID. The
|
||||||
extra parameter is only used in the case of permalinks where an event ID
|
extra parameter is only used in the case of permalinks where an event ID
|
||||||
is referenced. The matrix.to URI, when referenced, must always start
|
is referenced. The matrix.to URI, when referenced, must always start
|
||||||
with `https://matrix.to/#/` followed by the identifier.
|
with `https://matrix.to/#/` followed by the identifier.
|
||||||
|
|
@ -811,10 +891,16 @@ Examples of matrix.to URIs are:
|
||||||
<!-- Author's note: These examples should be consistent with the matrix scheme counterparts. -->
|
<!-- Author's note: These examples should be consistent with the matrix scheme counterparts. -->
|
||||||
* Link to `#somewhere:example.org`: `https://matrix.to/#/%23somewhere%3Aexample.org`
|
* Link to `#somewhere:example.org`: `https://matrix.to/#/%23somewhere%3Aexample.org`
|
||||||
* Link to `!somewhere:example.org`: `https://matrix.to/#/!somewhere%3Aexample.org?via=elsewhere.ca`
|
* Link to `!somewhere:example.org`: `https://matrix.to/#/!somewhere%3Aexample.org?via=elsewhere.ca`
|
||||||
* Link to `$event` in `#somewhere:example.org`: `https://matrix.to/#/%23somewhere:example.org/%24event%3Aexample.org`
|
|
||||||
* Link to `$event` in `!somewhere:example.org`: `https://matrix.to/#/!somewhere%3Aexample.org/%24event%3Aexample.org?via=elsewhere.ca`
|
* Link to `$event` in `!somewhere:example.org`: `https://matrix.to/#/!somewhere%3Aexample.org/%24event%3Aexample.org?via=elsewhere.ca`
|
||||||
* Link to `@alice:example.org`: `https://matrix.to/#/%40alice%3Aexample.org`
|
* Link to `@alice:example.org`: `https://matrix.to/#/%40alice%3Aexample.org`
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% changed-in v="1.11" %}}
|
||||||
|
Referencing event IDs within a room identified by room alias rather than room ID
|
||||||
|
is now deprecated. We are not aware of these ever having been used in
|
||||||
|
practice, and are nonsensical given room aliases are mutable.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
Historically, clients have not produced URIs which are fully encoded.
|
Historically, clients have not produced URIs which are fully encoded.
|
||||||
Clients should try to interpret these cases to the best of their
|
Clients should try to interpret these cases to the best of their
|
||||||
|
|
@ -830,16 +916,15 @@ encoded when producing matrix.to URIs, however.
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
<!-- TODO: @@TravisR: Make "Spaces" a link when that specification exists -->
|
|
||||||
In prior versions of this specification, a concept of "groups" were mentioned
|
In prior versions of this specification, a concept of "groups" were mentioned
|
||||||
to organize rooms. This functionality did not properly get introduced into
|
to organize rooms. This functionality did not properly get introduced into
|
||||||
the specification and is subsequently replaced with "Spaces". Historical
|
the specification and is subsequently replaced with [Spaces](/client-server-api/#spaces). Historical
|
||||||
matrix.to URIs pointing to groups might still exist: they take the form
|
matrix.to URIs pointing to groups might still exist: they take the form
|
||||||
`https://matrix.to/#/%2Bexample%3Aexample.org` (where the `+` sigil may or
|
`https://matrix.to/#/%2Bexample%3Aexample.org` (where the `+` sigil may or
|
||||||
may not be encoded).
|
may not be encoded).
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
##### Routing
|
#### Routing
|
||||||
|
|
||||||
Room IDs are not routable on their own as there is no reliable domain to
|
Room IDs are not routable on their own as there is no reliable domain to
|
||||||
send requests to. This is partially mitigated with the addition of a
|
send requests to. This is partially mitigated with the addition of a
|
||||||
|
|
@ -852,8 +937,8 @@ A room (or room permalink) which isn't using a room alias should supply
|
||||||
at least one server using `via` in the URI's query string. Multiple servers
|
at least one server using `via` in the URI's query string. Multiple servers
|
||||||
can be specified by including multuple `via` parameters.
|
can be specified by including multuple `via` parameters.
|
||||||
|
|
||||||
The values of `via` are intended to be passed along as the `server_name`
|
The values of `via` are intended to be passed along on the
|
||||||
parameters on the [Client Server `/join/{roomIdOrAlias}` API](/client-server-api/#post_matrixclientv3joinroomidoralias).
|
[Client Server `/join/{roomIdOrAlias}` API](/client-server-api/#post_matrixclientv3joinroomidoralias).
|
||||||
|
|
||||||
When generating room links and permalinks, the application should pick
|
When generating room links and permalinks, the application should pick
|
||||||
servers which have a high probability of being in the room in the
|
servers which have a high probability of being in the room in the
|
||||||
|
|
@ -890,9 +975,53 @@ unique servers based on the following criteria:
|
||||||
specify the servers it can. For example, a room with only 2 users in
|
specify the servers it can. For example, a room with only 2 users in
|
||||||
it would result in maximum 2 `via` parameters.
|
it would result in maximum 2 `via` parameters.
|
||||||
|
|
||||||
|
### Opaque Identifiers
|
||||||
|
|
||||||
|
The specification defines some identifiers to use the *Opaque Identifier
|
||||||
|
Grammar*. This is a common grammar intended for non-user-visible identifiers
|
||||||
|
which do not require parsing or interpretation (other than as a unique
|
||||||
|
identifier).
|
||||||
|
|
||||||
|
The grammar is defined as:
|
||||||
|
|
||||||
|
* Identifiers must be entirely composed of the characters `[0-9]`, `[A-Z]`,
|
||||||
|
`[a-z]`, `-`, `.`, `_`, and `~`.
|
||||||
|
* Unless otherwise specified, identifiers must be at least one character and at
|
||||||
|
most 255 characters in length.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
The acceptable character set matches the unreserved character set in [RFC
|
||||||
|
3986](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
## Cryptographic key representation
|
||||||
|
|
||||||
|
Sometimes it is necessary to present a private cryptographic key in the user
|
||||||
|
interface.
|
||||||
|
|
||||||
|
When this happens, the key SHOULD be presented as a string formatted as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
1. A byte array is created, consisting of two bytes `0x8B` and `0x01`,
|
||||||
|
followed by the raw key.
|
||||||
|
2. All the bytes in the array above, including the two header bytes,
|
||||||
|
are XORed together to form a parity byte. This parity byte is
|
||||||
|
appended to the byte array.
|
||||||
|
3. The byte array is encoded using base58, using the the alphabet
|
||||||
|
`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`.
|
||||||
|
4. A space is added after every 4th character.
|
||||||
|
|
||||||
|
When reading in a key, clients should disregard whitespace, and
|
||||||
|
perform the reverse of steps 1 through 4.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
The base58 alphabet is the same as that used for [Bitcoin
|
||||||
|
addresses](https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
## 3PID Types
|
## 3PID Types
|
||||||
|
|
||||||
Third Party Identifiers (3PIDs) represent identifiers on other
|
Third-party Identifiers (3PIDs) represent identifiers on other
|
||||||
namespaces that might be associated with a particular person. They
|
namespaces that might be associated with a particular person. They
|
||||||
comprise a tuple of `medium` which is a string that identifies the
|
comprise a tuple of `medium` which is a string that identifies the
|
||||||
namespace in which the identifier exists, and an `address`: a string
|
namespace in which the identifier exists, and an `address`: a string
|
||||||
|
|
@ -934,6 +1063,30 @@ The `address` is the telephone number represented as a MSISDN (Mobile
|
||||||
Station International Subscriber Directory Number) as defined by the
|
Station International Subscriber Directory Number) as defined by the
|
||||||
E.164 numbering plan. Note that MSISDNs do not include a leading '+'.
|
E.164 numbering plan. Note that MSISDNs do not include a leading '+'.
|
||||||
|
|
||||||
|
## Glob-style matching
|
||||||
|
|
||||||
|
It is useful to match strings via globbing in some situations. Globbing in Matrix
|
||||||
|
uses the following rules:
|
||||||
|
|
||||||
|
* The character `*` matches zero or more characters.
|
||||||
|
* `?` matches exactly one character.
|
||||||
|
|
||||||
|
## Dot-separated property paths
|
||||||
|
|
||||||
|
It is useful to express the "path" to an event property by concatenating property
|
||||||
|
names with dots, e.g. `content.body` would represent a `body` property in the
|
||||||
|
event's `content`.
|
||||||
|
|
||||||
|
To handle ambiguity when a property name contains a dot, any literal dot or
|
||||||
|
backslash found in a property name should be escaped with a backslash. E.g. a
|
||||||
|
property `m.relates_to` in the `content` would be expressed as
|
||||||
|
`content.m\.relates_to`. Similarly, a `content` property named `m\foo` would be
|
||||||
|
expressed as `content.m\\foo`.
|
||||||
|
|
||||||
|
Other escape sequences are left as-is, e.g. a `\x` would be treated as a literal
|
||||||
|
backslash followed by 'x'. It is recommended that implementations do not redundantly
|
||||||
|
escape characters, as other escape sequences are reserved for future use.
|
||||||
|
|
||||||
## Security Threat Model
|
## Security Threat Model
|
||||||
|
|
||||||
### Denial of Service
|
### Denial of Service
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,14 @@
|
||||||
title: "Application Service API"
|
title: "Application Service API"
|
||||||
weight: 30
|
weight: 30
|
||||||
type: docs
|
type: docs
|
||||||
|
description: |
|
||||||
|
The Matrix client-server API and server-server APIs provide a consistent,
|
||||||
|
self-contained federated messaging fabric but leave little room for custom
|
||||||
|
server-side behaviour such as gateways, filters, or extensible hooks. The
|
||||||
|
Application Service API defines a standard way to add this extensible
|
||||||
|
functionality, independent of the underlying homeserver implementation.
|
||||||
---
|
---
|
||||||
|
|
||||||
The Matrix client-server API and server-server APIs provide the means to
|
|
||||||
implement a consistent self-contained federated messaging fabric.
|
|
||||||
However, they provide limited means of implementing custom server-side
|
|
||||||
behaviour in Matrix (e.g. gateways, filters, extensible hooks etc). The
|
|
||||||
Application Service API (AS API) defines a standard API to allow such
|
|
||||||
extensible functionality to be implemented irrespective of the
|
|
||||||
underlying homeserver implementation.
|
|
||||||
|
|
||||||
## Application Services
|
## Application Services
|
||||||
|
|
||||||
Application services are passive and can only observe events from the
|
Application services are passive and can only observe events from the
|
||||||
|
|
@ -164,19 +162,27 @@ each is as follows:
|
||||||
Homeservers should periodically try again for the newer endpoints
|
Homeservers should periodically try again for the newer endpoints
|
||||||
because the application service may have been updated.
|
because the application service may have been updated.
|
||||||
|
|
||||||
|
#### Unknown routes
|
||||||
|
|
||||||
|
If a request for an unsupported (or unknown) endpoint is received then the server
|
||||||
|
must respond with a 404 `M_UNRECOGNIZED` error.
|
||||||
|
|
||||||
|
Similarly, a 405 `M_UNRECOGNIZED` error is used to denote an unsupported method
|
||||||
|
to a known endpoint.
|
||||||
|
|
||||||
#### Pushing events
|
#### Pushing events
|
||||||
|
|
||||||
The application service API provides a transaction API for sending a
|
The application service API provides a transaction API for sending a
|
||||||
list of events. Each list of events includes a transaction ID, which
|
list of events. Each list of events includes a transaction ID, which
|
||||||
works as follows:
|
works as follows:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
Typical
|
Typical
|
||||||
HS ---> AS : Homeserver sends events with transaction ID T.
|
HS ---> AS : Homeserver sends events with transaction ID T.
|
||||||
<--- : Application Service sends back 200 OK.
|
<--- : Application Service sends back 200 OK.
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
AS ACK Lost
|
AS ACK Lost
|
||||||
HS ---> AS : Homeserver sends events with transaction ID T.
|
HS ---> AS : Homeserver sends events with transaction ID T.
|
||||||
<-/- : AS 200 OK is lost.
|
<-/- : AS 200 OK is lost.
|
||||||
|
|
@ -199,6 +205,87 @@ processed the events.
|
||||||
|
|
||||||
{{% http-api spec="application-service" api="transactions" %}}
|
{{% http-api spec="application-service" api="transactions" %}}
|
||||||
|
|
||||||
|
##### Pushing ephemeral data
|
||||||
|
|
||||||
|
{{% added-in v="1.13" %}}
|
||||||
|
|
||||||
|
If the `receive_ephemeral` settings is enabled in the [registration](#registration)
|
||||||
|
file, homeservers MUST send ephemeral data that is relevant to the application
|
||||||
|
service via the transaction API, using the `ephemeral` property of the request's
|
||||||
|
body. This property is an array that is effectively a combination of the
|
||||||
|
`presence` and `ephemeral` sections of the client-server [`/sync`](/client-server-api/#get_matrixclientv3sync)
|
||||||
|
API.
|
||||||
|
|
||||||
|
There are currently three event types that can be delivered to an application
|
||||||
|
service:
|
||||||
|
|
||||||
|
- **[`m.presence`](/client-server-api/#mpresence)**: MUST be sent to the
|
||||||
|
application service if the data would apply contextually. For example, a
|
||||||
|
presence update for a user an application service shares a room with, or
|
||||||
|
matching one of the application service's namespaces.
|
||||||
|
- **[`m.typing`](/client-server-api/#mtyping)**: MUST be sent to the application
|
||||||
|
service under the same rules as regular events, meaning that the application
|
||||||
|
service must have registered interest in the room itself, or in a user that is
|
||||||
|
in the room. The data MUST use the same format as the client-server API, with
|
||||||
|
the addition of a `room_id` property at the top level to identify the room that
|
||||||
|
they were sent in.
|
||||||
|
- **[`m.receipt`](/client-server-api/#mreceipt)**: MUST be sent to the
|
||||||
|
application service under the same rules as regular events, meaning that the
|
||||||
|
application service must have registered interest in the room itself, or in a
|
||||||
|
user that is in the room. The data MUST use the same format as the client-server
|
||||||
|
API, with the addition of a `room_id` property at the top level to identify the
|
||||||
|
room that they were sent in. [Private read receipts](/client-server-api/#private-read-receipts)
|
||||||
|
MUST only be sent for users matching one of the application service's
|
||||||
|
namespaces. Normal read receipts and threaded read receipts are always sent.
|
||||||
|
|
||||||
|
#### Pinging
|
||||||
|
|
||||||
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
|
The application service API includes a ping mechanism to allow
|
||||||
|
appservices to ensure that the homeserver can reach the appservice.
|
||||||
|
Appservices may use this mechanism to detect misconfigurations and
|
||||||
|
report them appropriately.
|
||||||
|
|
||||||
|
Implementations using this mechanism should take care to not fail
|
||||||
|
entirely in the event of temporary issues, e.g. gracefully handling
|
||||||
|
cases where the appservice is started before the homeserver.
|
||||||
|
|
||||||
|
The mechanism works as follows (note: the human-readable `error` fields
|
||||||
|
have been omitted for brevity):
|
||||||
|
|
||||||
|
**Typical**
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
AS ---> HS : /_matrix/client/v1/appservice/{appserviceId}/ping {"transaction_id": "meow"}
|
||||||
|
HS ---> AS : /_matrix/app/v1/ping {"transaction_id": "meow"}
|
||||||
|
HS <--- AS : 200 OK {}
|
||||||
|
AS <--- HS : 200 OK {"duration_ms": 123}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Incorrect `hs_token`**
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
AS ---> HS : /_matrix/client/v1/appservice/{appserviceId}/ping {"transaction_id": "meow"}
|
||||||
|
HS ---> AS : /_matrix/app/v1/ping {"transaction_id": "meow"}
|
||||||
|
HS <--- AS : 403 Forbidden {"errcode": "M_FORBIDDEN"}
|
||||||
|
AS <--- HS : 502 Bad Gateway {"errcode": "M_BAD_STATUS", "status": 403, "body": "{\"errcode\": \"M_FORBIDDEN\"}"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Can't connect to appservice**
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
AS ---> HS : /_matrix/client/v1/appservice/{appserviceId}/ping {"transaction_id": "meow"}
|
||||||
|
HS -/-> AS : /_matrix/app/v1/ping {"transaction_id": "meow"}
|
||||||
|
AS <--- HS : 502 Bad Gateway {"errcode": "M_CONNECTION_FAILED"}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `/_matrix/app/v1/ping` endpoint is described here. The
|
||||||
|
[`/_matrix/client/v1/appservice/{appserviceId}/ping`](#post_matrixclientv1appserviceappserviceidping)
|
||||||
|
endpoint is under the Client-Server API extensions section below.
|
||||||
|
|
||||||
|
{{% http-api spec="application-service" api="ping" %}}
|
||||||
|
|
||||||
#### Querying
|
#### Querying
|
||||||
|
|
||||||
The application service API includes two querying APIs: for room aliases
|
The application service API includes two querying APIs: for room aliases
|
||||||
|
|
@ -224,18 +311,18 @@ mappings.
|
||||||
|
|
||||||
{{% http-api spec="application-service" api="query_room" %}}
|
{{% http-api spec="application-service" api="query_room" %}}
|
||||||
|
|
||||||
#### Third party networks
|
#### Third-party networks
|
||||||
|
|
||||||
Application services may declare which protocols they support via their
|
Application services may declare which protocols they support via their
|
||||||
registration configuration for the homeserver. These networks are
|
registration configuration for the homeserver. These networks are
|
||||||
generally for third party services such as IRC that the application
|
generally for third-party services such as IRC that the application
|
||||||
service is managing. Application services may populate a Matrix room
|
service is managing. Application services may populate a Matrix room
|
||||||
directory for their registered protocols, as defined in the
|
directory for their registered protocols, as defined in the
|
||||||
Client-Server API Extensions.
|
Client-Server API Extensions.
|
||||||
|
|
||||||
Each protocol may have several "locations" (also known as "third party
|
Each protocol may have several "locations" (also known as "third-party
|
||||||
locations" or "3PLs"). A location within a protocol is a place in the
|
locations" or "3PLs"). A location within a protocol is a place in the
|
||||||
third party network, such as an IRC channel. Users of the third party
|
third-party network, such as an IRC channel. Users of the third-party
|
||||||
network may also be represented by the application service.
|
network may also be represented by the application service.
|
||||||
|
|
||||||
Locations and users can be searched by fields defined by the application
|
Locations and users can be searched by fields defined by the application
|
||||||
|
|
@ -267,6 +354,7 @@ service would like to masquerade as.
|
||||||
Inputs:
|
Inputs:
|
||||||
- Application service token (`as_token`)
|
- Application service token (`as_token`)
|
||||||
- User ID in the AS namespace to act as.
|
- User ID in the AS namespace to act as.
|
||||||
|
- Device ID belonging to the User ID to act with.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- This applies to all aspects of the Client-Server API, except for
|
- This applies to all aspects of the Client-Server API, except for
|
||||||
|
|
@ -286,9 +374,19 @@ service's `user` namespaces. If the parameter is missing, the homeserver
|
||||||
is to assume the application service intends to act as the user implied
|
is to assume the application service intends to act as the user implied
|
||||||
by the `sender_localpart` property of the registration.
|
by the `sender_localpart` property of the registration.
|
||||||
|
|
||||||
|
{{% added-in v="1.17" %}} Application services MAY similarly masquerade
|
||||||
|
as a specific device ID belonging the user ID through use of the `device_id`
|
||||||
|
query string parameter on the request. If the given device ID is not known
|
||||||
|
to belong to the user, the server will return a 400 `M_UNKNOWN_DEVICE` error.
|
||||||
|
If no `user_id` is supplied, the `device_id` MUST belong to the user implied
|
||||||
|
by the `sender_localpart` property of the application service's registration.
|
||||||
|
If no `device_id` is supplied, the homeserver is to assume the request is
|
||||||
|
being made without a device ID and will fail to complete operations which
|
||||||
|
require a device ID (such as uploading one-time keys).
|
||||||
|
|
||||||
An example request would be:
|
An example request would be:
|
||||||
|
|
||||||
GET /_matrix/client/v3/account/whoami?user_id=@_irc_user:example.org
|
GET /_matrix/client/v3/account/whoami?user_id=@_irc_user:example.org&device_id=ABC123
|
||||||
Authorization: Bearer YourApplicationServiceTokenHere
|
Authorization: Bearer YourApplicationServiceTokenHere
|
||||||
|
|
||||||
#### Timestamp massaging
|
#### Timestamp massaging
|
||||||
|
|
@ -328,6 +426,8 @@ imports and similar behaviour).
|
||||||
|
|
||||||
#### Server admin style permissions
|
#### Server admin style permissions
|
||||||
|
|
||||||
|
{{% changed-in v="1.17" %}}
|
||||||
|
|
||||||
The homeserver needs to give the application service *full control* over
|
The homeserver needs to give the application service *full control* over
|
||||||
its namespace, both for users and for room aliases. This means that the
|
its namespace, both for users and for room aliases. This means that the
|
||||||
AS should be able to manage any users and room alias in its namespace. No additional API
|
AS should be able to manage any users and room alias in its namespace. No additional API
|
||||||
|
|
@ -344,33 +444,59 @@ achieved by including the `as_token` on a `/register` request, along
|
||||||
with a login type of `m.login.application_service` to set the desired
|
with a login type of `m.login.application_service` to set the desired
|
||||||
user ID without a password.
|
user ID without a password.
|
||||||
|
|
||||||
POST /_matrix/client/v3/register
|
```http
|
||||||
Authorization: Bearer YourApplicationServiceTokenHere
|
POST /_matrix/client/v3/register
|
||||||
|
Authorization: Bearer YourApplicationServiceTokenHere
|
||||||
|
```
|
||||||
|
|
||||||
Content:
|
```json
|
||||||
{
|
{
|
||||||
type: "m.login.application_service",
|
"type": "m.login.application_service",
|
||||||
username: "_irc_example"
|
"username": "_irc_example"
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Similarly, logging in as users needs API changes in order to allow the AS to
|
{{% boxes/note %}}
|
||||||
log in without needing the user's password. This is achieved by including the
|
{{% added-in v="1.17" %}}
|
||||||
`as_token` on a `/login` request, along with a login type of
|
Servers MUST still allow application services to use the `/register` endpoint
|
||||||
`m.login.application_service`:
|
with a login type of `m.login.application_service` even if they don't support
|
||||||
|
the [Legacy Authentication API](/client-server-api/#legacy-api).
|
||||||
|
|
||||||
|
In that case application services MUST set the `"inhibit_login": true` parameter
|
||||||
|
as they cannot use it to log in as users. If the `inhibit_login` parameter is
|
||||||
|
not set to `true`, the server MUST return a 400 HTTP status code with an
|
||||||
|
`M_APPSERVICE_LOGIN_UNSUPPORTED` error code.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
Similarly, logging in as users using the [Legacy authentication API](/client-server-api/#legacy-api)
|
||||||
|
needs API changes in order to allow the AS to log in without needing the user's
|
||||||
|
password. This is achieved by including the `as_token` on a `/login` request,
|
||||||
|
along with a login type of `m.login.application_service`:
|
||||||
|
|
||||||
{{% added-in v="1.2" %}}
|
{{% added-in v="1.2" %}}
|
||||||
|
|
||||||
POST /_matrix/client/v3/login
|
```http
|
||||||
Authorization: Bearer YourApplicationServiceTokenHere
|
POST /_matrix/client/v3/login
|
||||||
|
Authorization: Bearer YourApplicationServiceTokenHere
|
||||||
|
```
|
||||||
|
|
||||||
Content:
|
```json
|
||||||
{
|
{
|
||||||
type: "m.login.application_service",
|
"type": "m.login.application_service",
|
||||||
"identifier": {
|
"identifier": {
|
||||||
"type": "m.id.user",
|
"type": "m.id.user",
|
||||||
"user": "_irc_example"
|
"user": "_irc_example"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.17" %}}
|
||||||
|
Application services MUST NOT use the `/login` endpoint if the server doesn't
|
||||||
|
support the Legacy authentication API. If `/login` is called with the
|
||||||
|
`m.login.application_service` login type the server MUST return a 400 HTTP
|
||||||
|
status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
Application services which attempt to create users or aliases *outside*
|
Application services which attempt to create users or aliases *outside*
|
||||||
of their defined namespaces, or log in as users outside of their defined
|
of their defined namespaces, or log in as users outside of their defined
|
||||||
|
|
@ -380,6 +506,21 @@ an application service-defined namespace will receive the same
|
||||||
`M_EXCLUSIVE` error code, but only if the application service has
|
`M_EXCLUSIVE` error code, but only if the application service has
|
||||||
defined the namespace as `exclusive`.
|
defined the namespace as `exclusive`.
|
||||||
|
|
||||||
|
If `/register` or `/login` is called with the `m.login.application_service`
|
||||||
|
login type, but without a valid `as_token`, the endpoints will return an error
|
||||||
|
with the `M_MISSING_TOKEN` or `M_UNKNOWN_TOKEN` error code and 401 as the HTTP
|
||||||
|
status code. This is the same behavior as invalid auth in the client-server API
|
||||||
|
(see [Using access tokens](/client-server-api/#using-access-tokens)).
|
||||||
|
|
||||||
|
#### Pinging
|
||||||
|
|
||||||
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
|
This is the client-server API companion endpoint for the
|
||||||
|
[pinging](#pinging) mechanism described above.
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="appservice_ping" %}}
|
||||||
|
|
||||||
#### Using `/sync` and `/events`
|
#### Using `/sync` and `/events`
|
||||||
|
|
||||||
Application services wishing to use `/sync` or `/events` from the
|
Application services wishing to use `/sync` or `/events` from the
|
||||||
|
|
@ -388,16 +529,48 @@ via the query string). It is expected that the application service use
|
||||||
the transactions pushed to it to handle events rather than syncing with
|
the transactions pushed to it to handle events rather than syncing with
|
||||||
the user implied by `sender_localpart`.
|
the user implied by `sender_localpart`.
|
||||||
|
|
||||||
#### Application service room directories
|
#### Published room directories
|
||||||
|
|
||||||
Application services can maintain their own room directories for their
|
Application services can maintain their own published room directories for
|
||||||
defined third party protocols. These room directories may be accessed by
|
their defined third-party protocols. These directories may be accessed by
|
||||||
clients through additional parameters on the `/publicRooms`
|
clients through additional parameters on the `/publicRooms`
|
||||||
client-server endpoint.
|
client-server endpoint.
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="appservice_room_directory" %}}
|
{{% http-api spec="client-server" api="appservice_room_directory" %}}
|
||||||
|
|
||||||
### Referencing messages from a third party network
|
#### Device management
|
||||||
|
|
||||||
|
{{% added-in v="1.17" %}}
|
||||||
|
|
||||||
|
Application services need to be able to create and delete devices to manage the
|
||||||
|
encryption for their users without having to rely on `/login`, which also
|
||||||
|
generates an access token for the user, and which might not be available for
|
||||||
|
homeservers that only support the [OAuth 2.0 API](/client-server-api/#oauth-20-api).
|
||||||
|
|
||||||
|
##### Creating devices
|
||||||
|
|
||||||
|
Application services can use the [`PUT /_matrix/client/v3/devices/{deviceId}`](/client-server-api/#put_matrixclientv3devicesdeviceid)
|
||||||
|
endpoint to create new devices.
|
||||||
|
|
||||||
|
##### Deleting devices
|
||||||
|
|
||||||
|
The following endpoints used to delete devices MUST NOT require [User-Interactive
|
||||||
|
Authentication](/client-server-api/#user-interactive-authentication-api) when
|
||||||
|
used by an application service:
|
||||||
|
|
||||||
|
* [`DELETE /_matrix/client/v3/devices/{deviceId}`](/client-server-api/#delete_matrixclientv3devicesdeviceid)
|
||||||
|
* [`POST /_matrix/client/v3/delete_devices`](/client-server-api/#post_matrixclientv3delete_devices)
|
||||||
|
|
||||||
|
#### Cross-signing
|
||||||
|
|
||||||
|
{{% added-in v="1.17" %}}
|
||||||
|
|
||||||
|
Appservices need to be able to verify themselves and replace their cross-signing
|
||||||
|
keys, so the [`POST /_matrix/client/v3/keys/device_signing/upload`](/client-server-api/#post_matrixclientv3keysdevice_signingupload)
|
||||||
|
endpoint MUST NOT require [User-Interactive Authentication](/client-server-api/#user-interactive-authentication-api)
|
||||||
|
when used by an application service, even if cross-signing keys already exist.
|
||||||
|
|
||||||
|
### Referencing messages from a third-party network
|
||||||
|
|
||||||
Application services should include an `external_url` in the `content`
|
Application services should include an `external_url` in the `content`
|
||||||
of events it emits to indicate where the message came from. This
|
of events it emits to indicate where the message came from. This
|
||||||
|
|
|
||||||
8
content/changelog/_index.md
Normal file
8
content/changelog/_index.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
title: Changelog
|
||||||
|
type: docs
|
||||||
|
layout: changelog-index
|
||||||
|
weight: 1000
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- This page will be redirected to the latest version's changelog -->
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
---
|
---
|
||||||
title: Changelog
|
title: Historical versions
|
||||||
type: docs
|
type: docs
|
||||||
weight: 1000
|
outputs:
|
||||||
|
- html
|
||||||
---
|
---
|
||||||
|
|
||||||
{{% changelog/changelog-description %}}
|
Before version 1.1, versioning was applied at the level of individual API specifications.
|
||||||
|
This section includes links to these versions of the APIs.
|
||||||
|
|
||||||
{{% changelog/changelogs %}}
|
## Client-Server API
|
||||||
|
|
||||||
<h2 id="historical-versions" class="no-numbers">Historical versions</h2>
|
|
||||||
|
|
||||||
Before version 1.1, versioning was applied at the level of individual API specifications. This section includes links to these versions of the APIs.
|
|
||||||
|
|
||||||
* **Client-Server API**
|
|
||||||
- [r0.6.1](https://matrix.org/docs/spec/client_server/r0.6.1.html)
|
- [r0.6.1](https://matrix.org/docs/spec/client_server/r0.6.1.html)
|
||||||
- [r0.6.0](https://matrix.org/docs/spec/client_server/r0.6.0.html)
|
- [r0.6.0](https://matrix.org/docs/spec/client_server/r0.6.0.html)
|
||||||
- [r0.5.0](https://matrix.org/docs/spec/client_server/r0.5.0.html)
|
- [r0.5.0](https://matrix.org/docs/spec/client_server/r0.5.0.html)
|
||||||
|
|
@ -26,22 +23,26 @@ Before version 1.1, versioning was applied at the level of individual API specif
|
||||||
The last draft before the spec was formally released in version
|
The last draft before the spec was formally released in version
|
||||||
r0.0.0.
|
r0.0.0.
|
||||||
|
|
||||||
* **Server-Server API**
|
## Server-Server API
|
||||||
|
|
||||||
- [r0.1.4](https://matrix.org/docs/spec/server_server/r0.1.4.html)
|
- [r0.1.4](https://matrix.org/docs/spec/server_server/r0.1.4.html)
|
||||||
- [r0.1.3](https://matrix.org/docs/spec/server_server/r0.1.3.html)
|
- [r0.1.3](https://matrix.org/docs/spec/server_server/r0.1.3.html)
|
||||||
- [r0.1.2](https://matrix.org/docs/spec/server_server/r0.1.2.html)
|
- [r0.1.2](https://matrix.org/docs/spec/server_server/r0.1.2.html)
|
||||||
- [r0.1.1](https://matrix.org/docs/spec/server_server/r0.1.1.html)
|
- [r0.1.1](https://matrix.org/docs/spec/server_server/r0.1.1.html)
|
||||||
- [r0.1.0](https://matrix.org/docs/spec/server_server/r0.1.0.html)
|
- [r0.1.0](https://matrix.org/docs/spec/server_server/r0.1.0.html)
|
||||||
|
|
||||||
* **Application Service API**
|
## Application Service API
|
||||||
|
|
||||||
- [r0.1.1](https://matrix.org/docs/spec/application_service/r0.1.1.html)
|
- [r0.1.1](https://matrix.org/docs/spec/application_service/r0.1.1.html)
|
||||||
- [r0.1.0](https://matrix.org/docs/spec/application_service/r0.1.0.html)
|
- [r0.1.0](https://matrix.org/docs/spec/application_service/r0.1.0.html)
|
||||||
|
|
||||||
* **Identity Service API**
|
## Identity Service API
|
||||||
|
|
||||||
- [r0.3.0](https://matrix.org/docs/spec/identity_service/r0.3.0.html)
|
- [r0.3.0](https://matrix.org/docs/spec/identity_service/r0.3.0.html)
|
||||||
- [r0.2.1](https://matrix.org/docs/spec/identity_service/r0.2.1.html)
|
- [r0.2.1](https://matrix.org/docs/spec/identity_service/r0.2.1.html)
|
||||||
- [r0.2.0](https://matrix.org/docs/spec/identity_service/r0.2.0.html)
|
- [r0.2.0](https://matrix.org/docs/spec/identity_service/r0.2.0.html)
|
||||||
- [r0.1.0](https://matrix.org/docs/spec/identity_service/r0.1.0.html)
|
- [r0.1.0](https://matrix.org/docs/spec/identity_service/r0.1.0.html)
|
||||||
|
|
||||||
* **Push Gateway API**
|
## Push Gateway API
|
||||||
|
|
||||||
- [r0.1.0](https://matrix.org/docs/spec/push_gateway/r0.1.0.html)
|
- [r0.1.0](https://matrix.org/docs/spec/push_gateway/r0.1.0.html)
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
---
|
---
|
||||||
date: 2021-11-09T00:00:00+0000
|
title: v1.1 Changelog
|
||||||
|
linkTitle: v1.1
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2021-11-09
|
||||||
---
|
---
|
||||||
<!--
|
|
||||||
This is a header file for the generated changelog.
|
|
||||||
|
|
||||||
Variables:
|
## Client-Server API
|
||||||
v1.1 = Replaced by the version number (eg: v1.2)
|
|
||||||
November 09, 2021 = Replaced by the date (eg: April 01, 2021)
|
|
||||||
-->
|
|
||||||
|
|
||||||
## v1.1
|
|
||||||
|
|
||||||
<table class="release-info">
|
|
||||||
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-doc/tree/v1.1">https://github.com/matrix-org/matrix-doc/tree/v1.1</a></td>
|
|
||||||
<tr><th>Release date</th><td>November 09, 2021</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
|
||||||
### Client-Server API
|
|
||||||
|
|
||||||
|
|
||||||
<strong>Breaking Changes</strong>
|
<strong>Breaking Changes</strong>
|
||||||
|
|
@ -110,7 +102,7 @@ Variables:
|
||||||
- Fix documentation errors around `threepid_creds`. ([#3471](https://github.com/matrix-org/matrix-doc/issues/3471))
|
- Fix documentation errors around `threepid_creds`. ([#3471](https://github.com/matrix-org/matrix-doc/issues/3471))
|
||||||
|
|
||||||
|
|
||||||
### Server-Server API
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
<strong>New Endpoints</strong>
|
<strong>New Endpoints</strong>
|
||||||
|
|
@ -136,7 +128,7 @@ Variables:
|
||||||
- Tweak the example PDU diagram to better demonstrate situations with multiple `prev_events`. ([#3340](https://github.com/matrix-org/matrix-doc/issues/3340))
|
- Tweak the example PDU diagram to better demonstrate situations with multiple `prev_events`. ([#3340](https://github.com/matrix-org/matrix-doc/issues/3340))
|
||||||
|
|
||||||
|
|
||||||
### Application Service API
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -145,7 +137,7 @@ Variables:
|
||||||
- Fix various typos throughout the specification. ([#2888](https://github.com/matrix-org/matrix-doc/issues/2888))
|
- Fix various typos throughout the specification. ([#2888](https://github.com/matrix-org/matrix-doc/issues/2888))
|
||||||
|
|
||||||
|
|
||||||
### Identity Service API
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>New Endpoints</strong>
|
<strong>New Endpoints</strong>
|
||||||
|
|
@ -168,7 +160,7 @@ Variables:
|
||||||
- Describe how [MSC2844](https://github.com/matrix-org/matrix-doc/pull/2844) affects the `/versions` endpoint. ([#3459](https://github.com/matrix-org/matrix-doc/issues/3459))
|
- Describe how [MSC2844](https://github.com/matrix-org/matrix-doc/pull/2844) affects the `/versions` endpoint. ([#3459](https://github.com/matrix-org/matrix-doc/issues/3459))
|
||||||
|
|
||||||
|
|
||||||
### Push Gateway API
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
|
||||||
93
content/changelog/v1.10.md
Normal file
93
content/changelog/v1.10.md
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
title: v1.10 Changelog
|
||||||
|
linkTitle: v1.10
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2024-03-22
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Allow `/versions` to optionally accept authentication, as per [MSC4026](https://github.com/matrix-org/matrix-spec-proposals/pull/4026). ([#1728](https://github.com/matrix-org/matrix-spec/issues/1728))
|
||||||
|
- Add local erasure requests, as per [MSC4025](https://github.com/matrix-org/matrix-spec-proposals/pull/4025). ([#1730](https://github.com/matrix-org/matrix-spec/issues/1730))
|
||||||
|
- Use the `body` field as optional media caption, as per [MSC2530](https://github.com/matrix-org/matrix-spec-proposals/pull/2530). ([#1731](https://github.com/matrix-org/matrix-spec/issues/1731))
|
||||||
|
- Add server support discovery endpoint, as per [MSC1929](https://github.com/matrix-org/matrix-spec-proposals/pull/1929). ([#1733](https://github.com/matrix-org/matrix-spec/issues/1733))
|
||||||
|
- Add support for multi-stream VoIP, as per [MSC3077](https://github.com/matrix-org/matrix-spec-proposals/pull/3077). ([#1735](https://github.com/matrix-org/matrix-spec/issues/1735))
|
||||||
|
- Specify that the `Retry-After` header may be used to rate-limit a client, as per [MSC4041](https://github.com/matrix-org/matrix-spec-proposals/pull/4041). ([#1737](https://github.com/matrix-org/matrix-spec/issues/1737))
|
||||||
|
- Add support for recursion on the `GET /relations` endpoints, as per [MSC3981](https://github.com/matrix-org/matrix-spec-proposals/pull/3981). ([#1746](https://github.com/matrix-org/matrix-spec/issues/1746))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- The [strike](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strike) element is deprecated in the HTML spec. Clients should prefer [s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s) instead. ([#1629](https://github.com/matrix-org/matrix-spec/issues/1629))
|
||||||
|
- Clarify that read receipts should be batched by thread as well as by room. ([#1685](https://github.com/matrix-org/matrix-spec/issues/1685))
|
||||||
|
- Clarify that threads can be created based on replies. ([#1687](https://github.com/matrix-org/matrix-spec/issues/1687))
|
||||||
|
- Clarify in the reply fallbacks example that the prefix sequence should be repeated for each line. ([#1690](https://github.com/matrix-org/matrix-spec/issues/1690))
|
||||||
|
- Clarify the format of account data objects for secret storage. ([#1695](https://github.com/matrix-org/matrix-spec/issues/1695), [#1734](https://github.com/matrix-org/matrix-spec/issues/1734))
|
||||||
|
- Clarify that the key backup MAC is implemented incorrectly and does not pass the ciphertext through HMAC-SHA-256. ([#1712](https://github.com/matrix-org/matrix-spec/issues/1712))
|
||||||
|
- Clarify one-time key and fallback key types in examples. ([#1715](https://github.com/matrix-org/matrix-spec/issues/1715))
|
||||||
|
- Clarify that the HKDF calculation for SAS uses base64-encoded keys rather than the raw key bytes. ([#1719](https://github.com/matrix-org/matrix-spec/issues/1719))
|
||||||
|
- Clarify how to perform the ECDH exchange in step 12 of the SAS process. ([#1720](https://github.com/matrix-org/matrix-spec/issues/1720))
|
||||||
|
- Document the deprecation policy of HTML tags, as per [MSC4077](https://github.com/matrix-org/matrix-spec-proposals/pull/4077). ([#1732](https://github.com/matrix-org/matrix-spec/issues/1732))
|
||||||
|
- The [font](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/font) element is deprecated in the HTML spec. Clients should prefer [span](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span) with the `data-mx-bg-color` and `data-mx-color` attributes instead. ([#1739](https://github.com/matrix-org/matrix-spec/issues/1739))
|
||||||
|
- Disambiguate uses of `PublicRoomsChunk` in the `GET /hierarchy` endpoint. ([#1740](https://github.com/matrix-org/matrix-spec/issues/1740))
|
||||||
|
- Clarify that `sdpMid` and `sdpMLineIndex` are not required in `m.call.candidates`. ([#1742](https://github.com/matrix-org/matrix-spec/issues/1742))
|
||||||
|
- Fix various typos throughout the specification. ([#1748](https://github.com/matrix-org/matrix-spec/issues/1748))
|
||||||
|
- Clearly indicate that each `Content-Type` may have distinct behaviour on non-JSON requests/responses. ([#1756](https://github.com/matrix-org/matrix-spec/issues/1756))
|
||||||
|
- Clarify that the `m.push_rules` account data type cannot be set using the `/account_data` API, as per [MSC4010](https://github.com/matrix-org/matrix-spec-proposals/pull/4010). ([#1763](https://github.com/matrix-org/matrix-spec/issues/1763))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify Server-Server API request signing example by using the `POST` HTTP method, as `GET` requests don't have request bodies. ([#1721](https://github.com/matrix-org/matrix-spec/issues/1721))
|
||||||
|
- Disambiguate uses of `PublicRoomsChunk` in the `GET /hierarchy` endpoint. ([#1740](https://github.com/matrix-org/matrix-spec/issues/1740))
|
||||||
|
- Clarify that the `children_state`, `room_type` and `allowed_room_ids` properties in the items of the `children` array of the response of the `GET /hierarchy` endpoint are not required. ([#1741](https://github.com/matrix-org/matrix-spec/issues/1741))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify that the `/login` and `/register` endpoints should fail when using the `m.login.application_service` login type without a valid `as_token`. ([#1744](https://github.com/matrix-org/matrix-spec/issues/1744))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- For room versions 7 through 11: Clarify that `invite->knock` is not a legal transition. ([#1717](https://github.com/matrix-org/matrix-spec/issues/1717))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Update the spec release process. ([#1680](https://github.com/matrix-org/matrix-spec/issues/1680))
|
||||||
|
- Minor clarifications to the contributing guide. ([#1697](https://github.com/matrix-org/matrix-spec/issues/1697))
|
||||||
|
- Update Docsy to v0.8.0. ([#1699](https://github.com/matrix-org/matrix-spec/issues/1699), [#1762](https://github.com/matrix-org/matrix-spec/issues/1762))
|
||||||
|
- Fix npm release script for `@matrix-org/spec`. ([#1713](https://github.com/matrix-org/matrix-spec/issues/1713))
|
||||||
|
- Add some clarifications around implementation requirements for MSCs. ([#1718](https://github.com/matrix-org/matrix-spec/issues/1718))
|
||||||
|
- Update HTML templates to include links to object schema definitions. ([#1724](https://github.com/matrix-org/matrix-spec/issues/1724))
|
||||||
|
- Factor out all the common parameters of the various `/relations` apis. ([#1745](https://github.com/matrix-org/matrix-spec/issues/1745))
|
||||||
|
- Add support for `$ref` URIs containing fragments in OpenAPI definitions and JSON schemas. ([#1751](https://github.com/matrix-org/matrix-spec/issues/1751), [#1754](https://github.com/matrix-org/matrix-spec/issues/1754))
|
||||||
161
content/changelog/v1.11.md
Normal file
161
content/changelog/v1.11.md
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
---
|
||||||
|
title: v1.11 Changelog
|
||||||
|
linkTitle: v1.11
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2024-06-20
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Authentication using a query string is now deprecated, as per [MSC4126](https://github.com/matrix-org/matrix-spec-proposals/issues/4126). The `Authorization` header should be used instead. ([#1808](https://github.com/matrix-org/matrix-spec/issues/1808))
|
||||||
|
- Use of the `/_matrix/media/*` endpoints is now deprecated. New, authenticated, endpoints are available instead. ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
|
||||||
|
**New Endpoints**
|
||||||
|
|
||||||
|
- [`GET /_matrix/client/v1/media/config`](/client-server-api/#get_matrixclientv1mediaconfig) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
- [`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaid) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
- [`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}/{fileName}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaidfilename) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
- [`GET /_matrix/client/v1/media/preview_url`](/client-server-api/#get_matrixclientv1mediapreview_url) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
- [`GET /_matrix/client/v1/media/thumbnail/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediathumbnailservernamemediaid) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add support for muting in VoIP calls, as per [MSC3291](https://github.com/matrix-org/matrix-spec-proposals/pull/3291). ([#1755](https://github.com/matrix-org/matrix-spec/issues/1755))
|
||||||
|
- Add optional `animated` query string option to `GET /thumbnail`, as per [MSC2705](https://github.com/matrix-org/matrix-spec-proposals/pull/2705). ([#1757](https://github.com/matrix-org/matrix-spec/issues/1757))
|
||||||
|
- Specify terms of services at registration, as per [MSC1692](https://github.com/matrix-org/matrix-spec-proposals/pull/1692). ([#1812](https://github.com/matrix-org/matrix-spec/issues/1812))
|
||||||
|
- Add support for mathematical messages, as per [MSC2191](https://github.com/matrix-org/matrix-spec-proposals/pull/2191). ([#1816](https://github.com/matrix-org/matrix-spec/issues/1816))
|
||||||
|
- Do not require UIA when first uploading cross-signing keys, as per [MSC3967](https://github.com/matrix-org/matrix-spec-proposals/pull/3967). ([#1828](https://github.com/matrix-org/matrix-spec/issues/1828))
|
||||||
|
- Add the new `unsigned.membership` property to events, as per [MSC4115](https://github.com/matrix-org/matrix-spec-proposals/pull/4115). ([#1847](https://github.com/matrix-org/matrix-spec/issues/1847))
|
||||||
|
- Media downloads and thumbnails are now authenticated, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916). ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
- Some media endpoints are now consistently under `/_matrix/client/{version}/media/*` instead of `/_matrix/media/*`, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916). ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Add `/logout` and clarify the endpoints which do not take a JSON request body. ([#1644](https://github.com/matrix-org/matrix-spec/issues/1644))
|
||||||
|
- Clarify that the `type` of the `POST /login` request must be one of the types returned by the `GET /login` response. ([#1776](https://github.com/matrix-org/matrix-spec/issues/1776))
|
||||||
|
- Link to existing grammar where possible in types. ([#1813](https://github.com/matrix-org/matrix-spec/issues/1813))
|
||||||
|
- Rename "recovery key" to "backup decryption key". ([#1819](https://github.com/matrix-org/matrix-spec/issues/1819))
|
||||||
|
- Clarify that the device's Ed25519 signing key should be used in QR code verification (as opposed to the device's Curve25519 identity key). ([#1829](https://github.com/matrix-org/matrix-spec/issues/1829))
|
||||||
|
- Fix various typos throughout the specification. ([#1832](https://github.com/matrix-org/matrix-spec/issues/1832), [#1841](https://github.com/matrix-org/matrix-spec/issues/1841), [#1852](https://github.com/matrix-org/matrix-spec/issues/1852), [#1853](https://github.com/matrix-org/matrix-spec/issues/1853))
|
||||||
|
- Specify the encoding to be used when generating QR codes for device verification. ([#1839](https://github.com/matrix-org/matrix-spec/issues/1839))
|
||||||
|
- Clarify that an access token is optional on the `POST /account/password` and `POST /account/deactivate` endpoints. ([#1843](https://github.com/matrix-org/matrix-spec/issues/1843))
|
||||||
|
- Use RFC 2119 keywords more consistently. ([#1846](https://github.com/matrix-org/matrix-spec/issues/1846), [#1861](https://github.com/matrix-org/matrix-spec/issues/1861))
|
||||||
|
- Move size limits for user, room and event IDs into the appendix and clarify that the length is to be measured in bytes. ([#1850](https://github.com/matrix-org/matrix-spec/issues/1850))
|
||||||
|
- Clarify that relations recursion should be capped at a certain depth. ([#1854](https://github.com/matrix-org/matrix-spec/issues/1854))
|
||||||
|
- Add missing secrets, third-party invites and room tagging modules to feature profiles table. ([#1860](https://github.com/matrix-org/matrix-spec/issues/1860))
|
||||||
|
- Clarify when server name is used and link to the definition. ([#1862](https://github.com/matrix-org/matrix-spec/issues/1862))
|
||||||
|
- Clarify where keys reside when checking an `m.room.encrypted` event. ([#1863](https://github.com/matrix-org/matrix-spec/issues/1863))
|
||||||
|
- Clarify that `/media/v3/upload/{serverName}/{mediaId}` requires authentication. ([#1872](https://github.com/matrix-org/matrix-spec/issues/1872))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Use of the Client-Server API `/_matrix/media/*` endpoints is now deprecated. New, authenticated, endpoints are available instead. ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
|
||||||
|
**New Endpoints**
|
||||||
|
|
||||||
|
- [`GET /_matrix/federation/v1/media/download/{mediaId}`](/server-server-api/#get_matrixfederationv1mediadownloadmediaid) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
- [`GET /_matrix/federation/v1/media/thumbnail/{mediaId}`](/server-server-api/#get_matrixfederationv1mediathumbnailmediaid) ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Media downloads and thumbnails are now authenticated, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916). ([#1858](https://github.com/matrix-org/matrix-spec/issues/1858), [#1869](https://github.com/matrix-org/matrix-spec/issues/1869))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Link to existing grammar where possible in types. ([#1813](https://github.com/matrix-org/matrix-spec/issues/1813))
|
||||||
|
- Clarify that whitespace around commas is allowed in the `X-Matrix` `Authorization` header value params list. ([#1818](https://github.com/matrix-org/matrix-spec/issues/1818))
|
||||||
|
- Clarify that the `event` field of the `/v2/send_join` response is only required when the event is signed by the resident server. ([#1834](https://github.com/matrix-org/matrix-spec/issues/1834), [#1840](https://github.com/matrix-org/matrix-spec/issues/1840))
|
||||||
|
- Replace references to RFC 7235 and RFC 7230 that are obsoleted by RFC 9110. ([#1844](https://github.com/matrix-org/matrix-spec/issues/1844))
|
||||||
|
- Fix various typos throughout the specification. ([#1877](https://github.com/matrix-org/matrix-spec/issues/1877))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify that appservices should be notified of events relating to the `sender_localpart` user. ([#1810](https://github.com/matrix-org/matrix-spec/issues/1810))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Authentication using a query string is now deprecated, as per [MSC4126](https://github.com/matrix-org/matrix-spec-proposals/issues/4126). The `Authorization` header should be used instead. ([#1808](https://github.com/matrix-org/matrix-spec/issues/1808))
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify that redaction events are still subject to all applicable auth rules. ([#1824](https://github.com/matrix-org/matrix-spec/issues/1824))
|
||||||
|
- Fix various typos throughout the specification. ([#1827](https://github.com/matrix-org/matrix-spec/issues/1827), [#1848](https://github.com/matrix-org/matrix-spec/issues/1848))
|
||||||
|
- Fix the rendering of the event format for room versions 1 and 2. ([#1883](https://github.com/matrix-org/matrix-spec/issues/1883))
|
||||||
|
- Generate the Table of Contents with Hugo rather than JavaScript. ([#1884](https://github.com/matrix-org/matrix-spec/issues/1884))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Deprecate linking to events in rooms identified by alias, as per [MSC4132](https://github.com/matrix-org/matrix-spec-proposals/pull/4132). ([#1823](https://github.com/matrix-org/matrix-spec/issues/1823))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Define 'Opaque Identifier Grammar'. ([#1791](https://github.com/matrix-org/matrix-spec/issues/1791))
|
||||||
|
- Define common cryptographic key representation. ([#1819](https://github.com/matrix-org/matrix-spec/issues/1819))
|
||||||
|
- Move size limits for user, room and event IDs into the appendix and clarify that the length is to be measured in bytes. ([#1850](https://github.com/matrix-org/matrix-spec/issues/1850))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Update the spec release process and related documentation. ([#1759](https://github.com/matrix-org/matrix-spec/issues/1759))
|
||||||
|
- Fix npm release script for `@matrix-org/spec`. ([#1765](https://github.com/matrix-org/matrix-spec/issues/1765))
|
||||||
|
- Formatting fixes in `CONTRIBUTING.rst`. ([#1769](https://github.com/matrix-org/matrix-spec/issues/1769))
|
||||||
|
- Improve rendering on mobile devices. ([#1770](https://github.com/matrix-org/matrix-spec/issues/1770), [#1771](https://github.com/matrix-org/matrix-spec/issues/1771))
|
||||||
|
- Fix the OpenAPI definition of the security schemes. ([#1772](https://github.com/matrix-org/matrix-spec/issues/1772))
|
||||||
|
- Simplify uses of `resolve-refs` partial. ([#1773](https://github.com/matrix-org/matrix-spec/issues/1773))
|
||||||
|
- Fix Hugo warnings. ([#1775](https://github.com/matrix-org/matrix-spec/issues/1775), [#1788](https://github.com/matrix-org/matrix-spec/issues/1788))
|
||||||
|
- Fix `github-labels.rst`. ([#1781](https://github.com/matrix-org/matrix-spec/issues/1781))
|
||||||
|
- Update dependencies. ([#1786](https://github.com/matrix-org/matrix-spec/issues/1786), [#1803](https://github.com/matrix-org/matrix-spec/issues/1803), [#1804](https://github.com/matrix-org/matrix-spec/issues/1804))
|
||||||
|
- Solve `allOf` recursively in OpenAPI and JSON Schemas. ([#1787](https://github.com/matrix-org/matrix-spec/issues/1787))
|
||||||
|
- Fix property type resolution in `render-object-table` partial. ([#1789](https://github.com/matrix-org/matrix-spec/issues/1789))
|
||||||
|
- Factor out common definition of `Tag` type. ([#1793](https://github.com/matrix-org/matrix-spec/issues/1793))
|
||||||
|
- Update the version of Hugo used to render the spec to v0.124.1. ([#1794](https://github.com/matrix-org/matrix-spec/issues/1794))
|
||||||
|
- Add support for pattern formats for `patternProperties`. ([#1796](https://github.com/matrix-org/matrix-spec/issues/1796))
|
||||||
|
- Clean up unnecessary `allOf`s in OpenAPI definitions. ([#1797](https://github.com/matrix-org/matrix-spec/issues/1797))
|
||||||
|
- Show information about "Additional Properties" in object tables. ([#1798](https://github.com/matrix-org/matrix-spec/issues/1798))
|
||||||
|
- Fix anchors for schemas under `oneOf`. ([#1799](https://github.com/matrix-org/matrix-spec/issues/1799))
|
||||||
|
- Use reference to `OneTimeKeys` schema in OpenAPI definitions. ([#1800](https://github.com/matrix-org/matrix-spec/issues/1800))
|
||||||
|
- Do not use the `title` of objects containing only `additionalProperties` or `patternProperties`. ([#1801](https://github.com/matrix-org/matrix-spec/issues/1801))
|
||||||
|
- Add anchors in `definition` shortcode. ([#1802](https://github.com/matrix-org/matrix-spec/issues/1802))
|
||||||
|
- Set python version for the Towncrier CI job. ([#1805](https://github.com/matrix-org/matrix-spec/issues/1805))
|
||||||
|
- Replace `set-output` with environment files in CI. ([#1806](https://github.com/matrix-org/matrix-spec/issues/1806))
|
||||||
|
- Render response headers. ([#1809](https://github.com/matrix-org/matrix-spec/issues/1809))
|
||||||
|
- Use `patternProperties` in more places with supported formats. ([#1813](https://github.com/matrix-org/matrix-spec/issues/1813))
|
||||||
|
- Add support for rendering string formats. ([#1814](https://github.com/matrix-org/matrix-spec/issues/1814))
|
||||||
|
- Refactor the OpenAPI definitions of the content repository endpoints. ([#1822](https://github.com/matrix-org/matrix-spec/issues/1822))
|
||||||
|
- Clean up pull request template. ([#1831](https://github.com/matrix-org/matrix-spec/issues/1831))
|
||||||
|
- Do not add empty arrays to examples. ([#1849](https://github.com/matrix-org/matrix-spec/issues/1849))
|
||||||
|
- Generate the Table of Contents with Hugo rather than JavaScript. ([#1851](https://github.com/matrix-org/matrix-spec/issues/1851), [#1885](https://github.com/matrix-org/matrix-spec/issues/1885))
|
||||||
|
- Fix syntax errors in the spec release issue template. ([#1856](https://github.com/matrix-org/matrix-spec/issues/1856))
|
||||||
|
- Use environment variables for Netlify build job. ([#1865](https://github.com/matrix-org/matrix-spec/issues/1865))
|
||||||
|
- Render added/changed in info on request and response content types. ([#1876](https://github.com/matrix-org/matrix-spec/issues/1876))
|
||||||
|
- Fix validation errors in generated HTML. ([#1880](https://github.com/matrix-org/matrix-spec/issues/1880))
|
||||||
|
- Ensure most generated HTML IDs are unique. ([#1881](https://github.com/matrix-org/matrix-spec/issues/1881))
|
||||||
|
- Allow to specify a prefix for generated HTML IDs of API endpoints. ([#1882](https://github.com/matrix-org/matrix-spec/issues/1882))
|
||||||
113
content/changelog/v1.12.md
Normal file
113
content/changelog/v1.12.md
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
title: v1.12 Changelog
|
||||||
|
linkTitle: v1.12
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2024-10-07
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Deprecate the `server_name` query parameter on `POST /_matrix/client/v3/join/{roomIdOrAlias}` and `POST /_matrix/client/v3/knock/{roomIdOrAlias}`, as per [MSC4156](https://github.com/matrix-org/matrix-spec-proposals/pull/4156). ([#1933](https://github.com/matrix-org/matrix-spec/issues/1933))
|
||||||
|
|
||||||
|
**Removed Endpoints**
|
||||||
|
|
||||||
|
- Remove references to device-specific push rules. ([#1842](https://github.com/matrix-org/matrix-spec/issues/1842))
|
||||||
|
- Remove the deprecated name attribute on HTML anchor elements, as per [MSC4159](https://github.com/matrix-org/matrix-spec-proposals/pull/4159). ([#1870](https://github.com/matrix-org/matrix-spec/issues/1870))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add 403 responses on `GET /_matrix/client/v3/profile/{userId}/avatar_url` and `GET /_matrix/client/v3/profile/{userId}/displayname`, as per [MSC4170](https://github.com/matrix-org/matrix-spec-proposals/pull/4170). ([#1867](https://github.com/matrix-org/matrix-spec/issues/1867))
|
||||||
|
- Add support for marking rooms as unread, as per [MSC2867](https://github.com/matrix-org/matrix-spec-proposals/pull/2867). ([#1895](https://github.com/matrix-org/matrix-spec/issues/1895), [#1941](https://github.com/matrix-org/matrix-spec/issues/1941))
|
||||||
|
- Add `via` query parameter on `POST /_matrix/client/v3/join/{roomIdOrAlias}` and `POST /_matrix/client/v3/knock/{roomIdOrAlias}`, as per [MSC4156](https://github.com/matrix-org/matrix-spec-proposals/pull/4156). ([#1933](https://github.com/matrix-org/matrix-spec/issues/1933))
|
||||||
|
- Add account locking, as per [MSC3939](https://github.com/matrix-org/matrix-spec-proposals/pull/3939). ([#1934](https://github.com/matrix-org/matrix-spec/issues/1934))
|
||||||
|
- Guest accounts can now download/thumbnail media from the new authenticated endpoints, as per [MSC4189](https://github.com/matrix-org/matrix-spec-proposals/pull/4189). ([#1959](https://github.com/matrix-org/matrix-spec/issues/1959))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Rename and sort the modules in the feature profiles table for easier skimming. ([#1855](https://github.com/matrix-org/matrix-spec/issues/1855))
|
||||||
|
- Clarify that room avatars cannot be encrypted. ([#1871](https://github.com/matrix-org/matrix-spec/issues/1871))
|
||||||
|
- Document the acronyms and alternate names for the "Secrets" section. ([#1875](https://github.com/matrix-org/matrix-spec/issues/1875))
|
||||||
|
- Improve recommendation for how to form transaction IDs. ([#1888](https://github.com/matrix-org/matrix-spec/issues/1888))
|
||||||
|
- Clarify that the deprecated `dont_notify` and `coalesce` push rule actions MUST be ignored, not rejected. ([#1890](https://github.com/matrix-org/matrix-spec/issues/1890))
|
||||||
|
- Fix various typos throughout the specification. ([#1892](https://github.com/matrix-org/matrix-spec/issues/1892))
|
||||||
|
- Add missing references to `m.set_displayname`, `m.set_avatar_url`, and `m.3pid_changes` in capabilities table. ([#1897](https://github.com/matrix-org/matrix-spec/issues/1897))
|
||||||
|
- Clarify that the fallback login page calls `window.matrixLogin.onLogin` instead of `window.onLogin`. ([#1899](https://github.com/matrix-org/matrix-spec/issues/1899))
|
||||||
|
- Remove confusing description of restricted rooms with no valid conditions. ([#1903](https://github.com/matrix-org/matrix-spec/issues/1903))
|
||||||
|
- Clarify that `window.matrixLogin.onLogin` is called with the response body of `POST /_matrix/client/v3/login`. ([#1905](https://github.com/matrix-org/matrix-spec/issues/1905))
|
||||||
|
- Document the `m.get_login_token` capability, as per [MSC3882](https://github.com/matrix-org/matrix-spec-proposals/pull/3882). ([#1908](https://github.com/matrix-org/matrix-spec/issues/1908))
|
||||||
|
- Clarify that the `User identifier` object in `POST /_matrix/client/v3/login` contains additional properties that depend on the identification type. ([#1909](https://github.com/matrix-org/matrix-spec/issues/1909))
|
||||||
|
- Don't mention that `GET /_matrix/client/v3/profile/{userId}` can return additional properties because this is true for almost every endpoint. ([#1910](https://github.com/matrix-org/matrix-spec/issues/1910))
|
||||||
|
- Improve wording of the unauthenticated media deprecation box. Contributed by @HarHarLinks. ([#1916](https://github.com/matrix-org/matrix-spec/issues/1916))
|
||||||
|
- Additional properties in `GET /.well-known/matrix/client` don't have to be objects. ([#1920](https://github.com/matrix-org/matrix-spec/issues/1920))
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
- Specify `Content-Type` and `Content-Disposition` usage in the media repo, as per [MSC2701](https://github.com/matrix-org/matrix-spec-proposals/pull/2701) and [MSC2702](https://github.com/matrix-org/matrix-spec-proposals/pull/2702). ([#1935](https://github.com/matrix-org/matrix-spec/issues/1935))
|
||||||
|
- Additional keys in `GET /_matrix/client/v3/capabilities` don't have to be objects. ([#1945](https://github.com/matrix-org/matrix-spec/issues/1945))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add 403 response on `GET /_matrix/federation/v1/query/profile`, as per [MSC4170](https://github.com/matrix-org/matrix-spec-proposals/pull/4170). ([#1867](https://github.com/matrix-org/matrix-spec/issues/1867))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Remove `origin` field from PDU example because it doesn't exist in the schema anymore. ([#1918](https://github.com/matrix-org/matrix-spec/issues/1918))
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
- Fix required fields in `GET /_matrix/key/v2/server` response schema. ([#1930](https://github.com/matrix-org/matrix-spec/issues/1930))
|
||||||
|
- Use "server name" instead of "DNS name" to avoid confusion with the "DNS name" component of "server names" as defined in the appendices. ([#1946](https://github.com/matrix-org/matrix-spec/issues/1946))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Fix a formatting issue in state resolution v2. ([#1896](https://github.com/matrix-org/matrix-spec/issues/1896))
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- The Matrix.org Foundation no longer requires "real" or "legally identifiable" names in order to contribute to projects. ([#1886](https://github.com/matrix-org/matrix-spec/issues/1886), [#1914](https://github.com/matrix-org/matrix-spec/issues/1914))
|
||||||
|
- Document the `removal` changelog category. ([#1907](https://github.com/matrix-org/matrix-spec/issues/1907))
|
||||||
|
- Use dedicated fonts for better support of mathematical symbols. ([#1919](https://github.com/matrix-org/matrix-spec/issues/1919))
|
||||||
|
- Document that the spec uses [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119) keywords. Contributed by @HarHarLinks. ([#1928](https://github.com/matrix-org/matrix-spec/issues/1928))
|
||||||
|
- Provide markdown checklists for changelogs under `/changelog/$VERSION/checklist.md`. ([#1937](https://github.com/matrix-org/matrix-spec/issues/1937), [#1954](https://github.com/matrix-org/matrix-spec/issues/1954))
|
||||||
|
- Add the `deprecated` field to properties of OpenAPI definitions and JSON Schemas. ([#1940](https://github.com/matrix-org/matrix-spec/issues/1940))
|
||||||
|
- Use relative permalink to redirect to latest changelog. ([#1956](https://github.com/matrix-org/matrix-spec/issues/1956))
|
||||||
108
content/changelog/v1.13.md
Normal file
108
content/changelog/v1.13.md
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
---
|
||||||
|
title: v1.13 Changelog
|
||||||
|
linkTitle: v1.13
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2024-12-19
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**New Endpoints**
|
||||||
|
|
||||||
|
- Add `POST /_matrix/client/v3/rooms/{roomId}/report`, as per [MSC4151](https://github.com/matrix-org/matrix-spec-proposals/pull/4151). ([#1938](https://github.com/matrix-org/matrix-spec/issues/1938), [#2028](https://github.com/matrix-org/matrix-spec/issues/2028))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add error codes to requestToken endpoints, as per [MSC4178](https://github.com/matrix-org/matrix-spec-proposals/pull/4178). ([#1944](https://github.com/matrix-org/matrix-spec/issues/1944))
|
||||||
|
- Remove reply fallbacks, as per [MSC2781](https://github.com/matrix-org/matrix-spec-proposals/issues/2781). ([#1994](https://github.com/matrix-org/matrix-spec/issues/1994))
|
||||||
|
- Clarify the allowed HTTP methods in CORS responses, as per [MSC4138](https://github.com/matrix-org/matrix-spec-proposals/pull/4138). ([#1995](https://github.com/matrix-org/matrix-spec/issues/1995), [#2011](https://github.com/matrix-org/matrix-spec/issues/2011))
|
||||||
|
- Add new `M_USER_SUSPENDED` error code behaviour, as per [MSC3823](https://github.com/matrix-org/matrix-spec-proposals/pull/3823). ([#2014](https://github.com/matrix-org/matrix-spec/issues/2014))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- The `reason` parameter in `POST /_matrix/client/v3/rooms/{roomId}/report/{eventId}` can be omitted instead of left blank, as per [MSC2414](https://github.com/matrix-org/matrix-spec-proposals/pull/2414). ([#1938](https://github.com/matrix-org/matrix-spec/issues/1938))
|
||||||
|
- Correct OpenAPI specification for query parameters to `GET /_matrix/client/v3/thirdparty/location/{protocol}` endpoint. ([#1947](https://github.com/matrix-org/matrix-spec/issues/1947))
|
||||||
|
- Sort VoIP events semantically. ([#1967](https://github.com/matrix-org/matrix-spec/issues/1967))
|
||||||
|
- Clarify that servers must forward custom keys in `PusherData` when sending notifications to the push gateway. ([#1973](https://github.com/matrix-org/matrix-spec/issues/1973))
|
||||||
|
- Clarify formats of string types. ([#1978](https://github.com/matrix-org/matrix-spec/issues/1978), [#1979](https://github.com/matrix-org/matrix-spec/issues/1979), [#1980](https://github.com/matrix-org/matrix-spec/issues/1980))
|
||||||
|
- Clarify that the async upload endpoint will return 404 in some cases. ([#1983](https://github.com/matrix-org/matrix-spec/issues/1983))
|
||||||
|
- Remove distinction between `StateFilter` and `RoomEventFilter`. ([#2015](https://github.com/matrix-org/matrix-spec/issues/2015))
|
||||||
|
- Add hyperlinks throughout the specification. ([#2016](https://github.com/matrix-org/matrix-spec/issues/2016))
|
||||||
|
- Use `json` instead of `json5` for syntax highlighting. ([#2017](https://github.com/matrix-org/matrix-spec/issues/2017))
|
||||||
|
- Specify order that one-time keys are issued by `/keys/claim`, as per [MSC4225](https://github.com/matrix-org/matrix-spec-proposals/pull/4225). ([#2029](https://github.com/matrix-org/matrix-spec/issues/2029))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Make ACLs apply to EDUs, as per [MSC4163](https://github.com/matrix-org/matrix-spec-proposals/pull/4163). ([#2004](https://github.com/matrix-org/matrix-spec/issues/2004))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Add 403 error response to `/_matrix/federation/v1/state_ids/{roomId}`. ([#1926](https://github.com/matrix-org/matrix-spec/issues/1926))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Allow sending ephemeral data to application services, as per [MSC2409](https://github.com/matrix-org/matrix-spec-proposals/pull/2409). ([#2018](https://github.com/matrix-org/matrix-spec/issues/2018))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Document the schema of `PusherData`. ([#1968](https://github.com/matrix-org/matrix-spec/issues/1968))
|
||||||
|
- The path of HTTP pusher URLs is fixed to `/_matrix/push/v1/notify`. ([#1974](https://github.com/matrix-org/matrix-spec/issues/1974))
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify rule 4.3.1 of the auth rules in room version 11 to state which event's `sender` the `state_key` needs to match. ([#2024](https://github.com/matrix-org/matrix-spec/issues/2024))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Remove note about reference implementations. ([#1966](https://github.com/matrix-org/matrix-spec/issues/1966))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Add `x-weight` property for sorting events rendered with the `event-group` shortcode. ([#1967](https://github.com/matrix-org/matrix-spec/issues/1967))
|
||||||
|
- Enforce consistent vertical spacing between paragraphs in endpoint definitions. ([#1969](https://github.com/matrix-org/matrix-spec/issues/1969), [#2005](https://github.com/matrix-org/matrix-spec/issues/2005))
|
||||||
|
- Remove `boxes/added-in-paragraph` shortcode. ([#1970](https://github.com/matrix-org/matrix-spec/issues/1970))
|
||||||
|
- Remove `withVersioning` parameter of `rver-fragment` shortcode. ([#1971](https://github.com/matrix-org/matrix-spec/issues/1971))
|
||||||
|
- Remove `span` element from `added-in` and `changed-in` shortcodes. ([#1972](https://github.com/matrix-org/matrix-spec/issues/1972))
|
||||||
|
- Fix formatting of `added-in` and `changed-in` shortcodes by using `%` delimiter. ([#1975](https://github.com/matrix-org/matrix-spec/issues/1975))
|
||||||
|
- Remove CSS workaround for scroll-anchoring. ([#1976](https://github.com/matrix-org/matrix-spec/issues/1976))
|
||||||
|
- Rename `custom-formats.yaml` to `string-formats.yaml` and update its docs. ([#1977](https://github.com/matrix-org/matrix-spec/issues/1977))
|
||||||
|
- Fix relative URLs when serving the specification with a custom `baseURL`. ([#1984](https://github.com/matrix-org/matrix-spec/issues/1984), [#1997](https://github.com/matrix-org/matrix-spec/issues/1997))
|
||||||
|
- Rename `.htmltest.yaml` to `.htmltest.yml`. ([#1985](https://github.com/matrix-org/matrix-spec/issues/1985))
|
||||||
|
- Improve the JS script to highlight the current ToC entry. ([#1991](https://github.com/matrix-org/matrix-spec/issues/1991), [#2002](https://github.com/matrix-org/matrix-spec/issues/2002))
|
||||||
|
- Upgrade docsy to 0.11.0 and hugo to 0.139.0. ([#1996](https://github.com/matrix-org/matrix-spec/issues/1996), [#2007](https://github.com/matrix-org/matrix-spec/issues/2007))
|
||||||
|
- Improve the quality of the rendered diagrams ([#1999](https://github.com/matrix-org/matrix-spec/issues/1999))
|
||||||
|
- Update the Inter font and allow the browser to render the page before it is loaded ([#2000](https://github.com/matrix-org/matrix-spec/issues/2000))
|
||||||
|
- Use a proper Matrix favicon ([#2001](https://github.com/matrix-org/matrix-spec/issues/2001))
|
||||||
|
- Clean up unused CSS classes in `openapi/render-operation` partial. ([#2003](https://github.com/matrix-org/matrix-spec/issues/2003))
|
||||||
|
- Fix `changed-in` partial when used with multiple paragraphs. ([#2006](https://github.com/matrix-org/matrix-spec/issues/2006))
|
||||||
|
- Optimize generated CSS by removing unused selectors. ([#2008](https://github.com/matrix-org/matrix-spec/issues/2008))
|
||||||
|
- Remove trailing slash on void HTML elements. ([#2009](https://github.com/matrix-org/matrix-spec/issues/2009))
|
||||||
|
- Remove `type` and `language` attributes of `script` element. ([#2021](https://github.com/matrix-org/matrix-spec/issues/2021))
|
||||||
|
- Change the accessible role of info boxes to `note`. ([#2022](https://github.com/matrix-org/matrix-spec/issues/2022))
|
||||||
93
content/changelog/v1.14.md
Normal file
93
content/changelog/v1.14.md
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
title: v1.14 Changelog
|
||||||
|
linkTitle: v1.14
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2025-03-27
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**New Endpoints**
|
||||||
|
|
||||||
|
- Add `POST /_matrix/client/v3/users/{userId}/report`, as per [MSC4260](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). ([#2093](https://github.com/matrix-org/matrix-spec/issues/2093))
|
||||||
|
|
||||||
|
**Removed Endpoints**
|
||||||
|
|
||||||
|
- Remove `server_name` parameter from `/_matrix/client/v3/join/{roomIdOrAlias}` and `/_matrix/client/v3/knock/{roomIdOrAlias}`, as per [MSC4213](https://github.com/matrix-org/matrix-spec-proposals/pull/4213). ([#2059](https://github.com/matrix-org/matrix-spec/issues/2059))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- The `POST /_matrix/client/v3/rooms/{roomId}/initialSync` endpoint is no longer deprecated, as it is still used for peeking. ([#2036](https://github.com/matrix-org/matrix-spec/issues/2036))
|
||||||
|
- Clarify wording in the `/join` endpoints' summaries and descriptions. Contributed by @HarHarLinks. ([#2038](https://github.com/matrix-org/matrix-spec/issues/2038))
|
||||||
|
- Clarify formats of string types. ([#2046](https://github.com/matrix-org/matrix-spec/issues/2046))
|
||||||
|
- Fix various typos throughout the specification. ([#2047](https://github.com/matrix-org/matrix-spec/issues/2047), [#2048](https://github.com/matrix-org/matrix-spec/issues/2048), [#2080](https://github.com/matrix-org/matrix-spec/issues/2080), [#2091](https://github.com/matrix-org/matrix-spec/issues/2091))
|
||||||
|
- Document the `instance_id` field of `Protocol Instance` in the responses to `GET /_matrix/client/v3/thirdparty/protocols` and `GET /_matrix/client/v3/thirdparty/protocol/{protocol}`. ([#2051](https://github.com/matrix-org/matrix-spec/issues/2051))
|
||||||
|
- Applying redactions is a SHOULD for clients. ([#2055](https://github.com/matrix-org/matrix-spec/issues/2055))
|
||||||
|
- Clarify which rooms are returned from `/hierarchy`. ([#2064](https://github.com/matrix-org/matrix-spec/issues/2064))
|
||||||
|
- Clients can choose which history visibility options they offer to users when creating rooms. ([#2072](https://github.com/matrix-org/matrix-spec/issues/2072))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Remove the `origin` field in `PUT /send_join` responses, because it was never sent in the first place. ([#2050](https://github.com/matrix-org/matrix-spec/issues/2050))
|
||||||
|
- Clarify that `m.join_rules` should be in the `auth_events` of an `m.room.member` event with a `membership` of `knock`. ([#2063](https://github.com/matrix-org/matrix-spec/issues/2063))
|
||||||
|
- Remove an erroneous `room_id` field in a few examples. ([#2076](https://github.com/matrix-org/matrix-spec/issues/2076))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Update the default room version to 11, as per [MSC4239](https://github.com/matrix-org/matrix-spec-proposals/pull/4239). ([#2105](https://github.com/matrix-org/matrix-spec/issues/2105))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- For room versions 6 and 7, clarify in the authorization rules that `m.federate` must be checked and that events with rejected auth events must be rejected, for parity with all the other room versions. ([#2065](https://github.com/matrix-org/matrix-spec/issues/2065))
|
||||||
|
- Fix various typos throughout the specification. ([#2066](https://github.com/matrix-org/matrix-spec/issues/2066))
|
||||||
|
- Refactor PDU definitions to reduce duplication. ([#2070](https://github.com/matrix-org/matrix-spec/issues/2070))
|
||||||
|
- Clarify the maximum `depth` value for room versions 6, 7, 8, 9, 10, and 11. ([#2114](https://github.com/matrix-org/matrix-spec/issues/2114))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify that arbitrary unicode is allowed in user/room IDs and room aliases. ([#1506](https://github.com/matrix-org/matrix-spec/issues/1506))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Generate the changelog release info with Hugo, rather than the changelog generation script. ([#2033](https://github.com/matrix-org/matrix-spec/issues/2033))
|
||||||
|
- Update release steps documentation. ([#2041](https://github.com/matrix-org/matrix-spec/issues/2041))
|
||||||
|
- Remove unused `release_date` from Hugo config. ([#2042](https://github.com/matrix-org/matrix-spec/issues/2042))
|
||||||
|
- Clarify that v1.0 of Matrix was a release prior to the current global versioning system. ([#2045](https://github.com/matrix-org/matrix-spec/issues/2045))
|
||||||
|
- Fix syntax highlighting and click-to-copy buttons for code blocks by purging less CSS. ([#2049](https://github.com/matrix-org/matrix-spec/issues/2049))
|
||||||
|
- Fix the version of the Identity Service API when Matrix 1.0 was introduced. ([#2061](https://github.com/matrix-org/matrix-spec/issues/2061))
|
||||||
|
- Fix parsing of nested slices in `resolve-refs` and `resolve-allof` partials. ([#2069](https://github.com/matrix-org/matrix-spec/issues/2069))
|
||||||
|
- Deduplicate the definition of `RoomKeysUpdateResponse`. ([#2073](https://github.com/matrix-org/matrix-spec/issues/2073))
|
||||||
|
- Deduplicate the definitions of `Invite3pid`. ([#2074](https://github.com/matrix-org/matrix-spec/issues/2074))
|
||||||
|
- Support more locations for examples in OpenAPI definitions and JSON schemas. ([#2076](https://github.com/matrix-org/matrix-spec/issues/2076))
|
||||||
|
- Add link to the git commit for the unstable changelog. ([#2078](https://github.com/matrix-org/matrix-spec/issues/2078))
|
||||||
97
content/changelog/v1.15.md
Normal file
97
content/changelog/v1.15.md
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
---
|
||||||
|
title: v1.15 Changelog
|
||||||
|
linkTitle: v1.15
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2025-06-26
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**New Endpoints**
|
||||||
|
|
||||||
|
- Add `GET /_matrix/client/v1/room_summary/{roomIdOrAlias}`, as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125))
|
||||||
|
- Add `GET /_matrix/client/v1/auth_metadata`, as per [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965). ([#2147](https://github.com/matrix-org/matrix-spec/issues/2147))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). ([#2095](https://github.com/matrix-org/matrix-spec/issues/2095))
|
||||||
|
- Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147). ([#2122](https://github.com/matrix-org/matrix-spec/issues/2122))
|
||||||
|
- Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125), [#2158](https://github.com/matrix-org/matrix-spec/issues/2158))
|
||||||
|
- Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. ([#2141](https://github.com/matrix-org/matrix-spec/issues/2141), [#2148](https://github.com/matrix-org/matrix-spec/issues/2148), [#2149](https://github.com/matrix-org/matrix-spec/issues/2149), [#2150](https://github.com/matrix-org/matrix-spec/issues/2150), [#2151](https://github.com/matrix-org/matrix-spec/issues/2151), [#2159](https://github.com/matrix-org/matrix-spec/issues/2159), [#2164](https://github.com/matrix-org/matrix-spec/issues/2164))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify behaviour when the `topic` key of a `m.room.topic` event is absent, null, or empty. ([#2068](https://github.com/matrix-org/matrix-spec/issues/2068))
|
||||||
|
- Fix the example of the `GET /sync` endpoint and the `m.room.member` example used in several places. ([#2077](https://github.com/matrix-org/matrix-spec/issues/2077))
|
||||||
|
- Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083))
|
||||||
|
- "Public" rooms in profile look-ups are defined through their join rule and history visibility. ([#2101](https://github.com/matrix-org/matrix-spec/issues/2101))
|
||||||
|
- "Public" rooms in user directory queries are defined through their join rule and history visibility. ([#2102](https://github.com/matrix-org/matrix-spec/issues/2102))
|
||||||
|
- Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. ([#2104](https://github.com/matrix-org/matrix-spec/issues/2104))
|
||||||
|
- "Public" rooms with respect to call invites are defined through their join rule. ([#2106](https://github.com/matrix-org/matrix-spec/issues/2106))
|
||||||
|
- "Public" rooms have no specific meaning with respect to moderation policy lists. ([#2107](https://github.com/matrix-org/matrix-spec/issues/2107))
|
||||||
|
- "Public" rooms with respect to presence are defined through their join rule. ([#2108](https://github.com/matrix-org/matrix-spec/issues/2108))
|
||||||
|
- Spaces are subject to the same access mechanisms as rooms. ([#2109](https://github.com/matrix-org/matrix-spec/issues/2109))
|
||||||
|
- Fix various typos throughout the specification. ([#2121](https://github.com/matrix-org/matrix-spec/issues/2121), [#2144](https://github.com/matrix-org/matrix-spec/issues/2144))
|
||||||
|
- Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. ([#2140](https://github.com/matrix-org/matrix-spec/issues/2140))
|
||||||
|
- Add missing fields in example for `ExportedSessionData`. ([#2154](https://github.com/matrix-org/matrix-spec/issues/2154))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). ([#2095](https://github.com/matrix-org/matrix-spec/issues/2095))
|
||||||
|
- Extend `/_matrix/federation/v1/hierarchy/{roomId}` with the new optional properties `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room. ([#2067](https://github.com/matrix-org/matrix-spec/issues/2067))
|
||||||
|
- Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083))
|
||||||
|
- Clarify that auth event of `content.join_authorised_via_users_server` is only necessary for `m.room.member` with a `membership` of `join`. ([#2100](https://github.com/matrix-org/matrix-spec/issues/2100))
|
||||||
|
- Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. ([#2104](https://github.com/matrix-org/matrix-spec/issues/2104))
|
||||||
|
- Fix various typos throughout the specification. ([#2128](https://github.com/matrix-org/matrix-spec/issues/2128))
|
||||||
|
- Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. ([#2140](https://github.com/matrix-org/matrix-spec/issues/2140))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify in the application service registration schema the `url: null` behaviour. ([#2130](https://github.com/matrix-org/matrix-spec/issues/2130))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify that public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083))
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Adjust margins in rendered endpoints. ([#2081](https://github.com/matrix-org/matrix-spec/issues/2081))
|
||||||
|
- Replace Hugo shortcodes in OpenAPI output. ([#2088](https://github.com/matrix-org/matrix-spec/issues/2088))
|
||||||
|
- Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks. ([#2115](https://github.com/matrix-org/matrix-spec/issues/2115))
|
||||||
|
- Fix the historical info box when generating the historical spec in CI. ([#2123](https://github.com/matrix-org/matrix-spec/issues/2123))
|
||||||
|
- Update the header navigation menu with links to modern matrix.org. Contributed by @HarHarLinks. ([#2137](https://github.com/matrix-org/matrix-spec/issues/2137))
|
||||||
103
content/changelog/v1.16.md
Normal file
103
content/changelog/v1.16.md
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
title: v1.16 Changelog
|
||||||
|
linkTitle: v1.16
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2025-09-17
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Deprecate `m.set_avatar_url` and `m.set_displayname` capabilities, as per [MSC4133](https://github.com/matrix-org/matrix-spec-proposals/pull/4133). ([#2071](https://github.com/matrix-org/matrix-spec/issues/2071))
|
||||||
|
|
||||||
|
**Removed Endpoints**
|
||||||
|
|
||||||
|
- Remove unintentional intentional mentions in replies, as per [MSC4142](https://github.com/matrix-org/matrix-spec-proposals/pull/4142). ([#2210](https://github.com/matrix-org/matrix-spec/issues/2210))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Update user profile endpoints to handle custom fields, and add a new `m.profile_fields` capability, as per [MSC4133](https://github.com/matrix-org/matrix-spec-proposals/pull/4133). ([#2071](https://github.com/matrix-org/matrix-spec/issues/2071))
|
||||||
|
- Add `format` query parameter to `GET /state/{eventType}/{stateKey}` to allow fetching metadata of a specific state event. ([#2175](https://github.com/matrix-org/matrix-spec/issues/2175))
|
||||||
|
- Add the `use_state_after` query parameter and `state_after` response property to `GET /sync`, as per [MSC4222](https://github.com/matrix-org/matrix-spec-proposals/issues/4222). ([#2187](https://github.com/matrix-org/matrix-spec/issues/2187))
|
||||||
|
- When upgrading rooms to [room version 12](/rooms/v12), `additional_creators` may be specified on the [`POST /_matrix/client/v3/rooms/{roomId}/upgrade`](/client-server-api/#post_matrixclientv3roomsroomidupgrade) endpoint, as per [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- When creating rooms with [room version 12](/rooms/v12), the `trusted_private_chat` preset should merge the invitees into the supplied `content.additional_creators` in the resulting room, as per [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- In [room version 12](/rooms/v12), the power level of room creators is now infinitely high as per [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- In [room version 12](/rooms/v12), room IDs no longer have a domain component as per [MSC4291](https://github.com/matrix-org/matrix-spec-proposals/pull/4291). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- When creating rooms with [room version 12](/rooms/v12), the initial power levels will restrict the ability to upgrade rooms by default, as per [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- Add a profile field for a user's time zone, as per [MSC4175](https://github.com/matrix-org/matrix-spec-proposals/pull/4175). ([#2206](https://github.com/matrix-org/matrix-spec/issues/2206))
|
||||||
|
- Invites and knocks are now expected to contain the `m.room.create` event in their stripped state entries, as per [MSC4311](https://github.com/matrix-org/matrix-spec-proposals/pull/4311). ([#2207](https://github.com/matrix-org/matrix-spec/issues/2207))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify that `format` is required if `formatted_body` is specified. ([#2167](https://github.com/matrix-org/matrix-spec/issues/2167))
|
||||||
|
- The `latest_event` in an aggregated set of thread events uses the same format as the event itself. ([#2169](https://github.com/matrix-org/matrix-spec/issues/2169))
|
||||||
|
- Fix various typos throughout the specification. ([#2171](https://github.com/matrix-org/matrix-spec/issues/2171), [#2177](https://github.com/matrix-org/matrix-spec/issues/2177), [#2179](https://github.com/matrix-org/matrix-spec/issues/2179))
|
||||||
|
- Clarify that clients should replace events with the most recent replacement by `origin_server_ts`. ([#2190](https://github.com/matrix-org/matrix-spec/issues/2190))
|
||||||
|
- Fix `/sync` flow referencing incorrect parameter to use with `/messages`. ([#2195](https://github.com/matrix-org/matrix-spec/issues/2195))
|
||||||
|
- Clarify wording around the `world_readable` history visibility setting. Contributed by @HarHarLinks. ([#2204](https://github.com/matrix-org/matrix-spec/issues/2204))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- `invite_room_state` and `knock_room_state` now have additional requirements and validation depending on the room version, as per [MSC4311](https://github.com/matrix-org/matrix-spec-proposals/pull/4311). ([#2207](https://github.com/matrix-org/matrix-spec/issues/2207))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Room IDs in room version 12 are now the event ID of the create event with the normal room ID sigil (`!`), as per [MSC4291](https://github.com/matrix-org/matrix-spec-proposals/pull/4291). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- Room creators are formalized in room version 12 and have infinitely high power level, as per [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- State Resolution is updated in room version 12 to reduce the opportunity for "state resets", as per [MSC4297](https://github.com/matrix-org/matrix-spec-proposals/pull/4297). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- The default room version is now room version 12, though servers SHOULD keep using room version 11 for a little while, as per [MSC4304](https://github.com/matrix-org/matrix-spec-proposals/pull/4304). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
- Add [room version 12](/rooms/v12) as per [MSC4304](https://github.com/matrix-org/matrix-spec-proposals/pull/4304). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193), [#2199](https://github.com/matrix-org/matrix-spec/issues/2199))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- In room versions 1 through 12, an event's `auth_events` have always needed to belong to the same room as per [MSC4307](https://github.com/matrix-org/matrix-spec-proposals/pull/4307). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Room IDs can now appear without a domain component in [room version 12](/rooms/v12), as per [MSC4291](https://github.com/matrix-org/matrix-spec-proposals/pull/4291). ([#2193](https://github.com/matrix-org/matrix-spec/issues/2193))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add "placeholder MSC" process definition. ([#2157](https://github.com/matrix-org/matrix-spec/issues/2157))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Declare the Application Service Registration schema to follow JSON Schema spec 2020-12. ([#2132](https://github.com/matrix-org/matrix-spec/issues/2132))
|
||||||
|
- Declare the event schemas to follow JSON Schema spec 2020-12. ([#2132](https://github.com/matrix-org/matrix-spec/issues/2132))
|
||||||
|
- Upgrade the docsy theme to version 0.12.0. ([#2160](https://github.com/matrix-org/matrix-spec/issues/2160))
|
||||||
|
- GitHub actions are now building the OpenAPI `spec/identity-service-api/api.json` file. ([#2172](https://github.com/matrix-org/matrix-spec/issues/2172))
|
||||||
|
- Minor fixes to JSON schemas. ([#2182](https://github.com/matrix-org/matrix-spec/issues/2182))
|
||||||
|
- Specify a correct spelling for "display name". ([#2189](https://github.com/matrix-org/matrix-spec/issues/2189))
|
||||||
|
- Fix a grammatical typo on the Matrix Spec Process documentation page. ([#2205](https://github.com/matrix-org/matrix-spec/issues/2205))
|
||||||
91
content/changelog/v1.17.md
Normal file
91
content/changelog/v1.17.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
---
|
||||||
|
title: v1.17 Changelog
|
||||||
|
linkTitle: v1.17
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2025-12-18
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Removed Endpoints**
|
||||||
|
|
||||||
|
- Remove legacy mentions, as per [MSC4210](https://github.com/matrix-org/matrix-spec-proposals/issues/4210). ([#2186](https://github.com/matrix-org/matrix-spec/issues/2186))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Allow application services to masquerade as specific devices belonging to users, as per [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326). ([#2221](https://github.com/matrix-org/matrix-spec/issues/2221))
|
||||||
|
- Add the `m.oauth` authentication type for User-Interactive Authentication, as per [MSC4312](https://github.com/matrix-org/matrix-spec-proposals/pull/4312). ([#2234](https://github.com/matrix-org/matrix-spec/issues/2234))
|
||||||
|
- Allow application services to manage devices and register users without the legacy authentication API, as per [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190). ([#2267](https://github.com/matrix-org/matrix-spec/issues/2267))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Push rule IDs are globally unique within their kind. ([#2214](https://github.com/matrix-org/matrix-spec/issues/2214))
|
||||||
|
- Don't advertise `creator` field in description of room creation. ([#2215](https://github.com/matrix-org/matrix-spec/issues/2215))
|
||||||
|
- `room_id` is required for peeking via `/_matrix/client/v3/events`. ([#2216](https://github.com/matrix-org/matrix-spec/issues/2216))
|
||||||
|
- The `server-name` segment of MXC URIs is sanitised differently from the `media-id` segment. ([#2217](https://github.com/matrix-org/matrix-spec/issues/2217))
|
||||||
|
- Add note to each endpoint that uses capability negotiation. ([#2223](https://github.com/matrix-org/matrix-spec/issues/2223))
|
||||||
|
- Additional OpenGraph properties can be present in URL previews. ([#2225](https://github.com/matrix-org/matrix-spec/issues/2225))
|
||||||
|
- Clarify the special casing of membership events and redactions in power levels. ([#2231](https://github.com/matrix-org/matrix-spec/issues/2231))
|
||||||
|
- `M_RESOURCE_LIMIT_EXCEEDED` is now listed as a common error code. ([#2232](https://github.com/matrix-org/matrix-spec/issues/2232))
|
||||||
|
- Add `m.login.terms` to enumeration of authentication types. ([#2233](https://github.com/matrix-org/matrix-spec/issues/2233))
|
||||||
|
- Clarify how to use `state_after` ahead of declaring full support for its spec version. ([#2240](https://github.com/matrix-org/matrix-spec/issues/2240))
|
||||||
|
- `device_one_time_keys_count` is only optional if no unclaimed one-time keys exist. ([#2245](https://github.com/matrix-org/matrix-spec/issues/2245))
|
||||||
|
- Clarify that servers may choose not to use `M_USER_DEACTIVATED` at login time, for example for privacy reasons when they can't authenticate deactivated users. ([#2246](https://github.com/matrix-org/matrix-spec/issues/2246))
|
||||||
|
- Usage of the `event_id_only` format for push notifications is not mandatory. ([#2255](https://github.com/matrix-org/matrix-spec/issues/2255))
|
||||||
|
- Fix various typos throughout the specification. ([#2224](https://github.com/matrix-org/matrix-spec/issues/2224), [#2227](https://github.com/matrix-org/matrix-spec/issues/2227), [#2250](https://github.com/matrix-org/matrix-spec/issues/2250))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Allow application services to masquerade as specific devices belonging to users, as per [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326). ([#2221](https://github.com/matrix-org/matrix-spec/issues/2221))
|
||||||
|
- Allow application services to manage devices and register users without the legacy authentication API, as per [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190). ([#2267](https://github.com/matrix-org/matrix-spec/issues/2267))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Fix JSON formatting in the "Server admin style permissions" examples. ([#2213](https://github.com/matrix-org/matrix-spec/issues/2213))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- In room versions 8 through 12, clarify that "sufficient permission to invite users" on restricted joins also includes being a joined member of the room. ([#2220](https://github.com/matrix-org/matrix-spec/issues/2220))
|
||||||
|
- In room versions 3 through 12, clarify that when you have the power to redact, it is possible to redact events that you don't have the power to send. ([#2249](https://github.com/matrix-org/matrix-spec/issues/2249))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Swapped icon for X (fka. twitter) to updated logo in footer. ([#2219](https://github.com/matrix-org/matrix-spec/issues/2219))
|
||||||
|
- Inline Olm & Megolm specifications. ([#2226](https://github.com/matrix-org/matrix-spec/issues/2226), [#2241](https://github.com/matrix-org/matrix-spec/issues/2241), [#2242](https://github.com/matrix-org/matrix-spec/issues/2242))
|
||||||
|
- Silence failing redocly-cli rule. ([#2238](https://github.com/matrix-org/matrix-spec/issues/2238))
|
||||||
|
- Use NPM Trusted Publishers for publishing `@matrix-org/spec` to npm. ([#2239](https://github.com/matrix-org/matrix-spec/issues/2239))
|
||||||
|
- Add version picker in the navbar. ([#2256](https://github.com/matrix-org/matrix-spec/issues/2256), [#2258](https://github.com/matrix-org/matrix-spec/issues/2258), [#2259](https://github.com/matrix-org/matrix-spec/issues/2259), [#2260](https://github.com/matrix-org/matrix-spec/issues/2260), [#2261](https://github.com/matrix-org/matrix-spec/issues/2261), [#2264](https://github.com/matrix-org/matrix-spec/issues/2264), [#2268](https://github.com/matrix-org/matrix-spec/issues/2268))
|
||||||
|
- Add a list of endpoints to the top of each spec page. ([#2262](https://github.com/matrix-org/matrix-spec/issues/2262))
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
---
|
---
|
||||||
date: 2022-02-02T00:00:00+0000
|
title: v1.2 Changelog
|
||||||
|
linkTitle: v1.2
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2022-02-02
|
||||||
---
|
---
|
||||||
<!--
|
|
||||||
This is a header file for the generated changelog.
|
|
||||||
|
|
||||||
Variables:
|
## Client-Server API
|
||||||
v1.2 = Replaced by the version number (eg: v1.2)
|
|
||||||
February 02, 2022 = Replaced by the date (eg: April 01, 2021)
|
|
||||||
-->
|
|
||||||
|
|
||||||
## v1.2
|
|
||||||
|
|
||||||
<table class="release-info">
|
|
||||||
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-doc/tree/v1.2">https://github.com/matrix-org/matrix-doc/tree/v1.2</a></td>
|
|
||||||
<tr><th>Release date</th><td>February 02, 2022</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
|
||||||
### Client-Server API
|
|
||||||
|
|
||||||
|
|
||||||
<strong>Breaking Changes</strong>
|
<strong>Breaking Changes</strong>
|
||||||
|
|
@ -65,7 +57,7 @@ Variables:
|
||||||
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
||||||
|
|
||||||
|
|
||||||
### Server-Server API
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
<strong>New Endpoints</strong>
|
<strong>New Endpoints</strong>
|
||||||
|
|
@ -88,7 +80,7 @@ Variables:
|
||||||
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
||||||
|
|
||||||
|
|
||||||
### Application Service API
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -99,7 +91,7 @@ Variables:
|
||||||
- Correct the documentation for the response value for `GET /_matrix/app/v1/thirdparty/protocol/{protocol}`. ([#3675](https://github.com/matrix-org/matrix-doc/issues/3675))
|
- Correct the documentation for the response value for `GET /_matrix/app/v1/thirdparty/protocol/{protocol}`. ([#3675](https://github.com/matrix-org/matrix-doc/issues/3675))
|
||||||
|
|
||||||
|
|
||||||
### Identity Service API
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -114,7 +106,7 @@ Variables:
|
||||||
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
||||||
|
|
||||||
|
|
||||||
### Push Gateway API
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -123,7 +115,7 @@ Variables:
|
||||||
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
- Fix the rendering of the responses for various API endpoints. ([#3674](https://github.com/matrix-org/matrix-doc/issues/3674))
|
||||||
|
|
||||||
|
|
||||||
### Room Versions
|
## Room Versions
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -144,7 +136,7 @@ Variables:
|
||||||
- Fix auth rules to allow membership of `knock` -> `leave` in v7, v8, and v9. ([#3694](https://github.com/matrix-org/matrix-doc/issues/3694))
|
- Fix auth rules to allow membership of `knock` -> `leave` in v7, v8, and v9. ([#3694](https://github.com/matrix-org/matrix-doc/issues/3694))
|
||||||
|
|
||||||
|
|
||||||
### Appendices
|
## Appendices
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
---
|
---
|
||||||
date: 2022-06-15T00:00:00+0100
|
title: v1.3 Changelog
|
||||||
|
linkTitle: v1.3
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2022-06-15
|
||||||
---
|
---
|
||||||
<!--
|
|
||||||
This is a header file for the generated changelog.
|
|
||||||
|
|
||||||
Variables:
|
## Client-Server API
|
||||||
v1.3 = Replaced by the version number (eg: v1.2)
|
|
||||||
June 15, 2022 = Replaced by the date (eg: April 01, 2021)
|
|
||||||
-->
|
|
||||||
|
|
||||||
## v1.3
|
|
||||||
|
|
||||||
<table class="release-info">
|
|
||||||
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/v1.3">https://github.com/matrix-org/matrix-spec/tree/v1.3</a></td>
|
|
||||||
<tr><th>Release date</th><td>June 15, 2022</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
|
||||||
### Client-Server API
|
|
||||||
|
|
||||||
|
|
||||||
<strong>Deprecations</strong>
|
<strong>Deprecations</strong>
|
||||||
|
|
@ -55,7 +47,7 @@ Variables:
|
||||||
- Fix membership state transitions to denote that `invite->knock` and `external->leave` are valid transitions. ([#3730](https://github.com/matrix-org/matrix-spec-proposals/issues/3730))
|
- Fix membership state transitions to denote that `invite->knock` and `external->leave` are valid transitions. ([#3730](https://github.com/matrix-org/matrix-spec-proposals/issues/3730))
|
||||||
|
|
||||||
|
|
||||||
### Server-Server API
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -79,7 +71,7 @@ Variables:
|
||||||
- Clarify that the `content` for `X-Matrix` signature validation is the parsed JSON body. ([#3727](https://github.com/matrix-org/matrix-spec-proposals/issues/3727))
|
- Clarify that the `content` for `X-Matrix` signature validation is the parsed JSON body. ([#3727](https://github.com/matrix-org/matrix-spec-proposals/issues/3727))
|
||||||
|
|
||||||
|
|
||||||
### Application Service API
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -88,19 +80,19 @@ Variables:
|
||||||
- Add timestamp massaging as per [MSC3316](https://github.com/matrix-org/matrix-spec-proposals/pull/3316). ([#1094](https://github.com/matrix-org/matrix-spec/issues/1094))
|
- Add timestamp massaging as per [MSC3316](https://github.com/matrix-org/matrix-spec-proposals/pull/3316). ([#1094](https://github.com/matrix-org/matrix-spec/issues/1094))
|
||||||
|
|
||||||
|
|
||||||
### Identity Service API
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
No significant changes.
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
### Push Gateway API
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
No significant changes.
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
### Room Versions
|
## Room Versions
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -124,7 +116,7 @@ No significant changes.
|
||||||
- For room versions 7, 8, 9, and 10: fix join membership authorization rules when `join_rule` is `knock`. ([#3737](https://github.com/matrix-org/matrix-spec-proposals/issues/3737))
|
- For room versions 7, 8, 9, and 10: fix join membership authorization rules when `join_rule` is `knock`. ([#3737](https://github.com/matrix-org/matrix-spec-proposals/issues/3737))
|
||||||
|
|
||||||
|
|
||||||
### Appendices
|
## Appendices
|
||||||
|
|
||||||
|
|
||||||
No significant changes.
|
No significant changes.
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
---
|
---
|
||||||
date: 2022-09-29T00:00:00+0100
|
title: v1.4 Changelog
|
||||||
|
linkTitle: v1.4
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2022-09-29
|
||||||
---
|
---
|
||||||
<!--
|
|
||||||
This is a header file for the generated changelog.
|
|
||||||
|
|
||||||
Variables:
|
## Client-Server API
|
||||||
v1.4 = Replaced by the version number (eg: v1.2)
|
|
||||||
September 29, 2022 = Replaced by the date (eg: April 01, 2021)
|
|
||||||
-->
|
|
||||||
|
|
||||||
## v1.4
|
|
||||||
|
|
||||||
<table class="release-info">
|
|
||||||
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/v1.4">https://github.com/matrix-org/matrix-spec/tree/v1.4</a></td>
|
|
||||||
<tr><th>Release date</th><td>September 29, 2022</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
|
||||||
### Client-Server API
|
|
||||||
|
|
||||||
|
|
||||||
<strong>Removed Endpoints</strong>
|
<strong>Removed Endpoints</strong>
|
||||||
|
|
@ -58,7 +50,7 @@ Variables:
|
||||||
- Clarify enum values by separating possible values with commas. ([#1240](https://github.com/matrix-org/matrix-spec/issues/1240))
|
- Clarify enum values by separating possible values with commas. ([#1240](https://github.com/matrix-org/matrix-spec/issues/1240))
|
||||||
|
|
||||||
|
|
||||||
### Server-Server API
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -75,7 +67,7 @@ Variables:
|
||||||
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
||||||
|
|
||||||
|
|
||||||
### Application Service API
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Breaking Changes</strong>
|
<strong>Breaking Changes</strong>
|
||||||
|
|
@ -90,7 +82,7 @@ Variables:
|
||||||
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
|
||||||
|
|
||||||
### Identity Service API
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -100,7 +92,7 @@ Variables:
|
||||||
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
||||||
|
|
||||||
|
|
||||||
### Push Gateway API
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -109,7 +101,7 @@ Variables:
|
||||||
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
|
||||||
|
|
||||||
### Room Versions
|
## Room Versions
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -120,13 +112,13 @@ Variables:
|
||||||
- For room versions 7 through 10: Clarify that `invite->knock` is actually a legal transition. ([#1175](https://github.com/matrix-org/matrix-spec/issues/1175))
|
- For room versions 7 through 10: Clarify that `invite->knock` is actually a legal transition. ([#1175](https://github.com/matrix-org/matrix-spec/issues/1175))
|
||||||
|
|
||||||
|
|
||||||
### Appendices
|
## Appendices
|
||||||
|
|
||||||
|
|
||||||
No significant changes.
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
### Internal Changes/Tooling
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
---
|
---
|
||||||
date: 2022-11-17T08:22:11-07:00
|
title: v1.5 Changelog
|
||||||
|
linkTitle: v1.5
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2022-11-17
|
||||||
---
|
---
|
||||||
<!--
|
|
||||||
This is a header file for the generated changelog.
|
|
||||||
|
|
||||||
Variables:
|
## Client-Server API
|
||||||
v1.5 = Replaced by the version number (eg: v1.2)
|
|
||||||
November 17, 2022 = Replaced by the date (eg: April 01, 2021)
|
|
||||||
-->
|
|
||||||
|
|
||||||
## v1.5
|
|
||||||
|
|
||||||
<table class="release-info">
|
|
||||||
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/v1.5">https://github.com/matrix-org/matrix-spec/tree/v1.5</a></td>
|
|
||||||
<tr><th>Release date</th><td>November 17, 2022</td>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
|
||||||
### Client-Server API
|
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
@ -45,7 +37,7 @@ Variables:
|
||||||
- Add example read receipt to `GET /_matrix/client/v3/sync` response example. ([#1341](https://github.com/matrix-org/matrix-spec/issues/1341))
|
- Add example read receipt to `GET /_matrix/client/v3/sync` response example. ([#1341](https://github.com/matrix-org/matrix-spec/issues/1341))
|
||||||
|
|
||||||
|
|
||||||
### Server-Server API
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -54,7 +46,7 @@ Variables:
|
||||||
- Fix a number of broken links in the specification. ([#1330](https://github.com/matrix-org/matrix-spec/issues/1330))
|
- Fix a number of broken links in the specification. ([#1330](https://github.com/matrix-org/matrix-spec/issues/1330))
|
||||||
|
|
||||||
|
|
||||||
### Application Service API
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -63,7 +55,7 @@ Variables:
|
||||||
- Clarify that application services can only register an interest in local users, as per [MSC3905](https://github.com/matrix-org/matrix-spec-proposals/issues/3905). ([#1305](https://github.com/matrix-org/matrix-spec/issues/1305))
|
- Clarify that application services can only register an interest in local users, as per [MSC3905](https://github.com/matrix-org/matrix-spec-proposals/issues/3905). ([#1305](https://github.com/matrix-org/matrix-spec/issues/1305))
|
||||||
|
|
||||||
|
|
||||||
### Identity Service API
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -72,13 +64,13 @@ Variables:
|
||||||
- Fix a number of broken links in the specification. ([#1330](https://github.com/matrix-org/matrix-spec/issues/1330))
|
- Fix a number of broken links in the specification. ([#1330](https://github.com/matrix-org/matrix-spec/issues/1330))
|
||||||
|
|
||||||
|
|
||||||
### Push Gateway API
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
No significant changes.
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
### Room Versions
|
## Room Versions
|
||||||
|
|
||||||
|
|
||||||
<strong>Spec Clarifications</strong>
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
@ -89,13 +81,13 @@ No significant changes.
|
||||||
- Fix a number of broken links in the specification. ([#1330](https://github.com/matrix-org/matrix-spec/issues/1330))
|
- Fix a number of broken links in the specification. ([#1330](https://github.com/matrix-org/matrix-spec/issues/1330))
|
||||||
|
|
||||||
|
|
||||||
### Appendices
|
## Appendices
|
||||||
|
|
||||||
|
|
||||||
No significant changes.
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
### Internal Changes/Tooling
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
|
||||||
<strong>Backwards Compatible Changes</strong>
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
|
||||||
127
content/changelog/v1.6.md
Normal file
127
content/changelog/v1.6.md
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
---
|
||||||
|
title: v1.6 Changelog
|
||||||
|
linkTitle: v1.6
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2023-02-14
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add information on standard error responses for unknown endpoints/methods, as per [MSC3743](https://github.com/matrix-org/matrix-spec-proposals/pull/3743). ([#1347](https://github.com/matrix-org/matrix-spec/issues/1347))
|
||||||
|
- Add `/rooms/<roomID>/timestamp_to_event` endpoint, as per [MSC3030](https://github.com/matrix-org/matrix-spec-proposals/pull/3030). ([#1366](https://github.com/matrix-org/matrix-spec/issues/1366))
|
||||||
|
- Define `hkdf-hmac-sha256.v2` MAC method for SAS verification, as per [MSC3783](https://github.com/matrix-org/matrix-spec-proposals/pull/3783). ([#1412](https://github.com/matrix-org/matrix-spec/issues/1412))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Clarify the power levels integer range. ([#1169](https://github.com/matrix-org/matrix-spec/issues/1169), [#1355](https://github.com/matrix-org/matrix-spec/issues/1355))
|
||||||
|
- Clarify that `/context` always returns `event` even if `limit` is zero. Contributed by @sumnerevans at @beeper. ([#1239](https://github.com/matrix-org/matrix-spec/issues/1239))
|
||||||
|
- Clarify what fields are required when deleting a pusher ([#1321](https://github.com/matrix-org/matrix-spec/issues/1321))
|
||||||
|
- Improve the presentation of push rule kinds and actions. ([#1348](https://github.com/matrix-org/matrix-spec/issues/1348))
|
||||||
|
- Add missing description to m.call.answer schema. ([#1353](https://github.com/matrix-org/matrix-spec/issues/1353))
|
||||||
|
- Fix various typos throughout the specification. ([#1363](https://github.com/matrix-org/matrix-spec/issues/1363))
|
||||||
|
- Clarify parts of the end-to-end encryption sections. ([#1381](https://github.com/matrix-org/matrix-spec/issues/1381))
|
||||||
|
- Move login API definitions to the right heading. Contributed by @HarHarLinks. ([#1382](https://github.com/matrix-org/matrix-spec/issues/1382))
|
||||||
|
- Clarify which events will be included in Stripped State. Contributed by @andybalaam. ([#1409](https://github.com/matrix-org/matrix-spec/issues/1409))
|
||||||
|
- Add links to the spec for the definition of 3PID `medium`. ([#1417](https://github.com/matrix-org/matrix-spec/issues/1417))
|
||||||
|
- Correct the order of the default override pushrules in the spec. ([#1421](https://github.com/matrix-org/matrix-spec/issues/1421))
|
||||||
|
- Improve distinction between tags and their attributes in the rich text section. Contributed by Nico. ([#1433](https://github.com/matrix-org/matrix-spec/issues/1433))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Breaking Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Remove `keyId` from the server `/keys` endpoints, as per [MSC3938](https://github.com/matrix-org/matrix-spec-proposals/pull/3938). ([#1350](https://github.com/matrix-org/matrix-spec/issues/1350))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add information on standard error responses for unknown endpoints/methods, as per [MSC3743](https://github.com/matrix-org/matrix-spec-proposals/pull/3743). ([#1347](https://github.com/matrix-org/matrix-spec/issues/1347))
|
||||||
|
- Add `/timestamp_to_event/<roomID>` endpoint, as per [MSC3030](https://github.com/matrix-org/matrix-spec-proposals/pull/3030). ([#1366](https://github.com/matrix-org/matrix-spec/issues/1366))
|
||||||
|
- Extend `/_matrix/federation/v2/send_join` to allow omitting membership events, per [MSC3706](https://github.com/matrix-org/matrix-doc/pull/3706). ([#1393](https://github.com/matrix-org/matrix-spec/issues/1393), [#1398](https://github.com/matrix-org/matrix-spec/issues/1398))
|
||||||
|
- Note that `/_matrix/federation/v2/send_join` should include heroes for nameless rooms, even when allowed to omit membership events, per [MSC3943](https://github.com/matrix-org/matrix-doc/pull/3943). ([#1425](https://github.com/matrix-org/matrix-spec/issues/1425))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Include examples inline instead of using a reference for invite endpoint definitions. ([#1349](https://github.com/matrix-org/matrix-spec/issues/1349))
|
||||||
|
- Fix `POST _matrix/federation/v1/user/keys/claim` response schema. ([#1351](https://github.com/matrix-org/matrix-spec/issues/1351))
|
||||||
|
- Correct the default invite level definition in the "Checks performed on receipt of a PDU" section. ([#1371](https://github.com/matrix-org/matrix-spec/issues/1371))
|
||||||
|
- Clarify that CNAMEs are permissible for server names. ([#1376](https://github.com/matrix-org/matrix-spec/issues/1376))
|
||||||
|
- Fix `edu_type` in EDU examples. ([#1383](https://github.com/matrix-org/matrix-spec/issues/1383))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add information on standard error responses for unknown endpoints/methods, as per [MSC3743](https://github.com/matrix-org/matrix-spec-proposals/pull/3743). ([#1347](https://github.com/matrix-org/matrix-spec/issues/1347))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add information on standard error responses for unknown endpoints/methods, as per [MSC3743](https://github.com/matrix-org/matrix-spec-proposals/pull/3743). ([#1347](https://github.com/matrix-org/matrix-spec/issues/1347))
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add information on standard error responses for unknown endpoints/methods, as per [MSC3743](https://github.com/matrix-org/matrix-spec-proposals/pull/3743). ([#1347](https://github.com/matrix-org/matrix-spec/issues/1347))
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Update the default room version to 10, as per [MSC3904](https://github.com/matrix-org/matrix-spec-proposals/pull/3904). ([#1397](https://github.com/matrix-org/matrix-spec/issues/1397))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Clarify the grammar for room versions. ([#1422](https://github.com/matrix-org/matrix-spec/issues/1422))
|
||||||
|
- Fix various typos throughout the specification. ([#1423](https://github.com/matrix-org/matrix-spec/issues/1423))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add link to the unstable spec to the README. ([#1357](https://github.com/matrix-org/matrix-spec/issues/1357))
|
||||||
|
- Improve safety of the proposals retrieval script in the event of failure. ([#1368](https://github.com/matrix-org/matrix-spec/issues/1368))
|
||||||
|
- Rename `<content>` to `content` in the OpenAPI files for content uploads. ([#1370](https://github.com/matrix-org/matrix-spec/issues/1370))
|
||||||
|
- Stop autogenerating examples where we already have an example. ([#1384](https://github.com/matrix-org/matrix-spec/issues/1384))
|
||||||
|
- Improve formatting of definitions in the Push Notifications section. ([#1415](https://github.com/matrix-org/matrix-spec/issues/1415))
|
||||||
139
content/changelog/v1.7.md
Normal file
139
content/changelog/v1.7.md
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
---
|
||||||
|
title: v1.7 Changelog
|
||||||
|
linkTitle: v1.7
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2023-05-25
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>New Endpoints</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- [`POST /_matrix/media/v1/create`](/client-server-api/#post_matrixmediav1create) ([#1499](https://github.com/matrix-org/matrix-spec/issues/1499))
|
||||||
|
- [`PUT /_matrix/media/v3/upload/{serverName}/{mediaId}`](/client-server-api/#put_matrixmediav3uploadservernamemediaid) ([#1499](https://github.com/matrix-org/matrix-spec/issues/1499))
|
||||||
|
- [`POST /_matrix/client/v1/login/get_token`](/client-server-api/#post_matrixclientv1loginget_token) ([#1530](https://github.com/matrix-org/matrix-spec/issues/1530))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Changes to the server-side aggregation of `m.replace` (edit) events, as per [MSC3925](https://github.com/matrix-org/matrix-spec-proposals/pull/3925). ([#1440](https://github.com/matrix-org/matrix-spec/issues/1440), [#1525](https://github.com/matrix-org/matrix-spec/issues/1525))
|
||||||
|
- Add new push rule conditions `event_property_is` and `event_property_contains`, as per [MSC3758](https://github.com/matrix-org/matrix-spec-proposals/pull/3758) and [MSC3966](https://github.com/matrix-org/matrix-spec-proposals/pull/3966). ([#1464](https://github.com/matrix-org/matrix-spec/issues/1464))
|
||||||
|
- Add `m.annotation` relations (reactions), as per [MSC2677](https://github.com/matrix-org/matrix-spec-proposals/pull/2677). ([#1475](https://github.com/matrix-org/matrix-spec/issues/1475), [#1531](https://github.com/matrix-org/matrix-spec/issues/1531))
|
||||||
|
- Support asynchronous media uploads, as per [MSC2246](https://github.com/matrix-org/matrix-spec-proposals/pull/2246). ([#1499](https://github.com/matrix-org/matrix-spec/issues/1499), [#1510](https://github.com/matrix-org/matrix-spec/issues/1510))
|
||||||
|
- Document the `m.mentions` property; the `.m.rule.is_user_mention` and `.m.rule.is_room_mention` push rules; and other notification behaviour, as per [MSC3952](https://github.com/matrix-org/matrix-spec-proposals/pull/3952). ([#1508](https://github.com/matrix-org/matrix-spec/issues/1508))
|
||||||
|
- Improve VoIP signaling, as per [MSC2746](https://github.com/matrix-org/matrix-spec-proposals/pull/2746). ([#1511](https://github.com/matrix-org/matrix-spec/issues/1511), [#1540](https://github.com/matrix-org/matrix-spec/issues/1540))
|
||||||
|
- Update the scope of transaction IDs, as per [MSC3970](https://github.com/matrix-org/matrix-spec-proposals/pull/3970). ([#1526](https://github.com/matrix-org/matrix-spec/issues/1526))
|
||||||
|
- Add an ability to redirect media downloads, as per [MSC3860](https://github.com/matrix-org/matrix-spec-proposals/pull/3860). ([#1529](https://github.com/matrix-org/matrix-spec/issues/1529))
|
||||||
|
- Add an ability to use an existing session to log in another, as per [MSC3882](https://github.com/matrix-org/matrix-spec-proposals/pull/3882). ([#1530](https://github.com/matrix-org/matrix-spec/issues/1530))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Clarify the sections of the specification concerning aggregation of child events. ([#1424](https://github.com/matrix-org/matrix-spec/issues/1424))
|
||||||
|
- Fix various typos throughout the specification. ([#1432](https://github.com/matrix-org/matrix-spec/issues/1432), [#1442](https://github.com/matrix-org/matrix-spec/issues/1442), [#1447](https://github.com/matrix-org/matrix-spec/issues/1447), [#1455](https://github.com/matrix-org/matrix-spec/issues/1455), [#1465](https://github.com/matrix-org/matrix-spec/issues/1465), [#1500](https://github.com/matrix-org/matrix-spec/issues/1500), [#1509](https://github.com/matrix-org/matrix-spec/issues/1509))
|
||||||
|
- Clarify that reply chain fallback for threads might not be present. ([#1439](https://github.com/matrix-org/matrix-spec/issues/1439))
|
||||||
|
- Clarify what event property the content-specific push rules match against. ([#1441](https://github.com/matrix-org/matrix-spec/issues/1441))
|
||||||
|
- Clarify the semantics that make requests idempotent. ([#1449](https://github.com/matrix-org/matrix-spec/issues/1449))
|
||||||
|
- Improve documentation of how clients use push rules. ([#1461](https://github.com/matrix-org/matrix-spec/issues/1461))
|
||||||
|
- Clarify that servers should enforce a default `limit` on a filter if one is not specified. ([#1463](https://github.com/matrix-org/matrix-spec/issues/1463))
|
||||||
|
- Disambiguate using property names with dots in them during push rule processing, as per [MSC3873](https://github.com/matrix-org/matrix-spec-proposals/pull/3873) and [MSC3980](https://github.com/matrix-org/matrix-spec-proposals/pull/3980). ([#1464](https://github.com/matrix-org/matrix-spec/issues/1464))
|
||||||
|
- Fix phrasing & typography in the registration endpoint description. Contributed by @HarHarLinks. ([#1474](https://github.com/matrix-org/matrix-spec/issues/1474))
|
||||||
|
- Remove outdated text saying that `state_default` is 0 if there is no `m.room.power_levels` event in a room. ([#1479](https://github.com/matrix-org/matrix-spec/issues/1479))
|
||||||
|
- Remove fictitious `token` parameter on `/keys/query` endpoint. ([#1485](https://github.com/matrix-org/matrix-spec/issues/1485))
|
||||||
|
- Fix rendering of properties with a list of types. ([#1487](https://github.com/matrix-org/matrix-spec/issues/1487))
|
||||||
|
- Clarify parts of the cross-signing signature upload request. ([#1495](https://github.com/matrix-org/matrix-spec/issues/1495))
|
||||||
|
- Remove the `dont_notify` and `coalesce` push rule actions, as per [MSC3987](https://github.com/matrix-org/matrix-spec-proposals/pull/3987). ([#1501](https://github.com/matrix-org/matrix-spec/issues/1501))
|
||||||
|
- Clarify `m.location` scheme by partially reverting [f1f32d3](https://github.com/matrix-org/matrix-spec/commit/f1f32d3a15c325ee8aa9d2c6bafd96c38069bb53). Contributed by @HarHarLinks. ([#1507](https://github.com/matrix-org/matrix-spec/issues/1507))
|
||||||
|
- Add missing `knock_restricted` join rule to the `m.room.join_rules` schema. ([#1535](https://github.com/matrix-org/matrix-spec/issues/1535))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Fix various typos throughout the specification. ([#1431](https://github.com/matrix-org/matrix-spec/issues/1431), [#1447](https://github.com/matrix-org/matrix-spec/issues/1447), [#1466](https://github.com/matrix-org/matrix-spec/issues/1466), [#1518](https://github.com/matrix-org/matrix-spec/issues/1518))
|
||||||
|
- Fix PDU examples by removing invalid OpenAPI reference to `examples/minimal_pdu.json`. ([#1454](https://github.com/matrix-org/matrix-spec/issues/1454))
|
||||||
|
- Remove leftover `{key_id}` from `/_matrix/key/v2/server/`. ([#1473](https://github.com/matrix-org/matrix-spec/issues/1473))
|
||||||
|
- Remove extraneous `age_ts` field from the reference hash calculation section. ([#1536](https://github.com/matrix-org/matrix-spec/issues/1536))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>New Endpoints</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- [`POST /_matrix/app/v1/ping`](/application-service-api/#post_matrixappv1ping) ([#1516](https://github.com/matrix-org/matrix-spec/issues/1516))
|
||||||
|
- [`POST /_matrix/client/v1/appservice/{appserviceId}/ping`](/application-service-api/#post_matrixclientv1appserviceappserviceidping) ([#1516](https://github.com/matrix-org/matrix-spec/issues/1516))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add homeserver->appservice ping mechanism, as per [MSC2659](https://github.com/matrix-org/matrix-spec-proposals/pull/2659). Contributed by @tulir at @beeper. ([#1516](https://github.com/matrix-org/matrix-spec/issues/1516), [#1541](https://github.com/matrix-org/matrix-spec/issues/1541))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Fix various typos throughout the specification. ([#1447](https://github.com/matrix-org/matrix-spec/issues/1447))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Corrections to the response format of `/_matrix/identity/v2/store-invite`. ([#1486](https://github.com/matrix-org/matrix-spec/issues/1486))
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Clarifications of event ID formats in early room versions ([#1484](https://github.com/matrix-org/matrix-spec/issues/1484))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Clarify that the term "Canonical JSON" is a specific thing within the Matrix specification. ([#1468](https://github.com/matrix-org/matrix-spec/issues/1468))
|
||||||
|
- Remove references to groups. ([#1483](https://github.com/matrix-org/matrix-spec/issues/1483))
|
||||||
|
- Clarifications of event ID formats in early room versions. ([#1484](https://github.com/matrix-org/matrix-spec/issues/1484))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Update references to Inter font. ([#1444](https://github.com/matrix-org/matrix-spec/issues/1444))
|
||||||
|
- Endpoint disclosures now hide everything but the URL. ([#1446](https://github.com/matrix-org/matrix-spec/issues/1446))
|
||||||
|
- Wrap $ref in allOf where other attributes are present, to improve OpenAPI compliance. ([#1457](https://github.com/matrix-org/matrix-spec/issues/1457))
|
||||||
|
- Minor cleanups to the GitHub Actions workflows ([#1476](https://github.com/matrix-org/matrix-spec/issues/1476))
|
||||||
|
- Fix generation of anchors for additional properties. ([#1488](https://github.com/matrix-org/matrix-spec/issues/1488))
|
||||||
|
- Fix various typos throughout the specification. ([#1534](https://github.com/matrix-org/matrix-spec/issues/1534))
|
||||||
|
- Document more of the spec release timeline/process. ([#1538](https://github.com/matrix-org/matrix-spec/issues/1538))
|
||||||
113
content/changelog/v1.8.md
Normal file
113
content/changelog/v1.8.md
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
title: v1.8 Changelog
|
||||||
|
linkTitle: v1.8
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2023-08-23
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Require callers to be joined to the room to report its events, as per [MSC2249](https://github.com/matrix-org/matrix-spec-proposals/pull/2249). ([#1517](https://github.com/matrix-org/matrix-spec/issues/1517))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Fix missing `type` property in the JSON schema definition of the `m.reaction` event. Contributed by @chebureki. ([#1552](https://github.com/matrix-org/matrix-spec/issues/1552))
|
||||||
|
- Make sure examples types match schema in definitions. ([#1563](https://github.com/matrix-org/matrix-spec/issues/1563))
|
||||||
|
- Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas. ([#1564](https://github.com/matrix-org/matrix-spec/issues/1564))
|
||||||
|
- Fix broken header formatting. Contributed by @midnightveil. ([#1578](https://github.com/matrix-org/matrix-spec/issues/1578))
|
||||||
|
- Render binary request and response bodies. ([#1579](https://github.com/matrix-org/matrix-spec/issues/1579))
|
||||||
|
- Fix description of MAC calculation in SAS verification. ([#1590](https://github.com/matrix-org/matrix-spec/issues/1590))
|
||||||
|
- Update link to SAS emoji definition data. ([#1593](https://github.com/matrix-org/matrix-spec/issues/1593))
|
||||||
|
- Fix various typos throughout the specification. ([#1597](https://github.com/matrix-org/matrix-spec/issues/1597))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Deprecations**
|
||||||
|
|
||||||
|
- Deprecate `matrix` SRV lookup steps during server discovery, as per [MSC4040](https://github.com/matrix-org/matrix-spec-proposals/pull/4040). ([#1624](https://github.com/matrix-org/matrix-spec/issues/1624))
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add `matrix-fed` SRV lookup steps to server discovery, as per [MSC4040](https://github.com/matrix-org/matrix-spec-proposals/pull/4040). ([#1624](https://github.com/matrix-org/matrix-spec/issues/1624))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Document why `/state_ids` can respond with a 404. ([#1521](https://github.com/matrix-org/matrix-spec/issues/1521))
|
||||||
|
- Fix response definition for `POST /_matrix/federation/v1/user/keys/claim`. ([#1559](https://github.com/matrix-org/matrix-spec/issues/1559))
|
||||||
|
- Fix examples in server keys definition. ([#1560](https://github.com/matrix-org/matrix-spec/issues/1560))
|
||||||
|
- Make sure examples types match schema in definitions. ([#1563](https://github.com/matrix-org/matrix-spec/issues/1563))
|
||||||
|
- Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas. ([#1564](https://github.com/matrix-org/matrix-spec/issues/1564))
|
||||||
|
- Fix broken header formatting. Contributed by @midnightveil. ([#1578](https://github.com/matrix-org/matrix-spec/issues/1578))
|
||||||
|
- Remove spurious mention of a "default port" with respect to SRV record lookup. ([#1615](https://github.com/matrix-org/matrix-spec/issues/1615))
|
||||||
|
- Switch to ordered list for server name resolution steps. ([#1623](https://github.com/matrix-org/matrix-spec/issues/1623))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Fix type of custom `fields` in thirdparty lookup queries. ([#1584](https://github.com/matrix-org/matrix-spec/issues/1584))
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Make sure examples types match schema in definitions. ([#1563](https://github.com/matrix-org/matrix-spec/issues/1563))
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add room version 11 as per [MSC3820](https://github.com/matrix-org/matrix-spec-proposals/pull/3820). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
|
||||||
|
- Move `redacts` from top level to `content` on `m.room.redaction` events in room version 11, as per [MSC2174](https://github.com/matrix-org/matrix-spec-proposals/pull/2174). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
|
||||||
|
- Remove `creator` from `m.room.creator` events in room version 11, as per [MSC2175](https://github.com/matrix-org/matrix-spec-proposals/pull/2175). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
|
||||||
|
- Remove remaining usage of `origin` from events in room version 11, as per [MSC3989](https://github.com/matrix-org/matrix-spec-proposals/pull/3989). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
|
||||||
|
- Update the redaction rules in room version 11, as per [MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176) and [MSC3821](https://github.com/matrix-org/matrix-spec-proposals/pull/3821). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Allow `+` in Matrix IDs, as per [MSC4009](https://github.com/matrix-org/matrix-spec-proposals/pull/4009). ([#1583](https://github.com/matrix-org/matrix-spec/issues/1583))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify spec re canonical JSON to handle negative-zero; also, give an example of negative-zero and a large power of ten. ([#1573](https://github.com/matrix-org/matrix-spec/issues/1573))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Upgrade Swagger data to OpenAPI 3.1. ([#1310](https://github.com/matrix-org/matrix-spec/issues/1310))
|
||||||
|
- Create `@matrix-org/spec` npm package to ship the SAS Emoji data definitions & translations. ([#1620](https://github.com/matrix-org/matrix-spec/issues/1620))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Update the CI to validate the file extension of changelog entries. ([#1542](https://github.com/matrix-org/matrix-spec/issues/1542))
|
||||||
|
- Disclosure sections now only display their title when collapsed. ([#1549](https://github.com/matrix-org/matrix-spec/issues/1549))
|
||||||
|
- Fix the sidebar in recent versions of Hugo. ([#1551](https://github.com/matrix-org/matrix-spec/issues/1551))
|
||||||
|
- Bump jsonschema to validate JSON Schemas against Draft 2020-12. ([#1556](https://github.com/matrix-org/matrix-spec/issues/1556))
|
||||||
|
- Use Redocly CLI to validate OpenAPI definitions. ([#1558](https://github.com/matrix-org/matrix-spec/issues/1558))
|
||||||
|
- Use tag name as the OpenAPI definition version. ([#1561](https://github.com/matrix-org/matrix-spec/issues/1561))
|
||||||
|
- Make sure version in `x-changedInMatrixVersion` is a string. ([#1562](https://github.com/matrix-org/matrix-spec/issues/1562))
|
||||||
|
- Clarify usage of ABNF for grammar in the documentation style guide. ([#1582](https://github.com/matrix-org/matrix-spec/issues/1582))
|
||||||
|
- Remove unnecessary `oneOf`s in JSON schemas. ([#1585](https://github.com/matrix-org/matrix-spec/issues/1585))
|
||||||
|
- Update the version of Hugo used to render the spec to v0.113.0. ([#1591](https://github.com/matrix-org/matrix-spec/issues/1591))
|
||||||
|
- Fix rendered changelog with new version of towncrier. ([#1598](https://github.com/matrix-org/matrix-spec/issues/1598))
|
||||||
|
- Improve the layout of tables on desktop displays. Contributed by Martin Fischer. ([#1601](https://github.com/matrix-org/matrix-spec/issues/1601))
|
||||||
84
content/changelog/v1.9.md
Normal file
84
content/changelog/v1.9.md
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
---
|
||||||
|
title: v1.9 Changelog
|
||||||
|
linkTitle: v1.9
|
||||||
|
type: docs
|
||||||
|
layout: changelog
|
||||||
|
outputs:
|
||||||
|
- html
|
||||||
|
- checklist
|
||||||
|
date: 2023-11-29
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client-Server API
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add the `m.rule.suppress_edits` default push rule, as per [MSC3958](https://github.com/matrix-org/matrix-spec-proposals/pull/3958). ([#1617](https://github.com/matrix-org/matrix-spec/issues/1617))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Fix `m.call.negotiate` schema and example. ([#1546](https://github.com/matrix-org/matrix-spec/issues/1546))
|
||||||
|
- Clarify that the `via` property is required for `m.space.parent` and `m.space.child` as per [MSC1772](https://github.com/matrix-org/matrix-spec-proposals/pull/1772). Contributed by @PaarthShah. ([#1618](https://github.com/matrix-org/matrix-spec/issues/1618))
|
||||||
|
- Add a note to the `/publicRooms` API that the server name is case sensitive. ([#1638](https://github.com/matrix-org/matrix-spec/issues/1638))
|
||||||
|
- Clarify that an `m.room.name` event with an absent `name` field is not expected behavior. ([#1639](https://github.com/matrix-org/matrix-spec/issues/1639))
|
||||||
|
- Fix schemas used for account data and presence events in `GET /initialSync`. ([#1647](https://github.com/matrix-org/matrix-spec/issues/1647))
|
||||||
|
- Fix various typos throughout the specification. ([#1658](https://github.com/matrix-org/matrix-spec/issues/1658), [#1661](https://github.com/matrix-org/matrix-spec/issues/1661), [#1665](https://github.com/matrix-org/matrix-spec/issues/1665))
|
||||||
|
- Fix `.m.rule.suppress_notices` push rule not being valid JSON. ([#1671](https://github.com/matrix-org/matrix-spec/issues/1671))
|
||||||
|
- Add missing properties for `event_property_is` and `event_property_contains` push conditions to `PushConditions` object. ([#1673](https://github.com/matrix-org/matrix-spec/issues/1673))
|
||||||
|
- Indicate that fallback keys should have a `fallback` property set to `true`. ([#1676](https://github.com/matrix-org/matrix-spec/issues/1676))
|
||||||
|
- Clarify that thread roots are not considered within the thread. ([#1677](https://github.com/matrix-org/matrix-spec/issues/1677))
|
||||||
|
|
||||||
|
|
||||||
|
## Server-Server API
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Fix schema of `m.receipt` EDU. ([#1636](https://github.com/matrix-org/matrix-spec/issues/1636))
|
||||||
|
- Fix various typos throughout the specification. ([#1661](https://github.com/matrix-org/matrix-spec/issues/1661))
|
||||||
|
- Clarify that federation requests for non-local users are invalid. ([#1672](https://github.com/matrix-org/matrix-spec/issues/1672))
|
||||||
|
|
||||||
|
|
||||||
|
## Application Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Identity Service API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Push Gateway API
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Room Versions
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Clarify timestamp specification with respect to leap seconds. ([#1627](https://github.com/matrix-org/matrix-spec/issues/1627))
|
||||||
|
- Fix various typos throughout the specification. ([#1652](https://github.com/matrix-org/matrix-spec/issues/1652))
|
||||||
|
|
||||||
|
|
||||||
|
## Internal Changes/Tooling
|
||||||
|
|
||||||
|
**Backwards Compatible Changes**
|
||||||
|
|
||||||
|
- Add more CI checks for OpenAPI definitions and JSON Schemas. ([#1656](https://github.com/matrix-org/matrix-spec/issues/1656))
|
||||||
|
- Generate server-server OpenAPI definition. ([#1657](https://github.com/matrix-org/matrix-spec/issues/1657))
|
||||||
|
|
||||||
|
**Spec Clarifications**
|
||||||
|
|
||||||
|
- Replace all mentions of Swagger by OpenAPI. ([#1633](https://github.com/matrix-org/matrix-spec/issues/1633))
|
||||||
|
- Fix enum types in JSON schemas. ([#1634](https://github.com/matrix-org/matrix-spec/issues/1634))
|
||||||
|
- Fix schema of `m.mentions` object. ([#1635](https://github.com/matrix-org/matrix-spec/issues/1635))
|
||||||
|
- Fix rendering of `m.receipt` event in Client-Server API. ([#1637](https://github.com/matrix-org/matrix-spec/issues/1637))
|
||||||
|
- Remove required `fieldname` in appservice Protocol definition. ([#1646](https://github.com/matrix-org/matrix-spec/issues/1646))
|
||||||
|
- Fix github action workflow responsible for releasing of @matrix-org/spec package. ([#1648](https://github.com/matrix-org/matrix-spec/issues/1648))
|
||||||
|
- Upgrade GitHub actions. ([#1660](https://github.com/matrix-org/matrix-spec/issues/1660))
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,7 @@ data with the same `type`.
|
||||||
The client receives the account data as events in the `account_data`
|
The client receives the account data as events in the `account_data`
|
||||||
sections of a [`/sync`](#get_matrixclientv3sync) response.
|
sections of a [`/sync`](#get_matrixclientv3sync) response.
|
||||||
|
|
||||||
These events can also be received in a `/events` response or in the
|
These events can also be received in a [`/events`](#get_matrixclientv3events) response or in the
|
||||||
`account_data` section of a room in a `/sync` response. `m.tag` events appearing in
|
`account_data` section of a room in a `/sync` response. `m.tag` events appearing in
|
||||||
`/events` will have a `room_id` with the room the tags are for.
|
`/events` will have a `room_id` with the room the tags are for.
|
||||||
|
|
||||||
|
|
@ -26,6 +26,15 @@ These events can also be received in a `/events` response or in the
|
||||||
|
|
||||||
#### Server Behaviour
|
#### Server Behaviour
|
||||||
|
|
||||||
Servers MUST reject clients from setting account data for event types
|
Servers MUST reject setting account data for event types
|
||||||
that the server manages. Currently, this only includes
|
that the server manages by using a 405 error response.
|
||||||
[m.fully\_read](#mfully_read).
|
Currently, this only includes [`m.fully_read`](#mfully_read)
|
||||||
|
and [`m.push_rules`](#push-rules-events). This applies to
|
||||||
|
both global and room-specific account data.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% changed-in v="1.10" %}} `m.push_rules` was added to the rejection
|
||||||
|
list.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
Servers must allow clients to read the above event types as normal.
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ user wants to send to a room would be uploaded here, as would an avatar
|
||||||
the user wants to use.
|
the user wants to use.
|
||||||
|
|
||||||
Uploads are POSTed to a resource on the user's local homeserver which
|
Uploads are POSTed to a resource on the user's local homeserver which
|
||||||
returns a MXC URI which can later be used to GET the download. Content
|
returns an `mxc://` URI which can later be used to GET the download. Content
|
||||||
is downloaded from the recipient's local homeserver, which must first
|
is downloaded from the recipient's local homeserver, which must first
|
||||||
transfer the content from the origin homeserver using the same API
|
transfer the content from the origin homeserver using the same API
|
||||||
(unless the origin and destination homeservers are the same).
|
(unless the origin and destination homeservers are the same).
|
||||||
|
|
@ -16,26 +16,69 @@ When serving content, the server SHOULD provide a
|
||||||
`Content-Security-Policy` header. The recommended policy is
|
`Content-Security-Policy` header. The recommended policy is
|
||||||
`sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';`.
|
`sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';`.
|
||||||
|
|
||||||
{{% boxes/added-in-paragraph %}}
|
{{% added-in v="1.4" %}} The server SHOULD additionally provide
|
||||||
{{< added-in v="1.4" >}} The server SHOULD additionally provide
|
|
||||||
`Cross-Origin-Resource-Policy: cross-origin` when serving content to allow
|
`Cross-Origin-Resource-Policy: cross-origin` when serving content to allow
|
||||||
(web) clients to access restricted APIs such as `SharedArrayBuffer` when
|
(web) clients to access restricted APIs such as `SharedArrayBuffer` when
|
||||||
interacting with the media repository.
|
interacting with the media repository.
|
||||||
{{% /boxes/added-in-paragraph %}}
|
|
||||||
|
|
||||||
#### Matrix Content (MXC) URIs
|
{{% changed-in v="1.11" %}} The unauthenticated download endpoints have been
|
||||||
|
deprecated in favour of newer, authenticated, ones. This change includes updating
|
||||||
|
the paths of all media endpoints from `/_matrix/media/*` to `/_matrix/client/{version}/media/*`,
|
||||||
|
with the exception of the `/upload` and `/create` endpoints. The upload/create
|
||||||
|
endpoints are expected to undergo a similar transition in a later version of the
|
||||||
|
specification.
|
||||||
|
|
||||||
Content locations are represented as Matrix Content (MXC) URIs. They
|
#### Matrix Content (`mxc://`) URIs
|
||||||
|
|
||||||
|
Content locations are represented as Matrix Content (`mxc://`) URIs. They
|
||||||
look like:
|
look like:
|
||||||
|
|
||||||
mxc://<server-name>/<media-id>
|
```nohighlight
|
||||||
|
mxc://<server-name>/<media-id>
|
||||||
|
|
||||||
<server-name> : The name of the homeserver where this content originated, e.g. matrix.org
|
<server-name> : The name of the homeserver where this content originated, e.g. matrix.org
|
||||||
<media-id> : An opaque ID which identifies the content.
|
<media-id> : An opaque ID which identifies the content.
|
||||||
|
```
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour {id="content-repo-client-behaviour"}
|
||||||
|
|
||||||
Clients can upload and download content using the following HTTP APIs.
|
Clients can access the content repository using the following endpoints.
|
||||||
|
|
||||||
|
{{% changed-in v="1.11" %}} A number of endpoints under the /_matrix/media hierarchy
|
||||||
|
have been deprecated and replaced with new endpoints which require authentication.
|
||||||
|
The deprecated endpoints are marked in the section below.
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
By Matrix 1.12, servers SHOULD "freeze" the deprecated, unauthenticated, endpoints
|
||||||
|
to prevent newly-uploaded media from being downloaded. This SHOULD mean that any
|
||||||
|
media uploaded *before* the freeze remains accessible via the deprecated endpoints,
|
||||||
|
and any media uploaded *after* (or *during*) the freeze SHOULD only be accessible
|
||||||
|
through the new, authenticated, endpoints. For remote media, "newly-uploaded" is
|
||||||
|
determined by the date the cache was populated. This may mean the media is older
|
||||||
|
than the freeze, but because the server had to re-download it, it is now considered
|
||||||
|
"new".
|
||||||
|
|
||||||
|
Clients SHOULD update to support the authenticated endpoints before servers freeze
|
||||||
|
unauthenticated access.
|
||||||
|
|
||||||
|
Servers SHOULD consider their local ecosystem impact before enacting a freeze.
|
||||||
|
This could mean ensuring their users' typical clients support the new endpoints
|
||||||
|
when available, or updating bridges to start using media proxies.
|
||||||
|
|
||||||
|
In addition to the above, servers SHOULD exclude [IdP icons used in the `m.login.sso` flow](/client-server-api/#definition-mloginsso-flow-schema)
|
||||||
|
from the freeze. See the `m.login.sso` flow schema for details.
|
||||||
|
|
||||||
|
An *example* timeline for a server may be:
|
||||||
|
|
||||||
|
* Matrix 1.11 release: Clients begin supporting authenticated media.
|
||||||
|
* Matrix 1.12 release: Servers freeze unauthenticated media access.
|
||||||
|
* Media uploaded prior to this point still works with the deprecated endpoints.
|
||||||
|
* Newly uploaded (or cached) media *only* works on the authenticated endpoints.
|
||||||
|
|
||||||
|
Matrix 1.12 is expected to be released in the July-September 2024 calendar quarter.
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="authed-content-repo" %}}
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="content-repo" %}}
|
{{% http-api spec="client-server" api="content-repo" %}}
|
||||||
|
|
||||||
|
|
@ -88,12 +131,17 @@ The HTTP GET endpoint does not require any authentication. Knowing the
|
||||||
URL of the content is sufficient to retrieve the content, even if the
|
URL of the content is sufficient to retrieve the content, even if the
|
||||||
entity isn't in the room.
|
entity isn't in the room.
|
||||||
|
|
||||||
MXC URIs are vulnerable to directory traversal attacks such as
|
`mxc://` URIs are vulnerable to directory traversal attacks such as
|
||||||
`mxc://127.0.0.1/../../../some_service/etc/passwd`. This would cause the
|
`mxc://127.0.0.1/../../../some_service/etc/passwd`. This would cause the
|
||||||
target homeserver to try to access and return this file. As such,
|
target homeserver to try to access and return this file. As such,
|
||||||
homeservers MUST sanitise MXC URIs by allowing only alphanumeric
|
homeservers MUST sanitise `mxc://` URIs by:
|
||||||
(`A-Za-z0-9`), `_` and `-` characters in the `server-name` and
|
|
||||||
`media-id` values. This set of whitelisted characters allows URL-safe
|
- restricting the `server-name` segment to valid
|
||||||
|
[server names](/appendices/#server-name)
|
||||||
|
- allowing only alphanumeric (`A-Za-z0-9`), `_` and `-` characters in
|
||||||
|
the `media-id` segment
|
||||||
|
|
||||||
|
The resulting set of whitelisted characters allows URL-safe
|
||||||
base64 encodings specified in RFC 4648. Applying this character
|
base64 encodings specified in RFC 4648. Applying this character
|
||||||
whitelist is preferable to blacklisting `.` and `/` as there are
|
whitelist is preferable to blacklisting `.` and `/` as there are
|
||||||
techniques around blacklisted characters (percent-encoded characters,
|
techniques around blacklisted characters (percent-encoded characters,
|
||||||
|
|
@ -119,3 +167,50 @@ Homeservers have additional content-specific concerns:
|
||||||
- Clients or remote homeservers may try to upload malicious files
|
- Clients or remote homeservers may try to upload malicious files
|
||||||
targeting vulnerabilities in either the homeserver thumbnailing or
|
targeting vulnerabilities in either the homeserver thumbnailing or
|
||||||
the client decoders.
|
the client decoders.
|
||||||
|
|
||||||
|
##### Serving inline content
|
||||||
|
|
||||||
|
Clients with insecure configurations may be vulnerable to Cross-Site Scripting
|
||||||
|
attacks when served media with a `Content-Disposition` of `inline`. Clients
|
||||||
|
SHOULD NOT be hosted on the same domain as the media endpoints for the homeserver
|
||||||
|
to mitigate most of this risk. Servers SHOULD restrict `Content-Type` headers to
|
||||||
|
one of the following values when serving content with `Content-Disposition: inline`:
|
||||||
|
|
||||||
|
* `text/css`
|
||||||
|
* `text/plain`
|
||||||
|
* `text/csv`
|
||||||
|
* `application/json`
|
||||||
|
* `application/ld+json`
|
||||||
|
* `image/jpeg`
|
||||||
|
* `image/gif`
|
||||||
|
* `image/png`
|
||||||
|
* `image/apng`
|
||||||
|
* `image/webp`
|
||||||
|
* `image/avif`
|
||||||
|
* `video/mp4`
|
||||||
|
* `video/webm`
|
||||||
|
* `video/ogg`
|
||||||
|
* `video/quicktime`
|
||||||
|
* `audio/mp4`
|
||||||
|
* `audio/webm`
|
||||||
|
* `audio/aac`
|
||||||
|
* `audio/mpeg`
|
||||||
|
* `audio/ogg`
|
||||||
|
* `audio/wave`
|
||||||
|
* `audio/wav`
|
||||||
|
* `audio/x-wav`
|
||||||
|
* `audio/x-pn-wav`
|
||||||
|
* `audio/flac`
|
||||||
|
* `audio/x-flac`
|
||||||
|
|
||||||
|
These types are unlikely to cause Cross-Site Scripting issues when a `Content-Type`
|
||||||
|
header is provided, as clients will only try to render the data using that content
|
||||||
|
type. For example, if a HTML file is uploaded with a `Content-Type` of `image/png`,
|
||||||
|
clients will just assume that the image is corrupted, and won't render it as a
|
||||||
|
HTML page. Therefore, there is no risk in trusting the user-defined content type,
|
||||||
|
as long as the `Content-Disposition` is calculated based on that type.
|
||||||
|
|
||||||
|
Clients SHOULD NOT rely on servers returning `inline` rather than `attachment`
|
||||||
|
on [`/download`](#get_matrixclientv1mediadownloadservernamemediaid). Server implementations might decide out of an abundance of
|
||||||
|
caution that all downloads are responded to with `attachment`, regardless of
|
||||||
|
content type - clients should not be surprised by this behaviour.
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ exchange fingerprints between users to build a web of trust.
|
||||||
device. This may include long-term identity keys, and/or one-time
|
device. This may include long-term identity keys, and/or one-time
|
||||||
keys.
|
keys.
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+----------+ +--------------+
|
+----------+ +--------------+
|
||||||
| Bob's HS | | Bob's Device |
|
| Bob's HS | | Bob's Device |
|
||||||
+----------+ +--------------+
|
+----------+ +--------------+
|
||||||
|
|
@ -29,7 +29,7 @@ keys.
|
||||||
|
|
||||||
2) Alice requests Bob's public identity keys and supported algorithms.
|
2) Alice requests Bob's public identity keys and supported algorithms.
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+----------------+ +------------+ +----------+
|
+----------------+ +------------+ +----------+
|
||||||
| Alice's Device | | Alice's HS | | Bob's HS |
|
| Alice's Device | | Alice's HS | | Bob's HS |
|
||||||
+----------------+ +------------+ +----------+
|
+----------------+ +------------+ +----------+
|
||||||
|
|
@ -40,7 +40,7 @@ keys.
|
||||||
|
|
||||||
3) Alice selects an algorithm and claims any one-time keys needed.
|
3) Alice selects an algorithm and claims any one-time keys needed.
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+----------------+ +------------+ +----------+
|
+----------------+ +------------+ +----------+
|
||||||
| Alice's Device | | Alice's HS | | Bob's HS |
|
| Alice's Device | | Alice's HS | | Bob's HS |
|
||||||
+----------------+ +------------+ +----------+
|
+----------------+ +------------+ +----------+
|
||||||
|
|
@ -51,6 +51,9 @@ keys.
|
||||||
|
|
||||||
##### Key algorithms
|
##### Key algorithms
|
||||||
|
|
||||||
|
Different key algorithms are used for different purposes. Each key algorithm
|
||||||
|
is identified by a name and is represented in a specific way.
|
||||||
|
|
||||||
The name `ed25519` corresponds to the
|
The name `ed25519` corresponds to the
|
||||||
[Ed25519](http://ed25519.cr.yp.to/) signature algorithm. The key is a
|
[Ed25519](http://ed25519.cr.yp.to/) signature algorithm. The key is a
|
||||||
32-byte Ed25519 public key, encoded using [unpadded Base64](/appendices/#unpadded-base64). Example:
|
32-byte Ed25519 public key, encoded using [unpadded Base64](/appendices/#unpadded-base64). Example:
|
||||||
|
|
@ -64,9 +67,9 @@ Example:
|
||||||
|
|
||||||
"JGLn/yafz74HB2AbPLYJWIVGnKAtqECOBf11yyXac2Y"
|
"JGLn/yafz74HB2AbPLYJWIVGnKAtqECOBf11yyXac2Y"
|
||||||
|
|
||||||
The name `signed_curve25519` also corresponds to the Curve25519
|
The name `signed_curve25519` also corresponds to the Curve25519 ECDH algorithm,
|
||||||
algorithm, but a key using this algorithm is represented by an object
|
but the key is signed so that it can be authenticated. A key using this
|
||||||
with the following properties:
|
algorithm is represented by an object with the following properties:
|
||||||
|
|
||||||
`KeyObject`
|
`KeyObject`
|
||||||
|
|
||||||
|
|
@ -74,6 +77,7 @@ with the following properties:
|
||||||
|------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| key | string | **Required.** The unpadded Base64-encoded 32-byte Curve25519 public key. |
|
| key | string | **Required.** The unpadded Base64-encoded 32-byte Curve25519 public key. |
|
||||||
| signatures | Signatures | **Required.** Signatures of the key object. The signature is calculated using the process described at [Signing JSON](/appendices/#signing-json). |
|
| signatures | Signatures | **Required.** Signatures of the key object. The signature is calculated using the process described at [Signing JSON](/appendices/#signing-json). |
|
||||||
|
| fallback | boolean | Indicates whether this is a [fallback key](#one-time-and-fallback-keys). Defaults to `false`. |
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
@ -88,23 +92,54 @@ Example:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`ed25519` and `curve25519` keys are used for [device keys](#device-keys).
|
||||||
|
Additionally, `ed25519` keys are used for [cross-signing keys](#cross-signing).
|
||||||
|
|
||||||
|
`signed_curve25519` keys are used for [one-time and fallback keys](#one-time-and-fallback-keys).
|
||||||
|
|
||||||
##### Device keys
|
##### Device keys
|
||||||
|
|
||||||
Each device should have one Ed25519 signing key. This key should be
|
Each device should have one Ed25519 signing key. This key should be
|
||||||
generated on the device from a cryptographically secure source, and the
|
generated on the device from a cryptographically secure source, and the
|
||||||
private part of the key should never be exported from the device. This
|
private part of the key should never be exported from the device. This
|
||||||
key is used as the fingerprint for a device by other clients.
|
key is used as the fingerprint for a device by other clients, and signs the
|
||||||
|
device's other keys.
|
||||||
|
|
||||||
A device will generally need to generate a number of additional keys.
|
A device will generally need to generate a number of additional keys.
|
||||||
Details of these will vary depending on the messaging algorithm in use.
|
Details of these will vary depending on the messaging algorithm in use.
|
||||||
|
|
||||||
Algorithms generally require device identity keys as well as signing
|
For Olm version 1, each device also requires a single Curve25519 identity
|
||||||
keys. Some algorithms also require one-time keys to improve their
|
key.
|
||||||
secrecy and deniability. These keys are used once during session
|
|
||||||
establishment, and are then thrown away.
|
|
||||||
|
|
||||||
For Olm version 1, each device requires a single Curve25519 identity
|
##### One-time and fallback keys
|
||||||
key, and a number of signed Curve25519 one-time keys.
|
|
||||||
|
In addition to the device keys, which are long-lived, some encryption
|
||||||
|
algorithms require that devices may also have a number of one-time keys, which
|
||||||
|
are only used once and discarded after use. For Olm version 1, devices use
|
||||||
|
`signed_curve25519` one-time keys, signed by the device's Ed25519 key.
|
||||||
|
|
||||||
|
Devices will generate one-time keys and upload them to the server; these will
|
||||||
|
later be [claimed](#post_matrixclientv3keysclaim) by other users. Servers must
|
||||||
|
ensure that each one-time key is only claimed once: a homeserver should discard
|
||||||
|
the one time key once it has been given to another user.
|
||||||
|
|
||||||
|
{{% added-in v="1.2" %}} Fallback keys are similar to one-time keys, but are
|
||||||
|
not consumed once used. If a fallback key has been uploaded, it will be
|
||||||
|
returned by the server when the device has run out of one-time keys and a user
|
||||||
|
tries to claim a key. Fallback keys should be replaced with new fallback keys
|
||||||
|
as soon as possible after they have been used.
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
Fallback keys are used to prevent one-time key exhaustion when devices
|
||||||
|
are offline/unable to upload additional keys, though sessions started using
|
||||||
|
fallback keys could be vulnerable to replay attacks.
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
Devices will be informed, [via `/sync`](#e2e-extensions-to-sync), about the number of
|
||||||
|
one-time keys remaining that can be claimed, as well as whether the fallback
|
||||||
|
keys have been used. The device can thus ensure that, while it is online, there
|
||||||
|
is a sufficient supply of one-time keys available, and that the fallback keys
|
||||||
|
get replaced if they have been used.
|
||||||
|
|
||||||
##### Uploading keys
|
##### Uploading keys
|
||||||
|
|
||||||
|
|
@ -115,11 +150,10 @@ signed by that key, as described in [Signing
|
||||||
JSON](/appendices/#signing-json).
|
JSON](/appendices/#signing-json).
|
||||||
|
|
||||||
One-time and fallback keys are also uploaded to the homeserver using the
|
One-time and fallback keys are also uploaded to the homeserver using the
|
||||||
[`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) API.
|
[`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) API. New
|
||||||
|
one-time and fallback keys are uploaded as needed. Fallback keys for key
|
||||||
{{% added-in v="1.2" %}} Fallback keys are similar to one-time keys, but
|
algorithms whose format is a signed JSON object should contain a property named
|
||||||
are not consumed once used. They are only used when the device has run out
|
`fallback` with a value of `true`.
|
||||||
of one-time keys, and can be replaced by a new fallback key.
|
|
||||||
|
|
||||||
Devices must store the private part of each key they upload. They can
|
Devices must store the private part of each key they upload. They can
|
||||||
discard the private part of a one-time key when they receive a message
|
discard the private part of a one-time key when they receive a message
|
||||||
|
|
@ -129,12 +163,6 @@ never know that it can discard the key. Therefore a device could end up
|
||||||
trying to store too many private keys. A device that is trying to store
|
trying to store too many private keys. A device that is trying to store
|
||||||
too many private keys may discard keys starting with the oldest.
|
too many private keys may discard keys starting with the oldest.
|
||||||
|
|
||||||
{{% boxes/warning %}}
|
|
||||||
Fallback keys are used to prevent one-time key exhaustion when devices
|
|
||||||
are offline/unable to upload additional keys, though sessions started using
|
|
||||||
fallback keys could be vulnerable to replay attacks.
|
|
||||||
{{% /boxes/warning %}}
|
|
||||||
|
|
||||||
{{% boxes/warning %}}
|
{{% boxes/warning %}}
|
||||||
Clients should not store the private half of fallback keys indefinitely
|
Clients should not store the private half of fallback keys indefinitely
|
||||||
to avoid situations where attackers can decrypt past messages sent using
|
to avoid situations where attackers can decrypt past messages sent using
|
||||||
|
|
@ -280,7 +308,7 @@ properties.
|
||||||
| key | JWK | **Required.** A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. |
|
| key | JWK | **Required.** A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. |
|
||||||
| iv | string | **Required.** The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64. |
|
| iv | string | **Required.** The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64. |
|
||||||
| hashes | {string: string} | **Required.** A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64. Clients should support the SHA-256 hash, which uses the key `sha256`. |
|
| hashes | {string: string} | **Required.** A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64. Clients should support the SHA-256 hash, which uses the key `sha256`. |
|
||||||
| v | string | **Required.** Version of the encrypted attachments protocol. Must be `v2`. |
|
| v | string | **Required.** Version of the encrypted attachment's protocol. Must be `v2`. |
|
||||||
|
|
||||||
`JWK`
|
`JWK`
|
||||||
|
|
||||||
|
|
@ -353,21 +381,6 @@ Example:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Claiming one-time keys
|
|
||||||
|
|
||||||
A client wanting to set up a session with another device can claim a
|
|
||||||
one-time key for that device. This is done by making a request to the
|
|
||||||
[`/keys/claim`](/client-server-api/#post_matrixclientv3keysclaim) API.
|
|
||||||
|
|
||||||
A homeserver should rate-limit the number of one-time keys that a given
|
|
||||||
user or remote server can claim. A homeserver should discard the public
|
|
||||||
part of a one time key once it has given that key to another user.
|
|
||||||
|
|
||||||
{{% added-in v="1.2" %}} If the device has run out of one-time keys which
|
|
||||||
can be claimed, the homeserver will return the fallback key (if one was
|
|
||||||
uploaded). Fallback keys are not deleted once used and should be replaced
|
|
||||||
by the device when they are able to upload more one-time keys.
|
|
||||||
|
|
||||||
#### Device verification
|
#### Device verification
|
||||||
|
|
||||||
Before Alice sends Bob encrypted data, or trusts data received from him,
|
Before Alice sends Bob encrypted data, or trusts data received from him,
|
||||||
|
|
@ -478,7 +491,7 @@ this example, Bob's device sends the `m.key.verification.start`, Alice's device
|
||||||
could also send that message. As well, the order of the
|
could also send that message. As well, the order of the
|
||||||
`m.key.verification.done` messages could be reversed.
|
`m.key.verification.done` messages could be reversed.
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+---------------+ +---------------+ +-------------+ +-------------+
|
+---------------+ +---------------+ +-------------+ +-------------+
|
||||||
| AliceDevice1 | | AliceDevice2 | | BobDevice1 | | BobDevice2 |
|
| AliceDevice1 | | AliceDevice2 | | BobDevice1 | | BobDevice2 |
|
||||||
+---------------+ +---------------+ +-------------+ +-------------+
|
+---------------+ +---------------+ +-------------+ +-------------+
|
||||||
|
|
@ -515,7 +528,7 @@ messages, Alice only sends one request event (an event with type
|
||||||
`m.room.message` with `msgtype: m.key.verification.request`, rather than an
|
`m.room.message` with `msgtype: m.key.verification.request`, rather than an
|
||||||
event with type `m.key.verification.request`), to the room. In addition, Alice
|
event with type `m.key.verification.request`), to the room. In addition, Alice
|
||||||
does not send an `m.key.verification.cancel` event to tell Bob's other devices
|
does not send an `m.key.verification.cancel` event to tell Bob's other devices
|
||||||
that the request as already been accepted; instead, when Bob's other devices
|
that the request has already been accepted; instead, when Bob's other devices
|
||||||
see his `m.key.verification.ready` event, they will know that the request has
|
see his `m.key.verification.ready` event, they will know that the request has
|
||||||
already been accepted, and that they should ignore the request.
|
already been accepted, and that they should ignore the request.
|
||||||
|
|
||||||
|
|
@ -647,32 +660,34 @@ The process between Alice and Bob verifying each other would be:
|
||||||
11. Alice's device receives Bob's message and verifies the commitment
|
11. Alice's device receives Bob's message and verifies the commitment
|
||||||
hash from earlier matches the hash of the key Bob's device just sent
|
hash from earlier matches the hash of the key Bob's device just sent
|
||||||
and the content of Alice's `m.key.verification.start` message.
|
and the content of Alice's `m.key.verification.start` message.
|
||||||
12. Both Alice and Bob's devices perform an Elliptic-curve
|
12. Both Alice's and Bob's devices perform an Elliptic-curve Diffie-Hellman using
|
||||||
Diffie-Hellman
|
their private ephemeral key, and the other device's ephemeral public key
|
||||||
(*ECDH(K<sub>A</sub><sup>private</sup>*, *K<sub>B</sub><sup>public</sup>*)),
|
(*ECDH(K<sub>A</sub><sup>private</sup>*, *K<sub>B</sub><sup>public</sup>*)
|
||||||
using the result as the shared secret.
|
for Alice's device and
|
||||||
|
*ECDH(K<sub>B</sub><sup>private</sup>*, *K<sub>A</sub><sup>public</sup>*)
|
||||||
|
for Bob's device), using the result as the shared secret.
|
||||||
13. Both Alice and Bob's devices display a SAS to their users, which is
|
13. Both Alice and Bob's devices display a SAS to their users, which is
|
||||||
derived from the shared key using one of the methods in this
|
derived from the shared key using one of the methods in this
|
||||||
section. If multiple SAS methods are available, clients should allow
|
section. If multiple SAS methods are available, clients should allow
|
||||||
the users to select a method.
|
the users to select a method.
|
||||||
14. Alice and Bob compare the strings shown by their devices, and tell
|
14. Alice and Bob compare the strings shown by their devices, and tell
|
||||||
their devices if they match or not.
|
their devices if they match or not.
|
||||||
15. Assuming they match, Alice and Bob's devices calculate the HMAC of
|
15. Assuming they match, Alice and Bob's devices each calculate Message
|
||||||
their own device keys and a comma-separated sorted list of the key
|
Authentication Codes (MACs) for:
|
||||||
IDs that they wish the other user to verify, using SHA-256 as the
|
* Each of the keys that they wish the other user to verify (usually their
|
||||||
hash function. HMAC is defined in [RFC
|
device ed25519 key and their master cross-signing key).
|
||||||
2104](https://tools.ietf.org/html/rfc2104). The key for the HMAC is
|
* The complete list of key IDs that they wish the other user to verify.
|
||||||
different for each item and is calculated by generating 32 bytes
|
|
||||||
(256 bits) using [the key verification HKDF](#hkdf-calculation).
|
The MAC calculation is defined [below](#mac-calculation).
|
||||||
16. Alice's device sends Bob's device an `m.key.verification.mac`
|
16. Alice's device sends Bob's device an `m.key.verification.mac`
|
||||||
message containing the MAC of Alice's device keys and the MAC of her
|
message containing the MAC of Alice's device keys and the MAC of her
|
||||||
key IDs to be verified. Bob's device does the same for Bob's device
|
key IDs to be verified. Bob's device does the same for Bob's device
|
||||||
keys and key IDs concurrently with Alice.
|
keys and key IDs concurrently with Alice.
|
||||||
17. When the other device receives the `m.key.verification.mac` message,
|
17. When the other device receives the `m.key.verification.mac` message,
|
||||||
the device calculates the HMAC of its copies of the other device's
|
the device calculates the MACs of its copies of the other device's
|
||||||
keys given in the message, as well as the HMAC of the
|
keys given in the message, as well as the MAC of the
|
||||||
comma-separated, sorted, list of key IDs in the message. The device
|
comma-separated, sorted, list of key IDs in the message. The device
|
||||||
compares these with the HMAC values given in the message, and if
|
compares these with the MAC values given in the message, and if
|
||||||
everything matches then the device keys are verified.
|
everything matches then the device keys are verified.
|
||||||
18. Alice and Bob's devices send `m.key.verification.done` messages to complete
|
18. Alice and Bob's devices send `m.key.verification.done` messages to complete
|
||||||
the verification.
|
the verification.
|
||||||
|
|
@ -680,7 +695,7 @@ The process between Alice and Bob verifying each other would be:
|
||||||
The wire protocol looks like the following between Alice and Bob's
|
The wire protocol looks like the following between Alice and Bob's
|
||||||
devices:
|
devices:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+-------------+ +-----------+
|
+-------------+ +-----------+
|
||||||
| AliceDevice | | BobDevice |
|
| AliceDevice | | BobDevice |
|
||||||
+-------------+ +-----------+
|
+-------------+ +-----------+
|
||||||
|
|
@ -756,7 +771,59 @@ following error codes are used in addition to those already specified:
|
||||||
|
|
||||||
{{% event event="m.key.verification.mac" %}}
|
{{% event event="m.key.verification.mac" %}}
|
||||||
|
|
||||||
###### HKDF calculation
|
###### MAC calculation
|
||||||
|
|
||||||
|
During the verification process, Message Authentication Codes (MACs) are calculated
|
||||||
|
for keys and lists of key IDs.
|
||||||
|
|
||||||
|
The method used to calculate these MACs depends upon the value of the
|
||||||
|
`message_authentication_code` property in the [`m.key.verification.accept`](#mkeyverificationaccept)
|
||||||
|
message. All current implementations should use the `hkdf-hmac-sha256.v2` method which is
|
||||||
|
defined as follows:
|
||||||
|
|
||||||
|
1. An HMAC key is generated using HKDF, as defined in [RFC
|
||||||
|
5869](https://tools.ietf.org/html/rfc5869), using SHA-256 as the hash
|
||||||
|
function. The shared secret is supplied as the input keying material. No salt
|
||||||
|
is used, and in the info parameter is the concatenation of:
|
||||||
|
|
||||||
|
- The string `MATRIX_KEY_VERIFICATION_MAC`.
|
||||||
|
- The Matrix ID of the user whose key is being MAC-ed.
|
||||||
|
- The Device ID of the device sending the MAC.
|
||||||
|
- The Matrix ID of the other user.
|
||||||
|
- The Device ID of the device receiving the MAC.
|
||||||
|
- The `transaction_id` being used.
|
||||||
|
- The Key ID of the key being MAC-ed, or the string `KEY_IDS` if the
|
||||||
|
item being MAC-ed is the list of key IDs.
|
||||||
|
|
||||||
|
2. A MAC is then generated using HMAC as defined in [RFC
|
||||||
|
2104](https://tools.ietf.org/html/rfc2104) with the key generated above and
|
||||||
|
using SHA-256 as the hash function.
|
||||||
|
|
||||||
|
If a key is being MACed, the MAC is performed on the public key as encoded
|
||||||
|
according to the [key algorithm](#key-algorithms). For example, for `ed25519`
|
||||||
|
keys, it is the unpadded base64-encoded key.
|
||||||
|
|
||||||
|
If the key list is being MACed, the list is sorted lexicographically and
|
||||||
|
comma-separated with no extra whitespace added, with each key written in the
|
||||||
|
form `{algorithm}:{keyId}`. For example, the key list could look like:
|
||||||
|
`ed25519:Cross+Signing+Key,ed25519:DEVICEID`. In this way, the recipient can
|
||||||
|
reconstruct the list from the names in the `mac` property of the
|
||||||
|
`m.key.verification.mac` message and ensure that no keys were added or removed.
|
||||||
|
|
||||||
|
3. The MAC values are base64-encoded and sent in a
|
||||||
|
[`m.key.verification.mac`](#mkeyverificationmac) message.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
The MAC method `hkdf-hmac-sha256` used an incorrect base64 encoding, due to a
|
||||||
|
bug in the original implementation in libolm. To remedy this,
|
||||||
|
`hkdf-hmac-sha256.v2` was introduced, which calculates the MAC in the same way,
|
||||||
|
but uses a correct base64 encoding. `hkdf-hmac-sha256` is deprecated and will
|
||||||
|
be removed in a future version of the spec. Use of `hkdf-hmac-sha256` should
|
||||||
|
be avoided whenever possible: if both parties support `hkdf-hmac-sha256.v2`,
|
||||||
|
then `hkdf-hmac-sha256` MUST not be used.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
###### SAS HKDF calculation
|
||||||
|
|
||||||
In all of the SAS methods, HKDF is as defined in [RFC
|
In all of the SAS methods, HKDF is as defined in [RFC
|
||||||
5869](https://tools.ietf.org/html/rfc5869) and uses the previously
|
5869](https://tools.ietf.org/html/rfc5869) and uses the previously
|
||||||
|
|
@ -771,15 +838,15 @@ is the concatenation of:
|
||||||
- The Device ID of the device which sent the
|
- The Device ID of the device which sent the
|
||||||
`m.key.verification.start` message, followed by `|`.
|
`m.key.verification.start` message, followed by `|`.
|
||||||
- The public key from the `m.key.verification.key` message sent by
|
- The public key from the `m.key.verification.key` message sent by
|
||||||
the device which sent the `m.key.verification.start` message,
|
the device which sent the `m.key.verification.start` message, encoded as
|
||||||
followed by `|`.
|
unpadded base64, followed by `|`.
|
||||||
- The Matrix ID of the user who sent the `m.key.verification.accept`
|
- The Matrix ID of the user who sent the `m.key.verification.accept`
|
||||||
message, followed by `|`.
|
message, followed by `|`.
|
||||||
- The Device ID of the device which sent the
|
- The Device ID of the device which sent the
|
||||||
`m.key.verification.accept` message, followed by `|`.
|
`m.key.verification.accept` message, followed by `|`.
|
||||||
- The public key from the `m.key.verification.key` message sent by
|
- The public key from the `m.key.verification.key` message sent by
|
||||||
the device which sent the `m.key.verification.accept` message,
|
the device which sent the `m.key.verification.accept` message, encoded as
|
||||||
followed by `|`.
|
unpadded base64, followed by `|`.
|
||||||
- The `transaction_id` being used.
|
- The `transaction_id` being used.
|
||||||
|
|
||||||
When the `key_agreement_protocol` is the deprecated method `curve25519`,
|
When the `key_agreement_protocol` is the deprecated method `curve25519`,
|
||||||
|
|
@ -804,23 +871,9 @@ HKDF is used over the plain shared secret as it results in a harder
|
||||||
attack as well as more uniform data to work with.
|
attack as well as more uniform data to work with.
|
||||||
{{% /boxes/rationale %}}
|
{{% /boxes/rationale %}}
|
||||||
|
|
||||||
For verification of each party's device keys, HKDF is as defined in RFC
|
|
||||||
5869 and uses SHA-256 as the hash function. The shared secret is
|
|
||||||
supplied as the input keying material. No salt is used, and in the info
|
|
||||||
parameter is the concatenation of:
|
|
||||||
|
|
||||||
- The string `MATRIX_KEY_VERIFICATION_MAC`.
|
|
||||||
- The Matrix ID of the user whose key is being MAC-ed.
|
|
||||||
- The Device ID of the device sending the MAC.
|
|
||||||
- The Matrix ID of the other user.
|
|
||||||
- The Device ID of the device receiving the MAC.
|
|
||||||
- The `transaction_id` being used.
|
|
||||||
- The Key ID of the key being MAC-ed, or the string `KEY_IDS` if the
|
|
||||||
item being MAC-ed is the list of key IDs.
|
|
||||||
|
|
||||||
###### SAS method: `decimal`
|
###### SAS method: `decimal`
|
||||||
|
|
||||||
Generate 5 bytes using [HKDF](#hkdf-calculation) then take sequences of 13 bits
|
Generate 5 bytes using [HKDF](#sas-hkdf-calculation) then take sequences of 13 bits
|
||||||
to convert to decimal numbers (resulting in 3 numbers between 0 and 8191
|
to convert to decimal numbers (resulting in 3 numbers between 0 and 8191
|
||||||
inclusive each). Add 1000 to each calculated number.
|
inclusive each). Add 1000 to each calculated number.
|
||||||
|
|
||||||
|
|
@ -838,7 +891,7 @@ separator, such as dashes, or with the numbers on individual lines.
|
||||||
|
|
||||||
###### SAS method: `emoji`
|
###### SAS method: `emoji`
|
||||||
|
|
||||||
Generate 6 bytes using [HKDF](#hkdf-calculation) then split the first 42 bits
|
Generate 6 bytes using [HKDF](#sas-hkdf-calculation) then split the first 42 bits
|
||||||
into 7 groups of 6 bits, similar to how one would base64 encode
|
into 7 groups of 6 bits, similar to how one would base64 encode
|
||||||
something. Convert each group of 6 bits to a number and use the
|
something. Convert each group of 6 bits to a number and use the
|
||||||
following table to get the corresponding emoji:
|
following table to get the corresponding emoji:
|
||||||
|
|
@ -847,7 +900,7 @@ following table to get the corresponding emoji:
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
This table is available as JSON at
|
This table is available as JSON at
|
||||||
<https://github.com/matrix-org/matrix-doc/blob/master/data-definitions/sas-emoji.json>
|
<https://github.com/matrix-org/matrix-spec/blob/main/data-definitions/sas-emoji.json>.
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
{{% boxes/rationale %}}
|
{{% boxes/rationale %}}
|
||||||
|
|
@ -916,7 +969,7 @@ she can trust Bob's device if:
|
||||||
|
|
||||||
The following diagram illustrates how keys are signed:
|
The following diagram illustrates how keys are signed:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+------------------+ .................. +----------------+
|
+------------------+ .................. +----------------+
|
||||||
| +--------------+ | .................. : | +------------+ |
|
| +--------------+ | .................. : | +------------+ |
|
||||||
| | v v v : : v v v | |
|
| | v v v : : v v v | |
|
||||||
|
|
@ -947,7 +1000,7 @@ the user who created them.
|
||||||
The following diagram illustrates Alice's view, hiding the keys and
|
The following diagram illustrates Alice's view, hiding the keys and
|
||||||
signatures that she cannot see:
|
signatures that she cannot see:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+------------------+ +----------------+ +----------------+
|
+------------------+ +----------------+ +----------------+
|
||||||
| +--------------+ | | | | +------------+ |
|
| +--------------+ | | | | +------------+ |
|
||||||
| | v v | v v v | |
|
| | v v | v v v | |
|
||||||
|
|
@ -1071,7 +1124,7 @@ The process between Alice and Bob verifying each other would be:
|
||||||
framework as described above.
|
framework as described above.
|
||||||
3. Alice's client displays a QR code that Bob is able to scan if Bob's client
|
3. Alice's client displays a QR code that Bob is able to scan if Bob's client
|
||||||
indicated the ability to scan, an option to scan Bob's QR code if her client
|
indicated the ability to scan, an option to scan Bob's QR code if her client
|
||||||
is able to scan. Bob's client prompts displays a QR code that Alice can
|
is able to scan. Bob's client displays a QR code that Alice can
|
||||||
scan if Alice's client indicated the ability to scan, and an option to scan
|
scan if Alice's client indicated the ability to scan, and an option to scan
|
||||||
Alice's QR code if his client is able to scan. The format for the QR code
|
Alice's QR code if his client is able to scan. The format for the QR code
|
||||||
is described below. Other options, like starting SAS Emoji verification,
|
is described below. Other options, like starting SAS Emoji verification,
|
||||||
|
|
@ -1126,10 +1179,16 @@ The process between Alice and Bob verifying each other would be:
|
||||||
|
|
||||||
###### QR code format
|
###### QR code format
|
||||||
|
|
||||||
The QR codes to be displayed and scanned using this format will encode binary
|
The QR codes to be displayed and scanned MUST be
|
||||||
strings in the general form:
|
compatible with [ISO/IEC 18004:2015](https://www.iso.org/standard/62021.html) and
|
||||||
|
contain a single segment that uses the byte mode encoding.
|
||||||
|
|
||||||
- the ASCII string `MATRIX`
|
The error correction level can be chosen by the device displaying the QR code.
|
||||||
|
|
||||||
|
The binary segment MUST be of the following form:
|
||||||
|
|
||||||
|
- the string `MATRIX` encoded as one ASCII byte per character (i.e. `0x4D`,
|
||||||
|
`0x41`, `0x54`, `0x52`, `0x49`, `0x58`)
|
||||||
- one byte indicating the QR code version (must be `0x02`)
|
- one byte indicating the QR code version (must be `0x02`)
|
||||||
- one byte indicating the QR code verification mode. Should be one of the
|
- one byte indicating the QR code verification mode. Should be one of the
|
||||||
following values:
|
following values:
|
||||||
|
|
@ -1141,24 +1200,25 @@ strings in the general form:
|
||||||
request event, encoded as:
|
request event, encoded as:
|
||||||
- two bytes in network byte order (big-endian) indicating the length in
|
- two bytes in network byte order (big-endian) indicating the length in
|
||||||
bytes of the ID as a UTF-8 string
|
bytes of the ID as a UTF-8 string
|
||||||
- the ID as a UTF-8 string
|
- the ID encoded as a UTF-8 string
|
||||||
- the first key, as 32 bytes. The key to use depends on the mode field:
|
- the first key, as 32 bytes. The key to use depends on the mode field:
|
||||||
- if `0x00` or `0x01`, then the current user's own master cross-signing public key
|
- if `0x00` or `0x01`, then the current user's own master cross-signing public key
|
||||||
- if `0x02`, then the current device's device key
|
- if `0x02`, then the current device's Ed25519 signing key
|
||||||
- the second key, as 32 bytes. The key to use depends on the mode field:
|
- the second key, as 32 bytes. The key to use depends on the mode field:
|
||||||
- if `0x00`, then what the device thinks the other user's master
|
- if `0x00`, then what the device thinks the other user's master
|
||||||
cross-signing key is
|
cross-signing public key is
|
||||||
- if `0x01`, then what the device thinks the other device's device key is
|
- if `0x01`, then what the device thinks the other device's Ed25519 signing
|
||||||
- if `0x02`, then what the device thinks the user's master cross-signing key
|
public key is
|
||||||
is
|
- if `0x02`, then what the device thinks the user's master cross-signing public
|
||||||
- a random shared secret, as a byte string. It is suggested to use a secret
|
key is
|
||||||
|
- a random shared secret, as a sequence of bytes. It is suggested to use a secret
|
||||||
that is about 8 bytes long. Note: as we do not share the length of the
|
that is about 8 bytes long. Note: as we do not share the length of the
|
||||||
secret, and it is not a fixed size, clients will just use the remainder of
|
secret, and it is not a fixed size, clients will just use the remainder of
|
||||||
binary string as the shared secret.
|
binary segment as the shared secret.
|
||||||
|
|
||||||
For example, if Alice displays a QR code encoding the following binary string:
|
For example, if Alice displays a QR code encoding the following binary data:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
"MATRIX" |ver|mode| len | event ID
|
"MATRIX" |ver|mode| len | event ID
|
||||||
4D 41 54 52 49 58 02 00 00 2D 21 41 42 43 44 ...
|
4D 41 54 52 49 58 02 00 00 2D 21 41 42 43 44 ...
|
||||||
| user's cross-signing key | other user's cross-signing key | shared secret
|
| user's cross-signing key | other user's cross-signing key | shared secret
|
||||||
|
|
@ -1218,10 +1278,10 @@ tries to read a message that it does not have keys for, it may request
|
||||||
the key from the server and decrypt it. Backups are per-user, and users
|
the key from the server and decrypt it. Backups are per-user, and users
|
||||||
may replace backups with new backups.
|
may replace backups with new backups.
|
||||||
|
|
||||||
In contrast with [Key requests](#key-requests), Server-side key backups
|
In contrast with [key requests](#key-requests), server-side key backups do not
|
||||||
do not require another device to be online from which to request keys.
|
require another device to be online from which to request keys. However, as
|
||||||
However, as the session keys are stored on the server encrypted, it
|
the session keys are stored on the server encrypted, the client requires a
|
||||||
requires users to enter a decryption key to decrypt the session keys.
|
[decryption key](#decryption-key) to decrypt the session keys.
|
||||||
|
|
||||||
To create a backup, a client will call [POST
|
To create a backup, a client will call [POST
|
||||||
/\_matrix/client/v3/room\_keys/version](#post_matrixclientv3room_keysversion) and define how the keys are to
|
/\_matrix/client/v3/room\_keys/version](#post_matrixclientv3room_keysversion) and define how the keys are to
|
||||||
|
|
@ -1242,7 +1302,7 @@ Clients must only store keys in backups after they have ensured that the
|
||||||
|
|
||||||
- checking that it is signed by the user's [master cross-signing
|
- checking that it is signed by the user's [master cross-signing
|
||||||
key](#cross-signing) or by a verified device belonging to the same user, or
|
key](#cross-signing) or by a verified device belonging to the same user, or
|
||||||
- by deriving the public key from a private key that it obtained from a trusted
|
- deriving the public key from a private key that it obtained from a trusted
|
||||||
source. Trusted sources for the private key include the user entering the
|
source. Trusted sources for the private key include the user entering the
|
||||||
key, retrieving the key stored in [secret storage](#secret-storage), or
|
key, retrieving the key stored in [secret storage](#secret-storage), or
|
||||||
obtaining the key via [secret sharing](#sharing) from a verified device
|
obtaining the key via [secret sharing](#sharing) from a verified device
|
||||||
|
|
@ -1259,31 +1319,24 @@ replace it with the new key based on the key metadata as follows:
|
||||||
- and finally, if `is_verified` and `first_message_index` are equal,
|
- and finally, if `is_verified` and `first_message_index` are equal,
|
||||||
then it will keep the key with a lower `forwarded_count`.
|
then it will keep the key with a lower `forwarded_count`.
|
||||||
|
|
||||||
###### Recovery key
|
###### Decryption key
|
||||||
|
|
||||||
If the recovery key (the private half of the backup encryption key) is
|
Normally, the decryption key (i.e. the secret part of the encryption key) is
|
||||||
presented to the user to save, it is presented as a string constructed
|
stored on the server or shared with other devices using the [Secrets](#secrets)
|
||||||
as follows:
|
module. When doing so, it is identified using the name `m.megolm_backup.v1`,
|
||||||
|
and the key is base64-encoded before being encrypted.
|
||||||
|
|
||||||
1. The 256-bit curve25519 private key is prepended by the bytes `0x8B`
|
If the backup decryption key is given directly to the user, the key should be
|
||||||
and `0x01`
|
presented as a string using the common [cryptographic key
|
||||||
2. All the bytes in the string above, including the two header bytes,
|
representation](/appendices/#cryptographic-key-representation).
|
||||||
are XORed together to form a parity byte. This parity byte is
|
|
||||||
appended to the byte string.
|
|
||||||
3. The byte string is encoded using base58, using the same [mapping as
|
|
||||||
is used for Bitcoin
|
|
||||||
addresses](https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart),
|
|
||||||
that is, using the alphabet
|
|
||||||
`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`.
|
|
||||||
4. A space should be added after every 4th character.
|
|
||||||
|
|
||||||
When reading in a recovery key, clients must disregard whitespace, and
|
{{% boxes/note %}}
|
||||||
perform the reverse of steps 1 through 3.
|
The backup decryption key was previously referred to as a "recovery
|
||||||
|
key". However, this conflicted with common practice in client user
|
||||||
The recovery key can also be stored on the server or shared with other devices
|
interfaces, which often use the term "recovery key" to refer to the [secret
|
||||||
using the [Secrets](#secrets) module. When doing so, it is identified using the
|
storage](#storage) key. The term "recovery key" is no longer used in this
|
||||||
name `m.megolm_backup.v1`, and the key is base64-encoded before being
|
specification.
|
||||||
encrypted.
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
###### Backup algorithm: `m.megolm_backup.v1.curve25519-aes-sha2`
|
###### Backup algorithm: `m.megolm_backup.v1.curve25519-aes-sha2`
|
||||||
|
|
||||||
|
|
@ -1296,7 +1349,7 @@ the following format:
|
||||||
The `session_data` field in the backups is constructed as follows:
|
The `session_data` field in the backups is constructed as follows:
|
||||||
|
|
||||||
1. Encode the session key to be backed up as a JSON object using the
|
1. Encode the session key to be backed up as a JSON object using the
|
||||||
`SessionData` format defined below.
|
`BackedUpSessionData` format defined below.
|
||||||
|
|
||||||
2. Generate an ephemeral curve25519 key, and perform an ECDH with the
|
2. Generate an ephemeral curve25519 key, and perform an ECDH with the
|
||||||
ephemeral key and the backup's public key to generate a shared
|
ephemeral key and the backup's public key to generate a shared
|
||||||
|
|
@ -1313,10 +1366,18 @@ The `session_data` field in the backups is constructed as follows:
|
||||||
PKCS\#7 padding. This encrypted data, encoded using unpadded base64,
|
PKCS\#7 padding. This encrypted data, encoded using unpadded base64,
|
||||||
becomes the `ciphertext` property of the `session_data`.
|
becomes the `ciphertext` property of the `session_data`.
|
||||||
|
|
||||||
5. Pass the raw encrypted data (prior to base64 encoding) through
|
5. Pass an empty string through HMAC-SHA-256 using the MAC key generated above.
|
||||||
HMAC-SHA-256 using the MAC key generated above. The first 8 bytes of
|
The first 8 bytes of the resulting MAC are base64-encoded, and become the
|
||||||
the resulting MAC are base64-encoded, and become the `mac` property
|
`mac` property of the `session_data`.
|
||||||
of the `session_data`.
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
Step 5 was intended to pass the raw encrypted data, but due to a bug in libolm,
|
||||||
|
all implementations have since passed an empty string instead.
|
||||||
|
|
||||||
|
Future versions of the spec will fix this problem. See
|
||||||
|
[MSC4048](https://github.com/matrix-org/matrix-spec-proposals/pull/4048) for a
|
||||||
|
potential new key backup algorithm version that would fix this issue.
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
{{% definition path="api/client-server/definitions/key_backup_session_data" %}}
|
{{% definition path="api/client-server/definitions/key_backup_session_data" %}}
|
||||||
|
|
||||||
|
|
@ -1366,7 +1427,7 @@ user-supplied passphrase, and is created as follows:
|
||||||
|
|
||||||
###### Key export format
|
###### Key export format
|
||||||
|
|
||||||
The exported sessions are formatted as a JSON array of `SessionData`
|
The exported sessions are formatted as a JSON array of `ExportedSessionData`
|
||||||
objects described as follows:
|
objects described as follows:
|
||||||
|
|
||||||
{{% definition path="api/client-server/definitions/megolm_export_session_data" %}}
|
{{% definition path="api/client-server/definitions/megolm_export_session_data" %}}
|
||||||
|
|
@ -1396,8 +1457,8 @@ readers without adding any useful extra information.
|
||||||
##### `m.olm.v1.curve25519-aes-sha2`
|
##### `m.olm.v1.curve25519-aes-sha2`
|
||||||
|
|
||||||
The name `m.olm.v1.curve25519-aes-sha2` corresponds to version 1 of the
|
The name `m.olm.v1.curve25519-aes-sha2` corresponds to version 1 of the
|
||||||
Olm ratchet, as defined by the [Olm
|
Olm ratchet, as defined by the [Olm specification](/olm-megolm/olm).
|
||||||
specification](http://matrix.org/docs/spec/olm.html). This uses:
|
This uses:
|
||||||
|
|
||||||
- Curve25519 for the initial key agreement.
|
- Curve25519 for the initial key agreement.
|
||||||
- HKDF-SHA-256 for ratchet key derivation.
|
- HKDF-SHA-256 for ratchet key derivation.
|
||||||
|
|
@ -1451,38 +1512,11 @@ message.
|
||||||
|
|
||||||
The plaintext payload is of the form:
|
The plaintext payload is of the form:
|
||||||
|
|
||||||
```json
|
{{% definition path="api/client-server/definitions/olm_payload" %}}
|
||||||
{
|
|
||||||
"type": "<type of the plaintext event>",
|
|
||||||
"content": "<content for the plaintext event>",
|
|
||||||
"sender": "<sender_user_id>",
|
|
||||||
"recipient": "<recipient_user_id>",
|
|
||||||
"recipient_keys": {
|
|
||||||
"ed25519": "<our_ed25519_key>"
|
|
||||||
},
|
|
||||||
"keys": {
|
|
||||||
"ed25519": "<sender_ed25519_key>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The type and content of the plaintext message event are given in the
|
The type and content of the plaintext message event are given in the
|
||||||
payload.
|
payload.
|
||||||
|
|
||||||
Other properties are included in order to prevent an attacker from
|
|
||||||
publishing someone else's curve25519 keys as their own and subsequently
|
|
||||||
claiming to have sent messages which they didn't. `sender` must
|
|
||||||
correspond to the user who sent the event, `recipient` to the local
|
|
||||||
user, and `recipient_keys` to the local ed25519 key.
|
|
||||||
|
|
||||||
Clients must confirm that the `sender_key` and the `ed25519` field value
|
|
||||||
under the `keys` property match the keys returned by [`/keys/query`](/client-server-api/#post_matrixclientv3keysquery) for
|
|
||||||
the given user, and must also verify the signature of the keys from the
|
|
||||||
`/keys/query` response. Without this check, a client cannot be sure that
|
|
||||||
the sender device owns the private part of the ed25519 key it claims to
|
|
||||||
have in the Olm payload. This is crucial when the ed25519 key corresponds
|
|
||||||
to a verified device.
|
|
||||||
|
|
||||||
If a client has multiple sessions established with another device, it
|
If a client has multiple sessions established with another device, it
|
||||||
should use the session from which it last received and successfully
|
should use the session from which it last received and successfully
|
||||||
decrypted a message. For these purposes, a session that has not received
|
decrypted a message. For these purposes, a session that has not received
|
||||||
|
|
@ -1492,6 +1526,68 @@ maximum number of olm sessions that it will maintain for each device,
|
||||||
and expiring sessions on a Least Recently Used basis. The maximum number
|
and expiring sessions on a Least Recently Used basis. The maximum number
|
||||||
of olm sessions maintained per device should be at least 4.
|
of olm sessions maintained per device should be at least 4.
|
||||||
|
|
||||||
|
###### Validation of incoming decrypted events
|
||||||
|
|
||||||
|
{{% changed-in v="1.15" %}} Existing checks made more explicit, and checks for `sender_device_keys` added.
|
||||||
|
|
||||||
|
After decrypting an incoming encrypted event, clients MUST apply the
|
||||||
|
following checks:
|
||||||
|
|
||||||
|
1. The `sender` property in the decrypted content must match the
|
||||||
|
`sender` of the event.
|
||||||
|
2. The `keys.ed25519` property in the decrypted content must match
|
||||||
|
the `sender_key` property in the cleartext `m.room.encrypted`
|
||||||
|
event body.
|
||||||
|
3. The `recipient` property in the decrypted content must match
|
||||||
|
the user ID of the local user.
|
||||||
|
4. The `recipient_keys.ed25519` property in the decrypted content
|
||||||
|
must match the client device's [Ed25519 signing key](#device-keys).
|
||||||
|
5. Where `sender_device_keys` is present in the decrypted content:
|
||||||
|
1. `sender_device_keys.user_id` must also match the `sender`
|
||||||
|
of the event.
|
||||||
|
2. `sender_device_keys.keys.ed25519:<device_id>` must also match
|
||||||
|
the `sender_key` property in the cleartext `m.room.encrypted`
|
||||||
|
event body.
|
||||||
|
3. `sender_device_keys.keys.curve25519:<device_id>` must match
|
||||||
|
the Curve25519 key used to establish the Olm session.
|
||||||
|
4. The `sender_device_keys` structure must have a valid signature
|
||||||
|
from the key with ID `ed25519:<device_id>` (i.e., the sending
|
||||||
|
device's Ed25519 key).
|
||||||
|
|
||||||
|
Any event that does not comply with these checks MUST be discarded.
|
||||||
|
|
||||||
|
###### Verification of the sending user for incoming events
|
||||||
|
|
||||||
|
{{% added-in v="1.15" %}}
|
||||||
|
|
||||||
|
In addition, for each Olm session, clients MUST verify that the
|
||||||
|
Curve25519 key used to establish the Olm session does indeed belong
|
||||||
|
to the claimed `sender`. This requires a signed "device keys" structure
|
||||||
|
for that Curve25519 key, which can be obtained in one of two ways:
|
||||||
|
|
||||||
|
1. An Olm message may be received with a `sender_device_keys` property
|
||||||
|
in the decrypted content.
|
||||||
|
2. The keys are returned via a [`/keys/query`](#post_matrixclientv3keysquery)
|
||||||
|
request. Note that both the Curve25519 key **and** the Ed25519 key in
|
||||||
|
the returned device keys structure must match those used in an
|
||||||
|
Olm-encrypted event as above. (In particular, the Ed25519 key must
|
||||||
|
be present in the **encrypted** content of an Olm-encrypted event
|
||||||
|
to prevent an attacker from claiming another user's Curve25519 key
|
||||||
|
as their own.)
|
||||||
|
|
||||||
|
Ownership of the Curve25519 key is then established in one of two ways:
|
||||||
|
|
||||||
|
1. Via [cross-signing](#cross-signing). For this to be sufficient, the
|
||||||
|
device keys structure must be signed by the sender's self-signing key,
|
||||||
|
and that self-signing key must itself have been validated (either via
|
||||||
|
[explicit verification](#device-verification) or a "trust on first use" (TOFU) mechanism).
|
||||||
|
2. Via explicit verification of the device's Ed25519 signing key, as
|
||||||
|
contained in the device keys structure. This is no longer recommended.
|
||||||
|
|
||||||
|
A failure to complete these verifications does not necessarily mean that
|
||||||
|
the session is bogus; however it is the case that there is no proof that
|
||||||
|
the claimed sender is accurate, and the user should be warned accordingly.
|
||||||
|
|
||||||
###### Recovering from undecryptable messages
|
###### Recovering from undecryptable messages
|
||||||
|
|
||||||
Occasionally messages may be undecryptable by clients due to a variety
|
Occasionally messages may be undecryptable by clients due to a variety
|
||||||
|
|
@ -1535,8 +1631,8 @@ This is due to a deprecation of the fields. See
|
||||||
{{% changed-in v="1.3" %}}
|
{{% changed-in v="1.3" %}}
|
||||||
|
|
||||||
The name `m.megolm.v1.aes-sha2` corresponds to version 1 of the Megolm
|
The name `m.megolm.v1.aes-sha2` corresponds to version 1 of the Megolm
|
||||||
ratchet, as defined by the [Megolm
|
ratchet, as defined by the [Megolm specification](/olm-megolm/megolm).
|
||||||
specification](http://matrix.org/docs/spec/megolm.html). This uses:
|
This uses:
|
||||||
|
|
||||||
- HMAC-SHA-256 for the hash ratchet.
|
- HMAC-SHA-256 for the hash ratchet.
|
||||||
- HKDF-SHA-256, AES-256 in CBC mode, and 8 byte truncated HMAC-SHA-256
|
- HKDF-SHA-256, AES-256 in CBC mode, and 8 byte truncated HMAC-SHA-256
|
||||||
|
|
@ -1654,7 +1750,7 @@ When a client is updating a Megolm session in its store, the client MUST ensure:
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="keys" %}}
|
{{% http-api spec="client-server" api="keys" %}}
|
||||||
|
|
||||||
##### <a name="e2e-extensions-to-sync"> Extensions to /sync
|
##### Extensions to /sync {#e2e-extensions-to-sync}
|
||||||
|
|
||||||
This module adds an optional `device_lists` property to the [`/sync`](/client-server-api/#get_matrixclientv3sync) response,
|
This module adds an optional `device_lists` property to the [`/sync`](/client-server-api/#get_matrixclientv3sync) response,
|
||||||
as specified below. The server need only populate this property for an
|
as specified below. The server need only populate this property for an
|
||||||
|
|
@ -1679,19 +1775,18 @@ property is required for inclusion, though previous versions of the
|
||||||
specification did not have it. In addition to `/versions`, this can be
|
specification did not have it. In addition to `/versions`, this can be
|
||||||
a way to identify the server's support for fallback keys.
|
a way to identify the server's support for fallback keys.
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
| Parameter | Type | Description |
|
|----------------------------------|-------------------|------------------------------------------------------------------------------------------------------------------------|
|
||||||
|----------------------------------|--------------------|------------------------------------------------------------------------------------------------------------------------|
|
| device_lists | DeviceLists | Optional. Information on e2e device updates. Note: only present on an incremental sync. |
|
||||||
| device_lists | DeviceLists | Optional. Information on e2e device updates. Note: only present on an incremental sync. |
|
| device_one_time_keys_count | {string: integer} | **Required if any unclaimed one-time keys exist.** For each key algorithm, the number of unclaimed one-time keys currently held on the server for this device. If the count for an algorithm is zero, servers MAY omit that algorithm. If the count for all algorithms is zero, servers MAY omit this parameter entirely. |
|
||||||
| device_one_time_keys_count | {string: integer} | Optional. For each key algorithm, the number of unclaimed one-time keys currently held on the server for this device. If an algorithm is unlisted, the count for that algorithm is assumed to be zero. If this entire parameter is missing, the count for all algorithms is assumed to be zero. |
|
| device_unused_fallback_key_types | [string] | **Required.** The unused fallback key algorithms. |
|
||||||
| device_unused_fallback_key_types | [string] | **Required.** The unused fallback key algorithms. |
|
|
||||||
|
|
||||||
`DeviceLists`
|
`DeviceLists`
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
|------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| changed | [string] | List of users who have updated their device identity or cross-signing keys, or who now share an encrypted room with the client since the previous sync response. |
|
| changed | [string] | List of users who have updated their device identity or cross-signing keys, or who now share an encrypted room with the client since the previous sync response. |
|
||||||
| left | [string] | List of users with whom we do not share any encrypted rooms anymore since the previous sync response. |
|
| left | [string] | List of users with whom we do not share any encrypted rooms anymore since the previous sync response. |
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
For optimal performance, Alice should be added to `changed` in Bob's
|
For optimal performance, Alice should be added to `changed` in Bob's
|
||||||
|
|
@ -1717,9 +1812,9 @@ Example response:
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"device_one_time_keys_count": {
|
"device_one_time_keys_count": {
|
||||||
"curve25519": 10,
|
|
||||||
"signed_curve25519": 20
|
"signed_curve25519": 20
|
||||||
}
|
},
|
||||||
|
"device_unused_fallback_key_types": ["signed_curve25519"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
99
content/client-server-api/modules/event_annotations.md
Normal file
99
content/client-server-api/modules/event_annotations.md
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
### Event annotations and reactions
|
||||||
|
|
||||||
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
|
#### `m.annotation` relationship type
|
||||||
|
|
||||||
|
Annotations are events that use an [event
|
||||||
|
relationship](#forming-relationships-between-events) with a `rel_type` of
|
||||||
|
`m.annotation`.
|
||||||
|
|
||||||
|
Annotations are normally used for "reactions": for example, if the user wants
|
||||||
|
to react to an event with a thumbs-up, then the client sends an annotation
|
||||||
|
event with the corresponding emoji (👍). Another potential usage is to allow
|
||||||
|
bots to send an event indicating the success or failure of a command.
|
||||||
|
|
||||||
|
Along with the normal properties `event_id` and `rel_type`, an `m.relates_to`
|
||||||
|
property with `rel_type: m.annotation` should contain a `key` that indicates the
|
||||||
|
annotation being applied. For example, when reacting with emojis, the key
|
||||||
|
contains the emoji being used.
|
||||||
|
|
||||||
|
An example `m.annotation` relationship is shown below:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"m.relates_to": {
|
||||||
|
"rel_type": "m.annotation",
|
||||||
|
"event_id": "$some_event_id",
|
||||||
|
"key": "👍"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Any `type` of event is eligible for an annotation, including state events.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
#### Events
|
||||||
|
|
||||||
|
{{% event event="m.reaction" %}}
|
||||||
|
|
||||||
|
#### Client behaviour {id="annotations-client-behaviour"}
|
||||||
|
|
||||||
|
The intention of annotations is that they are counted up, rather than being
|
||||||
|
displayed individually. Clients must keep count of the number of annotations
|
||||||
|
with a given event `type` and annotation `key` they observe for each event;
|
||||||
|
these counts are typically presented alongside the event in the timeline.
|
||||||
|
|
||||||
|
When performing this count:
|
||||||
|
|
||||||
|
* Each event `type` and annotation `key` should normally be counted
|
||||||
|
separately, though whether to actually do so is an implementation decision.
|
||||||
|
|
||||||
|
* Annotation events sent by [ignored users](#ignoring-users) should be
|
||||||
|
excluded from the count.
|
||||||
|
|
||||||
|
* Multiple identical annotations (i.e., with the same event `type` and
|
||||||
|
annotation `key`) from the same user (i.e., events with the same `sender`)
|
||||||
|
should be treated as a single annotation.
|
||||||
|
|
||||||
|
* Implementations should ignore any annotation event which refers to an event
|
||||||
|
which itself has an `m.relates_to` with `rel_type: m.annotation` or
|
||||||
|
`rel_type: m.replace`. In other words, it is not possible to annotate a
|
||||||
|
[replacement event](#event-replacements) or an annotation. Annotations should
|
||||||
|
instead refer to the original event.
|
||||||
|
|
||||||
|
* When an annotation is redacted, it is removed from the count.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
It is not possible to edit a reaction, since replacement events do not change
|
||||||
|
`m.relates_to` (see [Applying `m.new_content`](#applying-mnew_content)), and
|
||||||
|
there is no other meaningful content within `m.reaction`. If a user wishes to
|
||||||
|
change their reaction, the original reaction should be redacted and a new one
|
||||||
|
sent in its place.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
The `key` field in `m.reaction` can be any string so clients must take care to
|
||||||
|
render long reactions in a sensible manner. For example, clients can elide
|
||||||
|
overly-long reactions.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
#### Server behaviour
|
||||||
|
|
||||||
|
##### Avoiding duplicate annotations
|
||||||
|
|
||||||
|
Homeservers should prevent users from sending a second annotation for a given
|
||||||
|
event with identical event `type` and annotation `key` (unless the first event
|
||||||
|
has been redacted).
|
||||||
|
|
||||||
|
Attempts to send such an annotation should be rejected with a 400 error and an
|
||||||
|
error code of `M_DUPLICATE_ANNOTATION`.
|
||||||
|
|
||||||
|
Note that this does not guarantee that duplicate annotations will not arrive
|
||||||
|
over federation. Clients are responsible for deduplicating received
|
||||||
|
annotations when [counting annotations](#annotations-client-behaviour).
|
||||||
|
|
||||||
|
##### Server-side aggregation of `m.annotation` relationships
|
||||||
|
|
||||||
|
`m.annotation` relationships are *not*
|
||||||
|
[aggregated](#aggregations-of-child-events) by the server. In other words,
|
||||||
|
`m.annotation` is not included in the `m.relations` property.
|
||||||
|
|
@ -133,13 +133,6 @@ being overwritten entirely by `m.new_content`, with the exception of `m.relates_
|
||||||
which is left *unchanged*. Any `m.relates_to` property within `m.new_content`
|
which is left *unchanged*. Any `m.relates_to` property within `m.new_content`
|
||||||
is ignored.
|
is ignored.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
|
||||||
Note that server implementations must not *actually* overwrite
|
|
||||||
the original event's `content`: instead the server presents it as being overwritten
|
|
||||||
when it is served over the client-server API. See [Server-side replacement of content](#server-side-replacement-of-content)
|
|
||||||
below.
|
|
||||||
{{% /boxes/note %}}
|
|
||||||
|
|
||||||
For example, given a pair of events:
|
For example, given a pair of events:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
@ -195,70 +188,91 @@ replacement event.
|
||||||
|
|
||||||
##### Server-side aggregation of `m.replace` relationships
|
##### Server-side aggregation of `m.replace` relationships
|
||||||
|
|
||||||
|
{{% changed-in v="1.7" %}}
|
||||||
|
|
||||||
Note that there can be multiple events with an `m.replace` relationship to a
|
Note that there can be multiple events with an `m.replace` relationship to a
|
||||||
given event (for example, if an event is edited multiple times). These should
|
given event (for example, if an event is edited multiple times). These should
|
||||||
be [aggregated](#aggregations) by the homeserver.
|
be [aggregated](#aggregations-of-child-events) by the homeserver.
|
||||||
|
|
||||||
The aggregation format of `m.replace` relationships gives the `event_id`,
|
The aggregation format of `m.replace` relationships gives the **most recent**
|
||||||
`origin_server_ts`, and `sender` of the **most recent** replacement event. The
|
valid replacement event, formatted [as normal](#room-event-format).
|
||||||
most recent event is determined by comparing `origin_server_ts`; if two or more
|
|
||||||
replacement events have identical `origin_server_ts`, the event with the
|
The most recent event is determined by comparing `origin_server_ts`; if two or
|
||||||
|
more replacement events have identical `origin_server_ts`, the event with the
|
||||||
lexicographically largest `event_id` is treated as more recent.
|
lexicographically largest `event_id` is treated as more recent.
|
||||||
|
|
||||||
This aggregation is bundled under the `unsigned` property as `m.relations` for any
|
As with any other aggregation of child events, the `m.replace` aggregation is
|
||||||
event that is the target of an `m.replace` relationship. For example:
|
included under the `m.relations` property in `unsigned` for any event that is
|
||||||
|
the target of an `m.replace` relationship. For example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"event_id": "$original_event_id",
|
"event_id": "$original_event_id",
|
||||||
// irrelevant fields not shown
|
"type": "m.room.message",
|
||||||
|
"content": {
|
||||||
|
"body": "I really like cake",
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"formatted_body": "I really like cake"
|
||||||
|
},
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"m.relations": {
|
"m.relations": {
|
||||||
"m.replace": {
|
"m.replace": {
|
||||||
"event_id": "$latest_edit_event_id",
|
"event_id": "$latest_edit_event_id",
|
||||||
"origin_server_ts": 1649772304313,
|
"origin_server_ts": 1649772304313,
|
||||||
"sender": "@editing_user:localhost"
|
"sender": "@editing_user:localhost"
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {
|
||||||
|
"body": "* I really like *chocolate* cake",
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"m.new_content": {
|
||||||
|
"body": "I really like *chocolate* cake",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"m.relates_to": {
|
||||||
|
"rel_type": "m.replace",
|
||||||
|
"event_id": "$original_event_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// irrelevant fields not shown
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If the original event is
|
If the original event is [redacted](#redactions), any
|
||||||
[redacted](#redactions), any
|
|
||||||
`m.replace` relationship should **not** be bundled with it (whether or not any
|
`m.replace` relationship should **not** be bundled with it (whether or not any
|
||||||
subsequent replacements are themselves redacted). Note that this behaviour is
|
subsequent replacements are themselves redacted). Note that this behaviour is
|
||||||
specific to the `m.replace` relationship. See also [redactions of edited
|
specific to the `m.replace` relationship. See also [redactions of edited
|
||||||
events](#redactions-of-edited-events) below.
|
events](#redactions-of-edited-events) below.
|
||||||
|
|
||||||
##### Server-side replacement of content
|
**Note:** the `content` of the original event is left intact. In particular servers
|
||||||
|
should **not** replace the content with that of the replacement event.
|
||||||
|
|
||||||
Whenever an `m.replace` is to be bundled with an event as above, the server
|
{{% boxes/rationale %}}
|
||||||
should also modify the content of the original event according to the
|
In previous versions of the specification, servers were expected to replace the
|
||||||
`m.new_content` of the most recent replacement event (determined as above).
|
content of an edited event whenever it was served to clients (with the
|
||||||
|
exception of the
|
||||||
An exception applies to [`GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}`](#get_matrixclientv3roomsroomideventeventid),
|
[`GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}`](#get_matrixclientv3roomsroomideventeventid)
|
||||||
which should return the unmodified event (though the relationship should still
|
endpoint). However, that behaviour made reliable client-side implementation
|
||||||
be bundled, as described above).
|
difficult, and servers should no longer make this replacement.
|
||||||
|
{{% /boxes/rationale %}}
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
Clients can often ignore `m.replace` events, because any events returned
|
Since the server will not replace the content of any edited events, clients
|
||||||
by the server to the client will be updated by the server to account for
|
should take note of any replacement events they receive, and apply the
|
||||||
subsequent edits.
|
replacement whenever possible and appropriate.
|
||||||
|
|
||||||
However, clients should apply the replacement themselves when the server is
|
|
||||||
unable to do so. This happens in the following situations:
|
|
||||||
|
|
||||||
* The client has already received and stored the original event before the
|
|
||||||
message edit event arrives.
|
|
||||||
|
|
||||||
* The original event (and hence its replacement) are encrypted.
|
|
||||||
|
|
||||||
Client authors are reminded to take note of the requirements for [Validity of
|
Client authors are reminded to take note of the requirements for [Validity of
|
||||||
replacement events](#validity-of-replacement-events), and to ignore any
|
replacement events](#validity-of-replacement-events), and to ignore any
|
||||||
invalid replacement events that are received.
|
invalid replacement events that are received.
|
||||||
|
|
||||||
|
Clients should render the content of the **most recent** valid replacement event. The
|
||||||
|
most recent event is determined by comparing `origin_server_ts`; if two or more
|
||||||
|
replacement events have identical `origin_server_ts`, the event with the
|
||||||
|
lexicographically largest `event_id` is treated as more recent.
|
||||||
|
|
||||||
##### Permalinks
|
##### Permalinks
|
||||||
|
|
||||||
When creating [links](/appendices/#uris) to events (also known as permalinks),
|
When creating [links](/appendices/#uris) to events (also known as permalinks),
|
||||||
|
|
@ -280,26 +294,92 @@ subsequent edits, from the visible timeline. In this situation, homeservers
|
||||||
will return an empty `content` for the original event as with any other
|
will return an empty `content` for the original event as with any other
|
||||||
redacted event, and as
|
redacted event, and as
|
||||||
[above](#server-side-aggregation-of-mreplace-relationships) the replacement
|
[above](#server-side-aggregation-of-mreplace-relationships) the replacement
|
||||||
events will not be bundled with the original event. Note that the subsequent edits are
|
events will not be included in the aggregation bundled with the original
|
||||||
not actually redacted themselves: they simply serve no purpose within the visible timeline.
|
event. Note that the subsequent edits are not actually redacted themselves:
|
||||||
|
they simply serve no purpose within the visible timeline.
|
||||||
|
|
||||||
|
#### Edits of events with mentions
|
||||||
|
|
||||||
|
When editing an event with [user and room mentions](#user-and-room-mentions) the
|
||||||
|
replacement event will have two `m.mentions` properties:
|
||||||
|
|
||||||
|
* One at the top-level of the `content`, which should contain mentions due to
|
||||||
|
this edit revision.
|
||||||
|
* One inside the `m.new_content` property, which should contain the resolved mentions
|
||||||
|
for the final version of the event.
|
||||||
|
|
||||||
|
The difference between these properties ensures that users will not be notified
|
||||||
|
for each edit revision of an event, but allows for new users to be mentioned (or
|
||||||
|
for re-notifying if the sending client feels a large enough revision was made).
|
||||||
|
|
||||||
|
For example, if there is an event mentioning Alice:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"event_id": "$original_event",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {
|
||||||
|
"body": "Hello Alice!",
|
||||||
|
"m.mentions": {
|
||||||
|
"user_ids": ["@alice:example.org"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And an edit to also mention Bob:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "* Hello Alice & Bob!",
|
||||||
|
"m.mentions": {
|
||||||
|
"user_ids": [
|
||||||
|
// Include only the newly mentioned user.
|
||||||
|
"@bob:example.org"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"m.new_content": {
|
||||||
|
"body": "Hello Alice & Bob!",
|
||||||
|
"m.mentions": {
|
||||||
|
"user_ids": [
|
||||||
|
// Include all of the mentioned users.
|
||||||
|
"@alice:example.org",
|
||||||
|
"@bob:example.org"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"m.relates_to": {
|
||||||
|
"rel_type": "m.replace",
|
||||||
|
"event_id": "$original_event"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// other fields as required by events
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If an edit revision removes a user's mention then that user's Matrix ID should be
|
||||||
|
included in neither `m.mentions` property.
|
||||||
|
|
||||||
|
Clients may also wish to modify the [client behaviour](#user-and-room-mentions) of
|
||||||
|
determining if an event mentions the current user by checking the `m.mentions`
|
||||||
|
property under `m.new_content`.
|
||||||
|
|
||||||
#### Edits of replies
|
#### Edits of replies
|
||||||
|
|
||||||
Some particular constraints apply to events which replace a
|
A particular constraint applies to events which replace a [reply](#rich-replies):
|
||||||
[reply](#rich-replies). In particular:
|
in contrast to the original reply, there should be no `m.in_reply_to` property
|
||||||
|
in the `m.relates_to` object, since it would be redundant (see
|
||||||
|
[Applying `m.new_content`](#applying-mnew_content) above, which notes that the
|
||||||
|
original event's `m.relates_to` is preserved), as well as being contrary to the
|
||||||
|
spirit of the event relationships mechanism which expects only one "parent" per
|
||||||
|
event.
|
||||||
|
|
||||||
* In contrast to the original reply, there should be no `m.in_reply_to`
|
{{% boxes/note %}}
|
||||||
property in the the `m.relates_to` object, since it would be redundant (see
|
{{% changed-in v="1.13" %}}
|
||||||
[Applying `m.new_content`](#applying-mnew_content) above, which notes that
|
In previous versions of the specification, events which replace a [reply](#rich-replies)
|
||||||
the original event's `m.relates_to` is preserved), as well as being contrary
|
could include a fallback in the `content`. This is no longer the case.
|
||||||
to the spirit of the event relationships mechanism which expects only one
|
{{% /boxes/note %}}
|
||||||
"parent" per event.
|
|
||||||
|
|
||||||
* `m.new_content` should **not** contain any [reply
|
|
||||||
fallback](#fallbacks-for-rich-replies),
|
|
||||||
since it is assumed that any client which can handle edits can also display
|
|
||||||
replies natively. However, the `content` of the replacement event should provide
|
|
||||||
fallback content for clients which support neither rich replies nor edits.
|
|
||||||
|
|
||||||
An example of an edit to a reply is as follows:
|
An example of an edit to a reply is as follows:
|
||||||
|
|
||||||
|
|
@ -308,15 +388,11 @@ An example of an edit to a reply is as follows:
|
||||||
"type": "m.room.message",
|
"type": "m.room.message",
|
||||||
// irrelevant fields not shown
|
// irrelevant fields not shown
|
||||||
"content": {
|
"content": {
|
||||||
"body": "> <@alice:example.org> question\n\n* reply",
|
"body": "* reply",
|
||||||
"msgtype": "m.text",
|
"msgtype": "m.text",
|
||||||
"format": "org.matrix.custom.html",
|
|
||||||
"formatted_body": "<mx-reply><blockquote><a href=\"https://matrix.to/#/!somewhere:example.org/$event:example.org\">In reply to</a> <a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a><br />question</blockquote></mx-reply>* reply",
|
|
||||||
"m.new_content": {
|
"m.new_content": {
|
||||||
"body": "reply",
|
"body": "reply",
|
||||||
"msgtype": "m.text",
|
"msgtype": "m.text",
|
||||||
"format": "org.matrix.custom.html",
|
|
||||||
"formatted_body": "reply"
|
|
||||||
},
|
},
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
"rel_type": "m.replace",
|
"rel_type": "m.replace",
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,20 @@ rather than allowing all homeservers to enforce the rules on each other.
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
for retrieving events:
|
for retrieving events and associated media:
|
||||||
|
|
||||||
* [GET /rooms/{roomId}/state](#get_matrixclientv3roomsroomidstate)
|
* [GET /rooms/{roomId}/state](#get_matrixclientv3roomsroomidstate)
|
||||||
* [GET /rooms/{roomId}/context/{eventId}](#get_matrixclientv3roomsroomidcontexteventid)
|
* [GET /rooms/{roomId}/context/{eventId}](#get_matrixclientv3roomsroomidcontexteventid)
|
||||||
* [GET /rooms/{roomId}/event/{eventId}](#get_matrixclientv3roomsroomideventeventid)
|
* [GET /rooms/{roomId}/event/{eventId}](#get_matrixclientv3roomsroomideventeventid)
|
||||||
* [GET /rooms/{roomId}/state/{eventType}/{stateKey}](#get_matrixclientv3roomsroomidstateeventtypestatekey)
|
* [GET /rooms/{roomId}/state/{eventType}/{stateKey}](#get_matrixclientv3roomsroomidstateeventtypestatekey)
|
||||||
* [GET /rooms/{roomId}/messages](#get_matrixclientv3roomsroomidmessages)
|
* [GET /rooms/{roomId}/messages](#get_matrixclientv3roomsroomidmessages)
|
||||||
* {{< added-in v="1.1" >}} [GET /rooms/{roomId}/members](#get_matrixclientv3roomsroomidmembers)
|
* {{% added-in v="1.1" %}} [GET /rooms/{roomId}/members](#get_matrixclientv3roomsroomidmembers)
|
||||||
* [GET /rooms/{roomId}/initialSync](#get_matrixclientv3roomsroomidinitialsync)
|
* [GET /rooms/{roomId}/initialSync](#get_matrixclientv3roomsroomidinitialsync)
|
||||||
* [GET /sync](#get_matrixclientv3sync)
|
* [GET /sync](#get_matrixclientv3sync)
|
||||||
* [GET /events](#get_matrixclientv3events) as used for room previews.
|
* [GET /events](#get_matrixclientv3events) as used for room previews.
|
||||||
|
* {{% added-in v="1.12" %}} [GET /media/download/{serverName}/{mediaId}](#get_matrixclientv1mediadownloadservernamemediaid)
|
||||||
|
* {{% added-in v="1.12" %}} [GET /media/download/{serverName}/{mediaId}/{fileName}](#get_matrixclientv1mediadownloadservernamemediaidfilename)
|
||||||
|
* {{% added-in v="1.12" %}} [GET /media/thumbnail/{serverName}/{mediaId}](#get_matrixclientv1mediathumbnailservernamemediaid)
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
for sending events:
|
for sending events:
|
||||||
|
|
@ -52,19 +55,20 @@ for sending events:
|
||||||
* [POST /rooms/{roomId}/leave](#post_matrixclientv3roomsroomidleave)
|
* [POST /rooms/{roomId}/leave](#post_matrixclientv3roomsroomidleave)
|
||||||
* [PUT /rooms/{roomId}/send/{eventType}/{txnId}](#put_matrixclientv3roomsroomidsendeventtypetxnid)
|
* [PUT /rooms/{roomId}/send/{eventType}/{txnId}](#put_matrixclientv3roomsroomidsendeventtypetxnid)
|
||||||
|
|
||||||
* {{< changed-in v="1.2" >}} Guests can now send *any* event type rather than just `m.room.message` events.
|
* {{% changed-in v="1.2" %}} Guests can now send *any* event type rather than just `m.room.message` events.
|
||||||
|
|
||||||
* {{< added-in v="1.2" >}} [PUT /rooms/{roomId}/state/{eventType}/{stateKey}](#put_matrixclientv3roomsroomidstateeventtypestatekey)
|
* {{% added-in v="1.2" %}} [PUT /rooms/{roomId}/state/{eventType}/{stateKey}](#put_matrixclientv3roomsroomidstateeventtypestatekey)
|
||||||
* [PUT /sendToDevice/{eventType}/{txnId}](#put_matrixclientv3sendtodeviceeventtypetxnid)
|
* [PUT /sendToDevice/{eventType}/{txnId}](#put_matrixclientv3sendtodeviceeventtypetxnid)
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
for their own account maintenance:
|
for their own account maintenance:
|
||||||
|
|
||||||
* [PUT /profile/{userId}/displayname](#put_matrixclientv3profileuseriddisplayname)
|
* [PUT /profile/{userId}/displayname](#put_matrixclientv3profileuseridkeyname). Guest users may only modify their display name; other profile fields may not be changed.
|
||||||
|
* {{% added-in v="1.16" %}} [DELETE /profile/{userId}/displayname](#delete_matrixclientv3profileuseridkeyname). Again, guest users may delete their display name but not other profile fields.
|
||||||
* [GET /devices](#get_matrixclientv3devices)
|
* [GET /devices](#get_matrixclientv3devices)
|
||||||
* [GET /devices/{deviceId}](#get_matrixclientv3devicesdeviceid)
|
* [GET /devices/{deviceId}](#get_matrixclientv3devicesdeviceid)
|
||||||
* [PUT /devices/{deviceId}](#put_matrixclientv3devicesdeviceid)
|
* [PUT /devices/{deviceId}](#put_matrixclientv3devicesdeviceid)
|
||||||
* {{< added-in v="1.2" >}} [GET /account/whoami](#get_matrixclientv3accountwhoami)
|
* {{% added-in v="1.2" %}} [GET /account/whoami](#get_matrixclientv3accountwhoami)
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
for end-to-end encryption:
|
for end-to-end encryption:
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ The four options for the `m.room.history_visibility` event are:
|
||||||
|
|
||||||
- `world_readable` - All events while this is the
|
- `world_readable` - All events while this is the
|
||||||
`m.room.history_visibility` value may be shared by any participating
|
`m.room.history_visibility` value may be shared by any participating
|
||||||
homeserver with anyone, regardless of whether they have ever joined
|
homeserver with any authenticated user, regardless of whether they have
|
||||||
the room.
|
ever joined the room. This includes [guest users](#guest-access).
|
||||||
- `shared` - Previous events are always accessible to newly joined
|
- `shared` - Previous events are always accessible to newly joined
|
||||||
members. All events in the room are accessible, even those sent when
|
members. All events in the room are accessible, even those sent when
|
||||||
the member was not a part of the room.
|
the member was not a part of the room.
|
||||||
|
|
@ -43,11 +43,8 @@ setting at that time was more restrictive.
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
Clients that implement this module MUST present to the user the possible
|
Clients may want to display a notice that events may be read by
|
||||||
options for setting history visibility when creating a room.
|
non-joined users if the history visibility is set to `world_readable`.
|
||||||
|
|
||||||
Clients may want to display a notice that their events may be read by
|
|
||||||
non-joined people if the value is set to `world_readable`.
|
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ and servers can implement the ignoring of users.
|
||||||
|
|
||||||
To ignore a user, effectively blocking them, the client should add the
|
To ignore a user, effectively blocking them, the client should add the
|
||||||
target user to the `m.ignored_user_list` event in their account data
|
target user to the `m.ignored_user_list` event in their account data
|
||||||
using [`/user/<user_id>/account_data/<type>`](/client-server-api/#put_matrixclientv3useruseridaccount_datatype). Once ignored, the client will no longer receive events sent by
|
using [`/user/<user_id>/account_data/<type>`](#put_matrixclientv3useruseridaccount_datatype). Once ignored, the client will no longer receive events sent by
|
||||||
that user, with the exception of state events. The client should either
|
that user, with the exception of state events. The client should either
|
||||||
hide previous content sent by the newly ignored user or perform a new
|
hide previous content sent by the newly ignored user or perform a new
|
||||||
`/sync` with no previous token.
|
[`/sync`](#get_matrixclientv3sync) with no previous token.
|
||||||
|
|
||||||
Invites to new rooms by ignored users will not be sent to the client.
|
Invites to new rooms by ignored users will not be sent to the client.
|
||||||
The server may optionally reject the invite on behalf of the client.
|
The server may optionally reject the invite on behalf of the client.
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,41 @@ instead.
|
||||||
|
|
||||||
Some message types support HTML in the event content that clients should
|
Some message types support HTML in the event content that clients should
|
||||||
prefer to display if available. Currently `m.text`, `m.emote`, `m.notice`,
|
prefer to display if available. Currently `m.text`, `m.emote`, `m.notice`,
|
||||||
and `m.key.verification.request` support an additional `format` parameter of
|
`m.image`, `m.file`, `m.audio`, `m.video` and `m.key.verification.request`
|
||||||
`org.matrix.custom.html`. When this field is present, a `formatted_body`
|
support an additional `format` parameter of `org.matrix.custom.html`. When this
|
||||||
with the HTML must be provided. The plain text version of the HTML
|
field is present, a `formatted_body` with the HTML must be provided. The plain
|
||||||
should be provided in the `body`.
|
text version of the HTML should be provided in the `body`.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% changed-in v="1.10" %}}
|
||||||
|
In previous versions of the specification, the `format` and `formatted` fields
|
||||||
|
were limited to `m.text`, `m.emote`, `m.notice`, and
|
||||||
|
`m.key.verification.request`. This list is expanded to include `m.image`,
|
||||||
|
`m.file`, `m.audio` and `m.video` for [media captions](#media-captions).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
Clients should limit the HTML they render to avoid Cross-Site Scripting,
|
Clients should limit the HTML they render to avoid Cross-Site Scripting,
|
||||||
HTML injection, and similar attacks. The strongly suggested set of HTML
|
HTML injection, and similar attacks. The strongly suggested set of HTML
|
||||||
tags to permit, denying the use and rendering of anything else, is:
|
tags to permit, denying the use and rendering of anything else, is:
|
||||||
`font`, `del`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `blockquote`, `p`,
|
`del`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `blockquote`, `p`, `a`, `ul`,
|
||||||
`a`, `ul`, `ol`, `sup`, `sub`, `li`, `b`, `i`, `u`, `strong`, `em`,
|
`ol`, `sup`, `sub`, `li`, `b`, `i`, `u`, `strong`, `em`, `s`, `code`,
|
||||||
`strike`, `code`, `hr`, `br`, `div`, `table`, `thead`, `tbody`, `tr`,
|
`hr`, `br`, `div`, `table`, `thead`, `tbody`, `tr`, `th`, `td`,
|
||||||
`th`, `td`, `caption`, `pre`, `span`, `img`, `details`, `summary`.
|
`caption`, `pre`, `span`, `img`, `details`, `summary`.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.10" %}}
|
||||||
|
HTML features MAY be deprecated and replaced by their modern equivalent without
|
||||||
|
requiring a [Spec Change Proposal](/proposals) when they are deprecated in the
|
||||||
|
[WHATWG HTML Living Standard](https://html.spec.whatwg.org/multipage/).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% changed-in v="1.10" %}}
|
||||||
|
In previous versions of the specification, the `font` tag was suggested with the
|
||||||
|
`data-mx-bg-color`, `data-mx-color` and `color` attributes. This tag is now
|
||||||
|
deprecated in favor of the `span` tag with the `data-mx-bg-color` and
|
||||||
|
`data-mx-color` attributes in new messages.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
Not all attributes on those tags should be permitted as they may be
|
Not all attributes on those tags should be permitted as they may be
|
||||||
avenues for other disruption attempts, such as adding `onclick` handlers
|
avenues for other disruption attempts, such as adding `onclick` handlers
|
||||||
|
|
@ -48,27 +71,14 @@ are listed, clients should translate the value (a `#` character followed
|
||||||
by a 6-character hex color code) to the appropriate CSS/attributes for
|
by a 6-character hex color code) to the appropriate CSS/attributes for
|
||||||
the tag.
|
the tag.
|
||||||
|
|
||||||
`font`
|
| Tag | Permitted Attributes |
|
||||||
`data-mx-bg-color`, `data-mx-color`, `color`
|
|--------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `span` | `data-mx-bg-color`, `data-mx-color`, `data-mx-spoiler` (see [spoiler messages](#spoiler-messages)), `data-mx-maths` (see [mathematical messages](#mathematical-messages)) |
|
||||||
`span`
|
| `a` | `target`, `href` (provided the value is not relative and has a scheme matching one of: `https`, `http`, `ftp`, `mailto`, `magnet`) |
|
||||||
`data-mx-bg-color`, `data-mx-color`, `data-mx-spoiler` (see
|
| `img` | `width`, `height`, `alt`, `title`, `src` (provided it is a [Matrix Content (`mxc://`) URI](#matrix-content-mxc-uris)) |
|
||||||
[spoiler messages](#spoiler-messages))
|
| `ol` | `start` |
|
||||||
|
| `code` | `class` (only classes which start with `language-` for syntax highlighting) |
|
||||||
`a`
|
| `div` | `data-mx-maths` (see [mathematical messages](#mathematical-messages)) |
|
||||||
`name`, `target`, `href` (provided the value is not relative and has a
|
|
||||||
scheme matching one of: `https`, `http`, `ftp`, `mailto`, `magnet`)
|
|
||||||
|
|
||||||
`img`
|
|
||||||
`width`, `height`, `alt`, `title`, `src` (provided it is a [Matrix
|
|
||||||
Content (MXC) URI](#matrix-content-mxc-uris))
|
|
||||||
|
|
||||||
`ol`
|
|
||||||
`start`
|
|
||||||
|
|
||||||
`code`
|
|
||||||
`class` (only classes which start with `language-` for syntax
|
|
||||||
highlighting)
|
|
||||||
|
|
||||||
Additionally, web clients should ensure that *all* `a` tags get a
|
Additionally, web clients should ensure that *all* `a` tags get a
|
||||||
`rel="noopener"` to prevent the target page from referencing the
|
`rel="noopener"` to prevent the target page from referencing the
|
||||||
|
|
@ -88,14 +98,12 @@ having appropriate closing tags, appropriate attributes (considering the
|
||||||
custom ones defined in this specification), and generally valid
|
custom ones defined in this specification), and generally valid
|
||||||
structure.
|
structure.
|
||||||
|
|
||||||
A special tag, `mx-reply`, may appear on rich replies (described below)
|
{{% boxes/note %}}
|
||||||
and should be allowed if, and only if, the tag appears as the very first
|
{{% changed-in v="1.13" %}}
|
||||||
tag in the `formatted_body`. The tag cannot be nested and cannot be
|
In previous versions of the specification, [rich replies](#rich-replies) could
|
||||||
located after another tag in the tree. Because the tag contains HTML, an
|
use a special tag, `mx-reply`. This is no longer the case. Clients SHOULD strip
|
||||||
`mx-reply` is expected to have a partner closing tag and should be
|
this tag and its content. See the "Rich replies" section for more information.
|
||||||
treated similar to a `div`. Clients that support rich replies will end
|
{{% /boxes/note %}}
|
||||||
up stripping the tag and its contents and therefore may wish to exclude
|
|
||||||
the tag entirely.
|
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
A future iteration of the specification will support more powerful and
|
A future iteration of the specification will support more powerful and
|
||||||
|
|
@ -328,11 +336,112 @@ When sending a spoiler, clients SHOULD provide the fallback in the `body` as sho
|
||||||
(including the reason). The fallback SHOULD NOT include the text containing spoilers since
|
(including the reason). The fallback SHOULD NOT include the text containing spoilers since
|
||||||
`body` might show up in text-only clients or in notifications. To prevent spoilers showing up in
|
`body` might show up in text-only clients or in notifications. To prevent spoilers showing up in
|
||||||
such situations, clients are strongly encouraged to first upload the text containing spoilers
|
such situations, clients are strongly encouraged to first upload the text containing spoilers
|
||||||
to the media repository, then reference the MXC URI in a markdown-style link, as shown above.
|
to the media repository, then reference the `mxc://` URI in a markdown-style link, as shown above.
|
||||||
|
|
||||||
Clients SHOULD render spoilers differently with some sort of disclosure. For example, the
|
Clients SHOULD render spoilers differently with some sort of disclosure. For example, the
|
||||||
client could blur the actual text and ask the user to click on it for it to be revealed.
|
client could blur the actual text and ask the user to click on it for it to be revealed.
|
||||||
|
|
||||||
|
##### Media captions
|
||||||
|
|
||||||
|
{{% added-in v="1.10" %}}
|
||||||
|
|
||||||
|
Media messages, comprised of `m.image`, `m.file`, `m.audio` and `m.video`, can
|
||||||
|
include a caption to convey additional information about the media.
|
||||||
|
|
||||||
|
To send captions, clients MUST use the `filename` and the `body`, and optionally
|
||||||
|
the `formatted_body` with the `org.matrix.custom.html` format, described above.
|
||||||
|
|
||||||
|
If the `filename` is present, and its value is different than `body`, then
|
||||||
|
`body` is considered to be a caption, otherwise `body` is a filename. `format`
|
||||||
|
and `formatted_body` are only used for captions.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
In previous versions of the specification, `body` was usually used to set the
|
||||||
|
filename of the uploaded file, and `filename` was only present on `m.file` with
|
||||||
|
the same purpose.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
An example of a media message with a caption is:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msgtype": "m.image",
|
||||||
|
"url": "mxc://example.org/abc123",
|
||||||
|
"filename": "dog.jpg",
|
||||||
|
"body": "this is a ~~cat~~ picture :3",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "this is a <s>cat</s> picture :3",
|
||||||
|
"info": {
|
||||||
|
"w": 479,
|
||||||
|
"h": 640,
|
||||||
|
"mimetype": "image/jpeg",
|
||||||
|
"size": 27253
|
||||||
|
},
|
||||||
|
"m.mentions": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Clients MUST render the caption alongside the media and SHOULD prefer its
|
||||||
|
formatted representation.
|
||||||
|
|
||||||
|
##### Mathematical messages
|
||||||
|
|
||||||
|
{{% added-in v="1.11" %}}
|
||||||
|
|
||||||
|
Users might want to send mathematical notations in their messages.
|
||||||
|
|
||||||
|
To send mathematical notations clients MUST use the `formatted_body` and
|
||||||
|
therefore the `org.matrix.custom.html` format, described above. This makes
|
||||||
|
mathematical notations valid on any `msgtype` which can support this format
|
||||||
|
appropriately.
|
||||||
|
|
||||||
|
Mathematical notations themselves use the `span` or `div` tags, depending
|
||||||
|
whether the notation should be presented inline or not. The mathematical
|
||||||
|
notation is written in [LaTeX](https://www.latex-project.org/) format using the
|
||||||
|
`data-mx-maths` attribute.
|
||||||
|
|
||||||
|
The contents of the tag should be a fallback representation for clients that
|
||||||
|
cannot render the LaTeX format. The fallback representation could be, for
|
||||||
|
example, an image, or an HTML approximation, or the raw LaTeX source. When using
|
||||||
|
an image as a fallback, the sending client should be aware of issues that may
|
||||||
|
arise from the receiving client using a different background colour. The `body`
|
||||||
|
should include a textual representation of the notation.
|
||||||
|
|
||||||
|
An example of a mathematical notation is:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"body": "This is an equation: sin(x)=a/b.",
|
||||||
|
"formatted_body": "This is an equation:
|
||||||
|
<span data-mx-maths=\"\\sin(x)=\\frac{a}{b}\">
|
||||||
|
sin(<i>x</i>)=<sup><i>a</i></sup>/<sub><i>b</i></sub>
|
||||||
|
</span>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The LaTeX format is poorly defined and has several extensions, so if a client
|
||||||
|
encounters syntax that it cannot render, it SHOULD present the fallback
|
||||||
|
representation instead. Clients SHOULD, however, aim to support, at minimum, the
|
||||||
|
basic [LaTeX2e](https://www.latex-project.org/) maths commands and the
|
||||||
|
[TeX](https://tug.org/) maths commands, with the possible exception of commands
|
||||||
|
that could be security risks.
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
In general, LaTeX places a heavy burden on client authors to ensure that it is
|
||||||
|
processed safely. Certain commands, such as [those that can create macros](https://katex.org/docs/supported#macros),
|
||||||
|
are potentially dangerous. Clients should either decline to process those
|
||||||
|
commands, or should take care to ensure that they are handled in safe ways (such
|
||||||
|
as by limiting recursion). In general, LaTeX commands should be filtered by
|
||||||
|
allowing known-good commands rather than forbidding known-bad commands.
|
||||||
|
|
||||||
|
Therefore, clients should not render mathematics by calling a LaTeX compiler
|
||||||
|
without proper sandboxing, as those executables were not written to handle
|
||||||
|
untrusted input. Some LaTeX rendering libraries are better suited for that by
|
||||||
|
allowing only a subset of LaTeX and enforcing recursion limits.
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
Homeservers SHOULD reject `m.room.message` events which don't have a
|
Homeservers SHOULD reject `m.room.message` events which don't have a
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,92 @@
|
||||||
|
|
||||||
### User and room mentions
|
### User and room mentions
|
||||||
|
|
||||||
This module allows users to mention other users and rooms within a room message.
|
{{% changed-in v="1.7" %}}
|
||||||
This is achieved by including a [Matrix URI](/appendices/#uris) in the HTML body of
|
|
||||||
an [m.room.message](#mroommessage) event. This module does not have any server-specific
|
|
||||||
behaviour to it.
|
|
||||||
|
|
||||||
Mentions apply only to [m.room.message](#mroommessage) events where the `msgtype` is
|
{{% changed-in v="1.17" %}}: the legacy push rules that looked for mentions in
|
||||||
`m.text`, `m.emote`, or `m.notice`. The `format` for the event must be
|
the `body` of the event were removed.
|
||||||
`org.matrix.custom.html` and therefore requires a `formatted_body`.
|
|
||||||
|
|
||||||
To make a mention, reference the entity being mentioned in the
|
This module allows users to "mention" other users and rooms within a room event.
|
||||||
`formatted_body` using an anchor, like so:
|
This is primarily used as an indicator that the recipient should receive a notification
|
||||||
|
about the event.
|
||||||
|
This is achieved by including metadata in the `m.mentions` content property of
|
||||||
|
the event to reference the entity being mentioned.
|
||||||
|
|
||||||
|
`m.mentions` is defined as follows:
|
||||||
|
|
||||||
|
{{% definition path="api/client-server/definitions/m.mentions" %}}
|
||||||
|
|
||||||
|
An event's content will then look like this:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"body": "Hello Alice!",
|
"body": "Hello Alice!",
|
||||||
"msgtype": "m.text",
|
"msgtype": "m.text",
|
||||||
"format": "org.matrix.custom.html",
|
"format": "org.matrix.custom.html",
|
||||||
"formatted_body": "Hello <a href='https://matrix.to/#/@alice:example.org'>Alice</a>!"
|
"formatted_body": "Hello <a href='https://matrix.to/#/@alice:example.org'>Alice</a>!",
|
||||||
|
"m.mentions": {
|
||||||
|
"user_ids": ["@alice:example.org"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Additionally, see the [`.m.rule.is_user_mention`](#_m_rule_is_user_mention) and
|
||||||
|
[`.m.rule.is_room_mention`](#_m_rule_is_room_mention) push rules.
|
||||||
|
Users should not add their own Matrix ID to the `m.mentions` property as outgoing
|
||||||
|
messages cannot self-notify.
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
If an encrypted event contains an `m.mentions` in its payload, it should be
|
||||||
|
encrypted as normal. To properly process mentions in encrypted rooms, events
|
||||||
|
must be decrypted first. See [receiving notifications](#receiving-notifications).
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
In previous versions of the specification, mentioning users was done by
|
||||||
|
including the user's display name or the localpart of their Matrix ID and room
|
||||||
|
mentions were done by including the string "@room" in the plaintext `body` of
|
||||||
|
the event. When the `m.mentions` field was introduced, those push rules were
|
||||||
|
disabled if the `m.mentions` field was present.
|
||||||
|
|
||||||
|
To avoid unintentional notifications with clients and servers that still use
|
||||||
|
those push rules, **it is recommended that clients still include a `m.mentions`
|
||||||
|
property on each event**. (If there are no mentions to include it can be an
|
||||||
|
empty object.)
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
In addition to using the appropriate `Matrix URI` for the mention,
|
Although it is possible to silently mention users, it is recommended to include a
|
||||||
clients should use the following guidelines when making mentions in
|
[Matrix URI](/appendices/#uris) in the HTML body of an [m.room.message](#mroommessage)
|
||||||
events to be sent:
|
event. This applies only to [m.room.message](#mroommessage) events where the `msgtype` is
|
||||||
|
`m.text`, `m.emote`, or `m.notice`. The `format` for the event must be
|
||||||
|
`org.matrix.custom.html` and therefore requires a `formatted_body`.
|
||||||
|
|
||||||
- When mentioning users, use the user's potentially ambiguous display
|
Clients should use the following guidelines when adding a `Matrix URI`
|
||||||
|
representing a mention to events to be sent:
|
||||||
|
|
||||||
|
- When linking to users, use the user's potentially ambiguous display
|
||||||
name for the anchor's text. If the user does not have a display
|
name for the anchor's text. If the user does not have a display
|
||||||
name, use the user's ID.
|
name, use the user's ID.
|
||||||
- When mentioning rooms, use the canonical alias for the room. If the
|
- When linking to rooms, use the canonical alias for the room. If the
|
||||||
room does not have a canonical alias, prefer one of the aliases
|
room does not have a canonical alias, prefer one of the aliases
|
||||||
listed on the room. If no alias can be found, fall back to the room
|
listed on the room. If no alias can be found, fall back to the room
|
||||||
ID. In all cases, use the alias/room ID being linked to as the
|
ID. In all cases, use the alias/room ID being linked to as the
|
||||||
anchor's text.
|
anchor's text.
|
||||||
|
|
||||||
The text component of the anchor should be used in the event's `body`
|
The text component of the anchor should be used in the event's `body`
|
||||||
where the mention would normally be represented, as shown in the example
|
where the link would normally be represented, as shown in the example
|
||||||
above.
|
above.
|
||||||
|
|
||||||
Clients should display mentions differently from other elements. For
|
Clients should display mentions differently from other elements. For
|
||||||
example, this may be done by changing the background color of the
|
example, this may be done by changing the background color of the
|
||||||
mention to indicate that it is different from a normal link.
|
mention to indicate that it is different from a normal link.
|
||||||
|
|
||||||
If the current user is mentioned in a message (either by a mention as
|
If the current user is mentioned in a message, the client should show that
|
||||||
defined in this module or by a push rule), the client should show that
|
|
||||||
mention differently from other mentions, such as by using a red
|
mention differently from other mentions, such as by using a red
|
||||||
background color to signify to the user that they were mentioned.
|
background color to signify to the user that they were mentioned. Note that
|
||||||
|
it is possible for a user to be mentioned without including their `Matrix URI`
|
||||||
|
in the event.
|
||||||
|
|
||||||
When clicked, the mention should navigate the user to the appropriate
|
When clicked, the mention should navigate the user to the appropriate
|
||||||
user or room information.
|
user or room information.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
|
||||||
Similar to legacy [matrix.to URLs](/appendices/#matrixto-navigation),
|
|
||||||
groups used to be representable by mentions. They follow a similar format
|
|
||||||
to room mentions, though using the group ID in both the link and anchor
|
|
||||||
text.
|
|
||||||
{{% /boxes/note %}}
|
|
||||||
|
|
@ -13,13 +13,14 @@ deciding what content is undesirable for any particular entity and
|
||||||
should instead be empowering those entities to make their own decisions.
|
should instead be empowering those entities to make their own decisions.
|
||||||
As such, a generic framework for communicating "moderation policy lists"
|
As such, a generic framework for communicating "moderation policy lists"
|
||||||
or "moderation policy rooms" is described. Note that this module only
|
or "moderation policy rooms" is described. Note that this module only
|
||||||
describes the data structures and not how they should be interpreting:
|
describes the data structures and not how they should be interpreted:
|
||||||
the entity making the decisions on filtering is best positioned to
|
the entity making the decisions on filtering is best positioned to
|
||||||
interpret the rules how it sees fit.
|
interpret the rules how it sees fit.
|
||||||
|
|
||||||
Moderation policy lists are stored as room state events. There are no
|
Moderation policy lists are stored as room state events. There are no
|
||||||
restrictions on how the rooms can be configured (they could be public,
|
restrictions on how the rooms can be configured in terms of
|
||||||
private, encrypted, etc).
|
[join rules](#mroomjoin_rules), [history visibility](#room-history-visibility),
|
||||||
|
encryption, etc.
|
||||||
|
|
||||||
There are currently 3 kinds of entities which can be affected by rules:
|
There are currently 3 kinds of entities which can be affected by rules:
|
||||||
`user`, `server`, and `room`. All 3 are described with
|
`user`, `server`, and `room`. All 3 are described with
|
||||||
|
|
@ -75,8 +76,8 @@ technique for receiving updates to the policy's rules.
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
The `entity` described by the state events can contain `*` and `?` to
|
The `entity` described by the state events is interpreted as a
|
||||||
match zero or more characters and exactly one character respectively. Note that
|
[glob-style pattern](/appendices#glob-style-matching). Note that
|
||||||
rules against rooms can describe a room ID or room alias - the
|
rules against rooms can describe a room ID or room alias - the
|
||||||
subscriber is responsible for resolving the alias to a room ID if
|
subscriber is responsible for resolving the alias to a room ID if
|
||||||
desired.
|
desired.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
### OpenID
|
### OpenID
|
||||||
|
|
||||||
This module allows users to verify their identity with a third party
|
This module allows users to verify their identity with a third-party
|
||||||
service. The third party service does need to be matrix-aware in that it
|
service. The third-party service does need to be matrix-aware in that it
|
||||||
will need to know to resolve matrix homeservers to exchange the user's
|
will need to know to resolve matrix homeservers to exchange the user's
|
||||||
token for identity information.
|
token for identity information.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,5 +68,7 @@ will cause the server to automatically set their presence to `online`.
|
||||||
|
|
||||||
#### Security considerations
|
#### Security considerations
|
||||||
|
|
||||||
Presence information is shared with all users who share a room with the
|
Presence information is published to all users who share a room with the
|
||||||
target user. In large public rooms this could be undesirable.
|
target user. If the target user is a member of a room with a `public`
|
||||||
|
[join rule](#mroomjoin_rules), any other user in the federation is
|
||||||
|
able to gain access to the target user's presence. This could be undesirable.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
### Push Notifications
|
### Push Notifications
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+--------------------+ +-------------------+
|
+--------------------+ +-------------------+
|
||||||
Matrix HTTP | | | |
|
Matrix HTTP | | | |
|
||||||
Notification Protocol | App Developer | | Device Vendor |
|
Notification Protocol | App Developer | | Device Vendor |
|
||||||
|
|
@ -51,120 +51,76 @@ such as Apple's APNS or Google's GCM. This happens as follows:
|
||||||
Definitions for terms used in this section are below:
|
Definitions for terms used in this section are below:
|
||||||
|
|
||||||
Push Provider
|
Push Provider
|
||||||
A push provider is a service managed by the device vendor which can send
|
|
||||||
notifications directly to the device. Google Cloud Messaging (GCM) and
|
: A push provider is a service managed by the device vendor which can send
|
||||||
Apple Push Notification Service (APNS) are two examples of push
|
notifications directly to the device. Google Cloud Messaging (GCM) and
|
||||||
providers.
|
Apple Push Notification Service (APNS) are two examples of push
|
||||||
|
providers.
|
||||||
|
|
||||||
Push Gateway
|
Push Gateway
|
||||||
A push gateway is a server that receives HTTP event notifications from
|
|
||||||
homeservers and passes them on to a different protocol such as APNS for
|
: A push gateway is a server that receives HTTP event notifications from
|
||||||
iOS devices or GCM for Android devices. Clients inform the homeserver
|
homeservers and passes them on to a different protocol such as APNS for
|
||||||
which Push Gateway to send notifications to when it sets up a Pusher.
|
iOS devices or GCM for Android devices. Clients inform the homeserver
|
||||||
|
which Push Gateway to send notifications to when it sets up a Pusher.
|
||||||
|
|
||||||
Pusher
|
Pusher
|
||||||
A pusher is a worker on the homeserver that manages the sending of HTTP
|
|
||||||
notifications for a user. A user can have multiple pushers: one per
|
: A pusher is a worker on the homeserver that manages the sending of HTTP
|
||||||
device.
|
notifications for a user. A user can have multiple pushers: one per
|
||||||
|
device.
|
||||||
|
|
||||||
Push Rule
|
Push Rule
|
||||||
A push rule is a single rule that states under what *conditions* an
|
|
||||||
event should be passed onto a push gateway and *how* the notification
|
: A push rule is a single rule that states under what *conditions* an
|
||||||
should be presented. These rules are stored on the user's homeserver.
|
event should be passed onto a push gateway and *how* the notification
|
||||||
They are manually configured by the user, who can create and view them
|
should be presented. These rules are stored on the user's homeserver.
|
||||||
via the Client/Server API.
|
They are manually configured by the user, who can create and view them
|
||||||
|
via the Client/Server API.
|
||||||
|
|
||||||
Push Ruleset
|
Push Ruleset
|
||||||
A push ruleset *scopes a set of rules according to some criteria*. For
|
|
||||||
example, some rules may only be applied for messages from a particular
|
|
||||||
sender, a particular room, or by default. The push ruleset contains the
|
|
||||||
entire set of scopes and rules.
|
|
||||||
|
|
||||||
#### Client behaviour
|
: A push ruleset *scopes a set of rules according to some criteria*. For
|
||||||
|
example, some rules may only be applied for messages from a particular
|
||||||
|
sender, a particular room, or by default. The push ruleset contains the
|
||||||
|
entire set of rules.
|
||||||
|
|
||||||
Clients MUST configure a Pusher before they will receive push
|
#### Push Rules
|
||||||
notifications. There is a single API endpoint for this, as described
|
|
||||||
below.
|
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="pusher" %}}
|
|
||||||
|
|
||||||
##### Listing Notifications
|
|
||||||
|
|
||||||
A client can retrieve a list of events that it has been notified about.
|
|
||||||
This may be useful so that users can see a summary of what important
|
|
||||||
messages they have received.
|
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="notifications" %}}
|
|
||||||
|
|
||||||
##### Receiving notifications
|
|
||||||
|
|
||||||
Servers MUST include the number of unread notifications in a client's
|
|
||||||
`/sync` stream, and MUST update it as it changes. Notifications are
|
|
||||||
determined by the push rules which apply to an event.
|
|
||||||
|
|
||||||
When the user updates their read receipt (either by using the API or by
|
|
||||||
sending an event), notifications prior to and including that event MUST
|
|
||||||
be marked as read. Which specific events are affected can vary depending
|
|
||||||
on whether a [threaded read receipt](#threaded-read-receipts) was used.
|
|
||||||
Note that users can send both an `m.read` and `m.read.private` receipt,
|
|
||||||
both of which are capable of clearing notifications.
|
|
||||||
|
|
||||||
If the user has both `m.read` and `m.read.private` set in the room then
|
|
||||||
the receipt which is more recent/ahead must be used to determine where
|
|
||||||
the user has read up to. For example, given an oldest-first set of events A,
|
|
||||||
B, C, and D the `m.read` receipt could be at event C and `m.read.private`
|
|
||||||
at event A - the user is considered to have read up to event C. If the
|
|
||||||
`m.read.private` receipt is then updated to point to B or C, the user's
|
|
||||||
notification state doesn't change (the `m.read` receipt is still more
|
|
||||||
ahead), however if the `m.read.private` receipt were to be updated to
|
|
||||||
event D then the user has read up to D (the `m.read` receipt is now
|
|
||||||
behind the `m.read.private` receipt).
|
|
||||||
|
|
||||||
{{< added-in v="1.4" >}} When handling threaded read receipts, the server
|
|
||||||
is to partition the notification count to each thread (with the main timeline
|
|
||||||
being its own thread). To determine if an event is part of a thread the
|
|
||||||
server follows the [event relationship](#forming-relationships-between-events)
|
|
||||||
until it finds a thread root (as specified by the [threading module](#threading)),
|
|
||||||
however it is not recommended that the server traverse infinitely. Instead,
|
|
||||||
implementations are encouraged to do a maximum of 3 hops to find a thread
|
|
||||||
before deciding that the event does not belong to a thread. This is primarily
|
|
||||||
to ensure that future events, like `m.reaction`, are correctly considered
|
|
||||||
"part of" a given thread.
|
|
||||||
|
|
||||||
##### Push Rules
|
|
||||||
|
|
||||||
A push rule is a single rule that states under what *conditions* an
|
A push rule is a single rule that states under what *conditions* an
|
||||||
event should be passed onto a push gateway and *how* the notification
|
event should be passed onto a push gateway and *how* the notification
|
||||||
should be presented. There are different "kinds" of push rules and each
|
should be presented. There are different "kinds" of push rules and each
|
||||||
rule has an associated priority. Every push rule MUST have a `kind` and
|
rule has an associated priority. Every push rule MUST have a `kind` and
|
||||||
`rule_id`. The `rule_id` is a unique string within the kind of rule and
|
`rule_id`. The `rule_id` is a unique string within the kind of rule.
|
||||||
its' scope: `rule_ids` do not need to be unique between rules of the
|
Rules may have extra keys depending on the value of `kind`.
|
||||||
same kind on different devices. Rules may have extra keys depending on
|
|
||||||
the value of `kind`.
|
|
||||||
|
|
||||||
The different `kind`s of rule, in the order that they are checked, are:
|
The different `kind`s of rule, in the order that they are checked, are:
|
||||||
|
|
||||||
Override Rules `override`
|
1. **Override rules (`override`).**
|
||||||
The highest priority rules are user-configured overrides.
|
The highest priority rules are user-configured overrides.
|
||||||
|
|
||||||
Content-specific Rules `content`
|
1. **Content-specific rules (`content`).**
|
||||||
These configure behaviour for (unencrypted) messages that match certain
|
These configure behaviour for messages that match certain patterns. Content
|
||||||
patterns. Content rules take one parameter: `pattern`, that gives the
|
rules take one parameter: `pattern`, that gives the
|
||||||
glob pattern to match against. This is treated in the same way as
|
[glob-style pattern](/appendices#glob-style-matching) to match against.
|
||||||
`pattern` for `event_match`.
|
The match is performed case-insensitively, and must match any substring of
|
||||||
|
the `content.body` property which starts and ends at a word boundary. A word
|
||||||
|
boundary is defined as the start or end of the value, or any character not
|
||||||
|
in the sets `[A-Z]`, `[a-z]`, `[0-9]` or `_`.The exact meaning of
|
||||||
|
"case insensitive" is defined by the implementation of the homeserver.
|
||||||
|
|
||||||
Room-specific Rules `room`
|
1. **Room-specific rules (`room`).**
|
||||||
These rules change the behaviour of all messages for a given room. The
|
These rules change the behaviour of all messages for a given room. The
|
||||||
`rule_id` of a room rule is always the ID of the room that it affects.
|
`rule_id` of a room rule is always the ID of the room that it affects.
|
||||||
|
|
||||||
Sender-specific rules `sender`
|
1. **Sender-specific rules (`sender`).**
|
||||||
These rules configure notification behaviour for messages from a
|
These rules configure notification behaviour for messages from a
|
||||||
specific Matrix user ID. The `rule_id` of Sender rules is always the
|
specific Matrix user ID. The `rule_id` of Sender rules is always the
|
||||||
Matrix user ID of the user whose messages they'd apply to.
|
Matrix user ID of the user whose messages they'd apply to.
|
||||||
|
|
||||||
Underride rules `underride`
|
1. **Underride rules (`underride`).**
|
||||||
These are identical to `override` rules, but have a lower priority than
|
These are identical to `override` rules, but have a lower priority than
|
||||||
`content`, `room` and `sender` rules.
|
`content`, `room` and `sender` rules.
|
||||||
|
|
||||||
Rules with the same `kind` can specify an ordering priority. This
|
Rules with the same `kind` can specify an ordering priority. This
|
||||||
determines which rule is selected in the event of multiple matches. For
|
determines which rule is selected in the event of multiple matches. For
|
||||||
|
|
@ -179,57 +135,62 @@ rules match an event, the homeserver MUST NOT notify the Push Gateway
|
||||||
for that event. Homeservers MUST NOT notify the Push Gateway for events
|
for that event. Homeservers MUST NOT notify the Push Gateway for events
|
||||||
that the user has sent themselves.
|
that the user has sent themselves.
|
||||||
|
|
||||||
###### Actions
|
##### Actions
|
||||||
|
|
||||||
All rules have an associated list of `actions`. An action affects if and
|
All rules have an associated list of `actions`. An action affects if and
|
||||||
how a notification is delivered for a matching event. The following
|
how a notification is delivered for a matching event. The following
|
||||||
actions are defined:
|
actions are defined:
|
||||||
|
|
||||||
`notify`
|
`notify`
|
||||||
This causes each matching event to generate a notification.
|
|
||||||
|
|
||||||
`dont_notify`
|
: This causes each matching event to generate a notification.
|
||||||
This prevents each matching event from generating a notification
|
|
||||||
|
|
||||||
`coalesce`
|
|
||||||
This enables notifications for matching events but activates homeserver
|
|
||||||
specific behaviour to intelligently coalesce multiple events into a
|
|
||||||
single notification. Not all homeservers may support this. Those that do
|
|
||||||
not support it should treat it as the `notify` action.
|
|
||||||
|
|
||||||
`set_tweak`
|
`set_tweak`
|
||||||
Sets an entry in the `tweaks` dictionary key that is sent in the
|
|
||||||
notification request to the Push Gateway. This takes the form of a
|
|
||||||
dictionary with a `set_tweak` key whose value is the name of the tweak
|
|
||||||
to set. It may also have a `value` key which is the value to which it
|
|
||||||
should be set.
|
|
||||||
|
|
||||||
The following tweaks are defined:
|
: Sets an entry in the `tweaks` dictionary key that is sent in the
|
||||||
|
notification request to the Push Gateway. This takes the form of a
|
||||||
|
dictionary with a `set_tweak` key whose value is the name of the tweak
|
||||||
|
to set. It may also have a `value` key which is the value to which it
|
||||||
|
should be set.
|
||||||
|
|
||||||
* `sound`: A string representing the sound to be played when this notification
|
The following tweaks are defined:
|
||||||
arrives. A value of `default` means to play a default sound. A device
|
|
||||||
may choose to alert the user by some other means if appropriate, eg.
|
|
||||||
vibration.
|
|
||||||
|
|
||||||
* `highlight`: A boolean representing whether or not this message should be highlighted
|
`sound`
|
||||||
in the UI. This will normally take the form of presenting the message in
|
|
||||||
a different colour and/or style. The UI might also be adjusted to draw
|
|
||||||
particular attention to the room in which the event occurred. If a
|
|
||||||
`highlight` tweak is given with no value, its value is defined to be
|
|
||||||
`true`. If no highlight tweak is given at all then the value of
|
|
||||||
`highlight` is defined to be false.
|
|
||||||
|
|
||||||
Tweaks are passed transparently through the homeserver so client
|
: A string representing the sound to be played when this notification
|
||||||
applications and Push Gateways may agree on additional tweaks. For
|
arrives. A value of `default` means to play a default sound. A device
|
||||||
example, a tweak may be added to specify how to flash the notification
|
may choose to alert the user by some other means if appropriate, eg.
|
||||||
light on a mobile device.
|
vibration.
|
||||||
|
|
||||||
|
`highlight`
|
||||||
|
|
||||||
|
: A boolean representing whether or not this message should be highlighted
|
||||||
|
in the UI. This will normally take the form of presenting the message in
|
||||||
|
a different colour and/or style. The UI might also be adjusted to draw
|
||||||
|
particular attention to the room in which the event occurred. If a
|
||||||
|
`highlight` tweak is given with no value, its value is defined to be
|
||||||
|
`true`. If no highlight tweak is given at all then the value of
|
||||||
|
`highlight` is defined to be false.
|
||||||
|
|
||||||
|
Tweaks are passed transparently through the homeserver so client
|
||||||
|
applications and Push Gateways may agree on additional tweaks. For
|
||||||
|
example, a tweak may be added to specify how to flash the notification
|
||||||
|
light on a mobile device.
|
||||||
|
|
||||||
Actions that have no parameters are represented as a string. Otherwise,
|
Actions that have no parameters are represented as a string. Otherwise,
|
||||||
they are represented as a dictionary with a key equal to their name and
|
they are represented as a dictionary with a key equal to their name and
|
||||||
other keys as their parameters, e.g.
|
other keys as their parameters, e.g.
|
||||||
`{ "set_tweak": "sound", "value": "default" }`
|
`{ "set_tweak": "sound", "value": "default" }`.
|
||||||
|
|
||||||
###### Conditions
|
###### Historical Actions
|
||||||
|
|
||||||
|
Older versions of the Matrix specification included the `dont_notify` and
|
||||||
|
`coalesce` actions. Clients and homeservers MUST ignore these actions, for
|
||||||
|
instance, by stripping them from actions arrays they encounter. This means,
|
||||||
|
for example, that a rule with `["dont_notify"]` actions MUST be equivalent
|
||||||
|
to a rule with an empty actions array.
|
||||||
|
|
||||||
|
##### Conditions
|
||||||
|
|
||||||
`override` and `underride` rules MAY have a list of 'conditions'. All
|
`override` and `underride` rules MAY have a list of 'conditions'. All
|
||||||
conditions must hold true for an event in order for the rule to match. A
|
conditions must hold true for an event in order for the rule to match. A
|
||||||
|
|
@ -246,23 +207,18 @@ The following conditions are defined:
|
||||||
|
|
||||||
**`event_match`**
|
**`event_match`**
|
||||||
|
|
||||||
This is a glob pattern match on a field of the event. Parameters:
|
This is a glob pattern match on a property of the event. Parameters:
|
||||||
|
|
||||||
- `key`: The dot-separated path of the property of the event to match, e.g.
|
- `key`: The [dot-separated path of the property](/appendices#dot-separated-property-paths)
|
||||||
`content.body`.
|
of the event to match, e.g. `content.body`.
|
||||||
|
|
||||||
- `pattern`: The glob-style pattern to match against.
|
- `pattern`: The [glob-style pattern](/appendices#glob-style-matching) to match against.
|
||||||
|
|
||||||
The match is performed case-insensitively, and must match the entire value of
|
The match is performed case-insensitively, and must match the entire value of
|
||||||
the event field given by `key` (though see below regarding `content.body`). The
|
the event property given by `key` (though see below regarding `content.body`). The
|
||||||
exact meaning of "case insensitive" is defined by the implementation of the
|
exact meaning of "case insensitive" is defined by the implementation of the
|
||||||
homeserver.
|
homeserver.
|
||||||
|
|
||||||
Within `pattern`:
|
|
||||||
|
|
||||||
* The character `*` matches zero or more characters.
|
|
||||||
* `?` matches exactly one character.
|
|
||||||
|
|
||||||
If the property specified by `key` is completely absent from the event, or does
|
If the property specified by `key` is completely absent from the event, or does
|
||||||
not have a string value, then the condition will not match, even if `pattern`
|
not have a string value, then the condition will not match, even if `pattern`
|
||||||
is `*`.
|
is `*`.
|
||||||
|
|
@ -288,7 +244,7 @@ Other `topic` values which will match are:
|
||||||
|
|
||||||
* `"LUNCH"` (case-insensitive; `*` may match zero characters)
|
* `"LUNCH"` (case-insensitive; `*` may match zero characters)
|
||||||
|
|
||||||
The following `membership` values will NOT match:
|
The following `topic` values will NOT match:
|
||||||
* `" lunch"` (note leading space)
|
* `" lunch"` (note leading space)
|
||||||
* `"lunc"` (`?` must match a character)
|
* `"lunc"` (`?` must match a character)
|
||||||
* `null` (not a string)
|
* `null` (not a string)
|
||||||
|
|
@ -306,7 +262,7 @@ following event will match:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"body": "An example event.",
|
"body": "An example event."
|
||||||
},
|
},
|
||||||
"event_id": "$143273976499sgjks:example.org",
|
"event_id": "$143273976499sgjks:example.org",
|
||||||
"room_id": "!636q39766251:example.com",
|
"room_id": "!636q39766251:example.com",
|
||||||
|
|
@ -332,12 +288,105 @@ For an example of this, see the default rule
|
||||||
[`.m.rule.tombstone`](#mruletombstone) below.
|
[`.m.rule.tombstone`](#mruletombstone) below.
|
||||||
{{% /boxes/warning %}}
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
**`event_property_is`**
|
||||||
|
|
||||||
|
This is an exact value match on a property of the event. Parameters:
|
||||||
|
|
||||||
|
- `key`: The [dot-separated path of the property](/appendices#dot-separated-property-paths)
|
||||||
|
of the event to match, e.g. `content.body`.
|
||||||
|
|
||||||
|
- `value`: The value to match against.
|
||||||
|
|
||||||
|
The match is performed exactly and only supports non-compound [canonical JSON](/appendices#canonical-json)
|
||||||
|
values: strings, integers in the range of `[-(2**53)+1, (2**53)-1]`, booleans, and
|
||||||
|
`null`.
|
||||||
|
|
||||||
|
If the property specified by `key` is completely absent from the event, or does
|
||||||
|
not have a string, integer, boolean, or `null` value, then the condition will not
|
||||||
|
match.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
For example, if `key` is `content.m\.federate`, and `value` is `true`, then
|
||||||
|
the following event will match:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"creator": "@example:example.org",
|
||||||
|
"m.federate": true,
|
||||||
|
"predecessor": {
|
||||||
|
"event_id": "$something:example.org",
|
||||||
|
"room_id": "!oldroom:example.org"
|
||||||
|
},
|
||||||
|
"room_version": "1"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"room_id": "!636q39766251:example.com",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"state_key": "",
|
||||||
|
"type": "m.room.create"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The following `m.federate` values will NOT match:
|
||||||
|
* `"true"` (note the string value)
|
||||||
|
* `1` (do not cast types)
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
**`event_property_contains`**
|
||||||
|
|
||||||
|
This matches if an array property of an event exactly contains a value. Parameters:
|
||||||
|
|
||||||
|
- `key`: The [dot-separated path of the property](/appendices#dot-separated-property-paths)
|
||||||
|
of the event to match, e.g. `content.body`.
|
||||||
|
|
||||||
|
- `value`: The value to match against.
|
||||||
|
|
||||||
|
The array values are matched exactly and only supports non-compound [canonical JSON](/appendices#canonical-json)
|
||||||
|
values: strings, integers in the range of `[-(2**53)+1, (2**53)-1]`, booleans,
|
||||||
|
and `null`. Array values not of those types are ignored.
|
||||||
|
|
||||||
|
If the property specified by `key` is completely absent from the event, or is not
|
||||||
|
an array, then the condition will not match.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
For example, if `key` is `content.alt_aliases`, and `value` is `"#myroom:example.com"`,
|
||||||
|
then the following event will match:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"alias": "#somewhere:localhost",
|
||||||
|
"alt_aliases": [
|
||||||
|
"#somewhere:example.org",
|
||||||
|
"#myroom:example.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"state_key": "",
|
||||||
|
"type": "m.room.canonical_alias",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The following `alt_aliases` values will NOT match:
|
||||||
|
* `":example.com"` (partial values do not match)
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
**`contains_display_name`**
|
**`contains_display_name`**
|
||||||
|
|
||||||
This matches unencrypted messages where `content.body` contains the
|
{{% changed-in v="1.17" %}}: this condition is deprecated and **should not be
|
||||||
owner's display name in that room. This is a separate rule because
|
used in new push rules**.
|
||||||
display names may change and as such it would be hard to maintain a rule
|
|
||||||
that matched the user's display name. This condition has no parameters.
|
This matches messages where `content.body` contains the owner's display name in
|
||||||
|
that room. This is a separate condition because display names may change and as such
|
||||||
|
it would be hard to maintain a rule that matched the user's display name. This
|
||||||
|
condition has no parameters.
|
||||||
|
|
||||||
**`room_member_count`**
|
**`room_member_count`**
|
||||||
|
|
||||||
|
|
@ -363,7 +412,10 @@ Parameters:
|
||||||
to look up the power level required to send a notification type from
|
to look up the power level required to send a notification type from
|
||||||
the `notifications` object in the power level event content.
|
the `notifications` object in the power level event content.
|
||||||
|
|
||||||
##### Predefined Rules
|
#### Predefined Rules
|
||||||
|
|
||||||
|
{{% changed-in v="1.17" %}}: the legacy default push rules that looked for
|
||||||
|
mentions in the `body` of the event were removed.
|
||||||
|
|
||||||
Homeservers can specify "server-default rules". They operate at a lower
|
Homeservers can specify "server-default rules". They operate at a lower
|
||||||
priority than "user-defined rules", except for the `.m.rule.master` rule
|
priority than "user-defined rules", except for the `.m.rule.master` rule
|
||||||
|
|
@ -372,7 +424,7 @@ for all server-default rules MUST start with a dot (".") to identify
|
||||||
them as "server-default". The following server-default rules are
|
them as "server-default". The following server-default rules are
|
||||||
specified:
|
specified:
|
||||||
|
|
||||||
###### Default Override Rules
|
##### Default Override Rules
|
||||||
|
|
||||||
**`.m.rule.master`**
|
**`.m.rule.master`**
|
||||||
|
|
||||||
|
|
@ -389,9 +441,7 @@ Definition:
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"conditions": [],
|
"conditions": [],
|
||||||
"actions": [
|
"actions": []
|
||||||
"dont_notify"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -410,12 +460,10 @@ Definition:
|
||||||
{
|
{
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"key": "content.msgtype",
|
"key": "content.msgtype",
|
||||||
"pattern": "m.notice",
|
"pattern": "m.notice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": []
|
||||||
"dont_notify",
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -475,27 +523,29 @@ Definition:
|
||||||
"pattern": "m.room.member"
|
"pattern": "m.room.member"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": []
|
||||||
"dont_notify"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**`.m.rule.contains_display_name`**
|
<a id="_m_rule_is_user_mention"></a> **`.m.rule.is_user_mention`**
|
||||||
|
|
||||||
Matches any message whose content is unencrypted and contains the user's
|
{{% added-in v="1.7" %}}
|
||||||
current display name in the room in which it was sent.
|
|
||||||
|
Matches any message which contains the user's Matrix ID in the list of `user_ids`
|
||||||
|
under the `m.mentions` property.
|
||||||
|
|
||||||
Definition:
|
Definition:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"rule_id": ".m.rule.contains_display_name",
|
"rule_id": ".m.rule.is_user_mention",
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"kind": "contains_display_name"
|
"kind": "event_property_contains",
|
||||||
|
"key": "content.m\\.mentions.user_ids",
|
||||||
|
"value": "[the user's Matrix ID]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
|
|
@ -511,7 +561,41 @@ Definition:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**<a name="mruletombstone"></a>`.m.rule.tombstone`**
|
<a id="_m_rule_is_room_mention"></a> **`.m.rule.is_room_mention`**
|
||||||
|
|
||||||
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
|
Matches any message from a sender with the proper power level with the `room`
|
||||||
|
property of the `m.mentions` property set to `true`.
|
||||||
|
|
||||||
|
Definition:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"rule_id": ".m.rule.is_room_mention",
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"kind": "event_property_is",
|
||||||
|
"key": "content.m\\.mentions.room",
|
||||||
|
"value": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "sender_notification_permission",
|
||||||
|
"key": "room"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**<a id="mruletombstone"></a>`.m.rule.tombstone`**
|
||||||
|
|
||||||
Matches any state event whose type is `m.room.tombstone`. This is
|
Matches any state event whose type is `m.room.tombstone`. This is
|
||||||
intended to notify users of a room when it is upgraded, similar to what
|
intended to notify users of a room when it is upgraded, similar to what
|
||||||
|
|
@ -545,6 +629,31 @@ Definition:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**<a id="mrulereaction"></a>`.m.rule.reaction`**
|
||||||
|
|
||||||
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
|
Matches any event whose type is `m.reaction`. This suppresses notifications for [`m.reaction`](#mreaction) events.
|
||||||
|
|
||||||
|
Definition:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"rule_id": ".m.rule.reaction",
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"kind": "event_match",
|
||||||
|
"key": "type",
|
||||||
|
"pattern": "m.reaction"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actions": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
**`.m.rule.room.server_acl`**
|
**`.m.rule.room.server_acl`**
|
||||||
|
|
||||||
{{% added-in v="1.4" %}}
|
{{% added-in v="1.4" %}}
|
||||||
|
|
@ -574,67 +683,31 @@ Definition:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**`.m.rule.roomnotif`**
|
**`.m.rule.suppress_edits`**
|
||||||
|
|
||||||
Matches any message whose content is unencrypted and contains the text
|
{{% added-in v="1.9" %}}
|
||||||
`@room`, signifying the whole room should be notified of the event.
|
|
||||||
|
Suppresses notifications related to [event replacements](#event-replacements).
|
||||||
|
|
||||||
Definition:
|
Definition:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"rule_id": ".m.rule.roomnotif",
|
"rule_id": ".m.rule.suppress_edits",
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"kind": "event_match",
|
"kind": "event_property_is",
|
||||||
"key": "content.body",
|
"key": "content.m\\.relates_to.rel_type",
|
||||||
"pattern": "@room"
|
"value": "m.replace"
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "sender_notification_permission",
|
|
||||||
"key": "room"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": []
|
||||||
"notify",
|
|
||||||
{
|
|
||||||
"set_tweak": "highlight"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Default Content Rules
|
##### Default Underride Rules
|
||||||
|
|
||||||
**`.m.rule.contains_user_name`**
|
|
||||||
|
|
||||||
Matches any message whose content is unencrypted and contains the local
|
|
||||||
part of the user's Matrix ID, separated by word boundaries.
|
|
||||||
|
|
||||||
Definition (as a `content` rule):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"rule_id": ".m.rule.contains_user_name",
|
|
||||||
"default": true,
|
|
||||||
"enabled": true,
|
|
||||||
"pattern": "[the local part of the user's Matrix ID]",
|
|
||||||
"actions": [
|
|
||||||
"notify",
|
|
||||||
{
|
|
||||||
"set_tweak": "sound",
|
|
||||||
"value": "default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"set_tweak": "highlight"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Default Underride Rules
|
|
||||||
|
|
||||||
**`.m.rule.call`**
|
**`.m.rule.call`**
|
||||||
|
|
||||||
|
|
@ -783,14 +856,14 @@ Definition:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Push Rules: API
|
#### Push Rules: API
|
||||||
|
|
||||||
Clients can retrieve, add, modify and remove push rules globally or
|
Clients can retrieve, add, modify and remove push rules globally or
|
||||||
per-device using the APIs below.
|
per-device using the APIs below.
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="pushrules" %}}
|
{{% http-api spec="client-server" api="pushrules" %}}
|
||||||
|
|
||||||
##### Push Rules: Events
|
#### Push Rules: Events
|
||||||
|
|
||||||
When a user changes their push rules a `m.push_rules` event is sent to
|
When a user changes their push rules a `m.push_rules` event is sent to
|
||||||
all clients in the `account_data` section of their next [`/sync`](#get_matrixclientv3sync) request.
|
all clients in the `account_data` section of their next [`/sync`](#get_matrixclientv3sync) request.
|
||||||
|
|
@ -798,21 +871,21 @@ The content of the event is the current push rules for the user.
|
||||||
|
|
||||||
{{% event event="m.push_rules" %}}
|
{{% event event="m.push_rules" %}}
|
||||||
|
|
||||||
###### Examples
|
##### Examples
|
||||||
|
|
||||||
To create a rule that suppresses notifications for the room with ID
|
To create a rule that suppresses notifications for the room with ID
|
||||||
`!dj234r78wl45Gh4D:matrix.org`:
|
`!dj234r78wl45Gh4D:matrix.org`:
|
||||||
|
|
||||||
curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/v3/pushrules/global/room/%21dj234r78wl45Gh4D%3Amatrix.org?access_token=123456" -d \
|
curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/v3/pushrules/global/room/%21dj234r78wl45Gh4D%3Amatrix.org?access_token=123456" -d \
|
||||||
'{
|
'{
|
||||||
"actions" : ["dont_notify"]
|
"actions" : []
|
||||||
}'
|
}'
|
||||||
|
|
||||||
To suppress notifications for the user `@spambot:matrix.org`:
|
To suppress notifications for the user `@spambot:matrix.org`:
|
||||||
|
|
||||||
curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/v3/pushrules/global/sender/%40spambot%3Amatrix.org?access_token=123456" -d \
|
curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/v3/pushrules/global/sender/%40spambot%3Amatrix.org?access_token=123456" -d \
|
||||||
'{
|
'{
|
||||||
"actions" : ["dont_notify"]
|
"actions" : []
|
||||||
}'
|
}'
|
||||||
|
|
||||||
To always notify for messages that contain the work 'cake' and set a
|
To always notify for messages that contain the work 'cake' and set a
|
||||||
|
|
@ -849,14 +922,82 @@ than the room, sender and content rules):
|
||||||
]
|
]
|
||||||
}'
|
}'
|
||||||
|
|
||||||
|
|
||||||
|
#### Client behaviour
|
||||||
|
|
||||||
|
Clients MUST configure a Pusher before they will receive push
|
||||||
|
notifications. There is a single API endpoint for this, as described
|
||||||
|
below.
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="pusher" %}}
|
||||||
|
|
||||||
|
##### Listing Notifications
|
||||||
|
|
||||||
|
A client can retrieve a list of events that it has been notified about.
|
||||||
|
This may be useful so that users can see a summary of what important
|
||||||
|
messages they have received.
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="notifications" %}}
|
||||||
|
|
||||||
|
##### Receiving notifications
|
||||||
|
|
||||||
|
Servers MUST include the number of unread notifications in a client's
|
||||||
|
[`/sync`](#get_matrixclientv3sync) stream, and MUST update it as it changes. Notifications are
|
||||||
|
determined by the push rules which apply to an event.
|
||||||
|
|
||||||
|
For encrypted events, the homeserver has limited access to the event content
|
||||||
|
and properly processing push rules falls on the client. Clients should process
|
||||||
|
push rules for each incoming event *after decrypting* them. This may result in
|
||||||
|
needing to modify the number of unread notifications received from the homeserver.
|
||||||
|
|
||||||
|
##### Marking notifications as read
|
||||||
|
|
||||||
|
When the user updates their read receipt (either by using the API or by
|
||||||
|
sending an event), notifications prior to and including that event MUST
|
||||||
|
be marked as read. Which specific events are affected can vary depending
|
||||||
|
on whether a [threaded read receipt](#threaded-read-receipts) was used.
|
||||||
|
Note that users can send both an `m.read` and `m.read.private` receipt,
|
||||||
|
both of which are capable of clearing notifications.
|
||||||
|
|
||||||
|
If the user has both `m.read` and `m.read.private` set in the room then
|
||||||
|
the receipt which is more recent/ahead must be used to determine where
|
||||||
|
the user has read up to. For example, given an oldest-first set of events A,
|
||||||
|
B, C, and D the `m.read` receipt could be at event C and `m.read.private`
|
||||||
|
at event A - the user is considered to have read up to event C. If the
|
||||||
|
`m.read.private` receipt is then updated to point to B or C, the user's
|
||||||
|
notification state doesn't change (the `m.read` receipt is still more
|
||||||
|
ahead), however if the `m.read.private` receipt were to be updated to
|
||||||
|
event D then the user has read up to D (the `m.read` receipt is now
|
||||||
|
behind the `m.read.private` receipt).
|
||||||
|
|
||||||
|
{{% added-in v="1.4" %}} When handling threaded read receipts, the server is to
|
||||||
|
partition the notification count to each thread (with the main timeline being
|
||||||
|
its own thread). To determine if an event is part of a thread the server follows
|
||||||
|
the [event relationship](#forming-relationships-between-events) until it finds a
|
||||||
|
thread root via an `m.thread` relation (as specified by the [threading
|
||||||
|
module](#threading)), however it is not recommended that the server traverse
|
||||||
|
infinitely. Instead, implementations are encouraged to do a maximum of 3 hops to
|
||||||
|
find a thread before deciding that the event does not belong to a thread. This
|
||||||
|
is primarily to ensure that future events, like `m.reaction`, are correctly
|
||||||
|
considered "part of" a given thread.
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
|
When receiving a new event homeservers process push rules for each of the local
|
||||||
|
users in the room (excluding the sender). This may result in:
|
||||||
|
|
||||||
|
* Generating a new number of unread notifications for the user.
|
||||||
|
* Making a request to the configured push gateway.
|
||||||
|
|
||||||
|
The updated notification count from a new event MUST appear in the same [`/sync`](#get_matrixclientv3sync)
|
||||||
|
response as the event itself.
|
||||||
|
|
||||||
#### Push Gateway behaviour
|
#### Push Gateway behaviour
|
||||||
|
|
||||||
##### Recommendations for APNS
|
##### Recommendations for APNS
|
||||||
|
|
||||||
The exact format for sending APNS notifications is flexible and up to
|
The exact format for sending APNS notifications is flexible and up to
|
||||||
the client app and its' push gateway to agree on. As APNS requires that
|
the client app and its push gateway to agree on. As APNS requires that
|
||||||
the sender has a private key owned by the app developer, each app must
|
the sender has a private key owned by the app developer, each app must
|
||||||
have its own push gateway. It is recommended that:
|
have its own push gateway. It is recommended that:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
### Read and unread markers
|
||||||
|
|
||||||
### Fully read markers
|
#### Fully read markers
|
||||||
|
|
||||||
The history for a given room may be split into three sections: messages
|
The history for a given room may be split into three sections: messages
|
||||||
the user has read (or indicated they aren't interested in them),
|
the user has read (or indicated they aren't interested in them),
|
||||||
|
|
@ -8,7 +9,7 @@ user hasn't seen yet. The "fully read marker" (also known as a "read
|
||||||
marker") marks the last event of the first section, whereas the user's
|
marker") marks the last event of the first section, whereas the user's
|
||||||
read receipt marks the last event of the second section.
|
read receipt marks the last event of the second section.
|
||||||
|
|
||||||
#### Events
|
##### Events
|
||||||
|
|
||||||
The user's fully read marker is kept as an event in the room's [account
|
The user's fully read marker is kept as an event in the room's [account
|
||||||
data](#client-config). The event may be read to determine the user's
|
data](#client-config). The event may be read to determine the user's
|
||||||
|
|
@ -22,13 +23,13 @@ should be considered to be the user's read receipt location.
|
||||||
|
|
||||||
{{% event event="m.fully_read" %}}
|
{{% event event="m.fully_read" %}}
|
||||||
|
|
||||||
#### Client behaviour
|
##### Client behaviour
|
||||||
|
|
||||||
The client cannot update fully read markers by directly modifying the
|
The client cannot update fully read markers by directly modifying the
|
||||||
`m.fully_read` account data event. Instead, the client must make use of
|
`m.fully_read` account data event. Instead, the client must make use of
|
||||||
the read markers API to change the values.
|
the read markers API to change the values.
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} `m.read.private` receipts can now be sent from
|
{{% changed-in v="1.4" %}} `m.read.private` receipts can now be sent from
|
||||||
`/read_markers`.
|
`/read_markers`.
|
||||||
|
|
||||||
The read markers API can additionally update the user's read receipt
|
The read markers API can additionally update the user's read receipt
|
||||||
|
|
@ -41,7 +42,7 @@ might wish to save an extra HTTP call. Providing `m.read` and/or
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="read_markers" %}}
|
{{% http-api spec="client-server" api="read_markers" %}}
|
||||||
|
|
||||||
#### Server behaviour
|
##### Server behaviour
|
||||||
|
|
||||||
The server MUST prevent clients from setting `m.fully_read` directly in
|
The server MUST prevent clients from setting `m.fully_read` directly in
|
||||||
room account data. The server must additionally ensure that it treats
|
room account data. The server must additionally ensure that it treats
|
||||||
|
|
@ -53,3 +54,46 @@ Upon updating the `m.fully_read` event due to a request to
|
||||||
`/read_markers`, the server MUST send the updated account data event
|
`/read_markers`, the server MUST send the updated account data event
|
||||||
through to the client via the event stream (eg: `/sync`), provided any
|
through to the client via the event stream (eg: `/sync`), provided any
|
||||||
applicable filters are also satisfied.
|
applicable filters are also satisfied.
|
||||||
|
|
||||||
|
#### Unread markers
|
||||||
|
|
||||||
|
{{% added-in v="1.12" %}}
|
||||||
|
|
||||||
|
Clients may use "unread markers" to allow users to label rooms for later
|
||||||
|
attention irrespective of [read receipts](#receipts) or
|
||||||
|
[fully read markers](#fully-read-markers).
|
||||||
|
|
||||||
|
##### Events
|
||||||
|
|
||||||
|
The user's unread marker in a room is kept under an `m.marked_unread`
|
||||||
|
event in the room's [account data](#client-config). The event may be read
|
||||||
|
to determine the user's current unread marker state in the room. Just
|
||||||
|
like other account data events, the event will be pushed down the event
|
||||||
|
stream when updated.
|
||||||
|
|
||||||
|
{{% event event="m.marked_unread" %}}
|
||||||
|
|
||||||
|
##### Client behaviour
|
||||||
|
|
||||||
|
Clients MUST update unread markers by directly modifying the `m.marked_unread`
|
||||||
|
room account data event. When marking a room as unread, clients SHOULD NOT change
|
||||||
|
the `m.fully_read` marker, so that the user's read position in the room is
|
||||||
|
retained.
|
||||||
|
|
||||||
|
When the `unread` field is `true`, clients SHOULD visually annotate the room
|
||||||
|
to indicate that it is unread. Exactly how this is achieved is left as an
|
||||||
|
implementation detail. It is RECOMMENDED that clients use a treatment similar
|
||||||
|
to how they represent rooms with unread notifications.
|
||||||
|
|
||||||
|
Clients SHOULD reset the unread marker by setting `unread` to `false` when
|
||||||
|
opening a room to display its timeline.
|
||||||
|
|
||||||
|
Clients that offer functionality to mark a room as _read_ by sending a read
|
||||||
|
receipt for the last event, SHOULD reset the unread marker simultaneously.
|
||||||
|
|
||||||
|
If the `m.marked_unread` event does not exist on the user's account data,
|
||||||
|
clients MUST behave as if `unread` was `false`.
|
||||||
|
|
||||||
|
##### Server behaviour
|
||||||
|
|
||||||
|
Servers have no additional requirements placed on them by this submodule.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
### Receipts
|
### Receipts
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} Added private read receipts.
|
{{% changed-in v="1.4" %}} Added private read receipts.
|
||||||
|
|
||||||
This module adds in support for receipts. These receipts are a form of
|
This module adds in support for receipts. These receipts are a form of
|
||||||
acknowledgement of an event. This module defines the `m.read` receipt
|
acknowledgement of an event. This module defines the `m.read` receipt
|
||||||
|
|
@ -19,7 +19,7 @@ that the user had read all events *up to* the referenced event. See the
|
||||||
[Receiving notifications](#receiving-notifications) section for more
|
[Receiving notifications](#receiving-notifications) section for more
|
||||||
information on how read receipts affect notification counts.
|
information on how read receipts affect notification counts.
|
||||||
|
|
||||||
{{< added-in v="1.4" >}} Read receipts exist in three major forms:
|
{{% added-in v="1.4" %}} Read receipts exist in three major forms:
|
||||||
* Unthreaded: Denotes a read-up-to receipt regardless of threads. This is how
|
* Unthreaded: Denotes a read-up-to receipt regardless of threads. This is how
|
||||||
pre-threading read receipts worked.
|
pre-threading read receipts worked.
|
||||||
* Threaded, main timeline: Denotes a read-up-to receipt for events not in a
|
* Threaded, main timeline: Denotes a read-up-to receipt for events not in a
|
||||||
|
|
@ -31,7 +31,7 @@ Threaded read receipts are discussed in further detail [below](#threaded-read-re
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} Each `user_id`, `receipt_type`, and categorisation
|
{{% changed-in v="1.4" %}} Each `user_id`, `receipt_type`, and categorisation
|
||||||
(unthreaded, or `thread_id`) tuple must be associated with only a single
|
(unthreaded, or `thread_id`) tuple must be associated with only a single
|
||||||
`event_id`.
|
`event_id`.
|
||||||
|
|
||||||
|
|
@ -39,9 +39,9 @@ Threaded read receipts are discussed in further detail [below](#threaded-read-re
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} Altered to support threaded read receipts.
|
{{% changed-in v="1.4" %}} Altered to support threaded read receipts.
|
||||||
|
|
||||||
In `/sync`, receipts are listed under the `ephemeral` array of events
|
In [`/sync`](#get_matrixclientv3sync), receipts are listed under the `ephemeral` array of events
|
||||||
for a given room. New receipts that come down the event streams are
|
for a given room. New receipts that come down the event streams are
|
||||||
deltas which update existing mappings. Clients should replace older
|
deltas which update existing mappings. Clients should replace older
|
||||||
receipt acknowledgements based on `user_id`, `receipt_type`, and the
|
receipt acknowledgements based on `user_id`, `receipt_type`, and the
|
||||||
|
|
@ -137,32 +137,30 @@ either a thread root's event ID or `main` for the main timeline.
|
||||||
|
|
||||||
Threading introduces a concept of multiple conversations being held in the same
|
Threading introduces a concept of multiple conversations being held in the same
|
||||||
room and thus deserve their own read receipts and notification counts. An event is
|
room and thus deserve their own read receipts and notification counts. An event is
|
||||||
considered to be "in a thread" if it meets any of the following criteria:
|
considered to be "in a thread" if:
|
||||||
* It has a `rel_type` of `m.thread`.
|
|
||||||
* It has child events with a `rel_type` of `m.thread` (in which case it'd be the
|
|
||||||
thread root).
|
|
||||||
* Following the event relationships, it has a parent event which qualifies for
|
|
||||||
one of the above. Implementations should not recurse infinitely, though: a
|
|
||||||
maximum of 3 hops is recommended to cover indirect relationships.
|
|
||||||
|
|
||||||
Events not in a thread but still in the room are considered to be part of the
|
* It has a `rel_type` of `m.thread`, or
|
||||||
"main timeline", or a special thread with an ID of `main`.
|
* Following the event relationships, it has a parent event which references
|
||||||
|
the thread root with a `rel_type` of `m.thread`. Implementations should
|
||||||
|
not recurse infinitely, though: a maximum of 3 hops is recommended to
|
||||||
|
cover indirect relationships.
|
||||||
|
|
||||||
|
Events not in a thread but still in the room are considered to be in the "main
|
||||||
|
timeline". When referring to the main timeline as a thread (e.g. in receipts
|
||||||
|
and notifications counts) a special thread ID of `main` is used.
|
||||||
|
|
||||||
|
Thread roots are considered to be in the main timeline, as are events that are
|
||||||
|
related to a thread root via non-thread relations.
|
||||||
|
|
||||||
The following is an example DAG for a room, with dotted lines showing event
|
The following is an example DAG for a room, with dotted lines showing event
|
||||||
relationships and solid lines showing topological ordering.
|
relationships and solid lines showing topological ordering.
|
||||||
|
|
||||||

|
{{% diagram name="threaded-dag" alt="Diagram presenting a DAG with thread relationships as a single timeline" %}}
|
||||||
|
|
||||||
{{% boxes/note %}}
|
|
||||||
`m.reaction` relationships are not currently specified, but are shown here for
|
|
||||||
their conceptual place in a threaded DAG. They are currently proposed as
|
|
||||||
[MSC2677](https://github.com/matrix-org/matrix-spec-proposals/pull/2677).
|
|
||||||
{{% /boxes/note %}}
|
|
||||||
|
|
||||||
This DAG can be represented as 3 threaded timelines, with `A` and `B` being thread
|
This DAG can be represented as 3 threaded timelines, with `A` and `B` being thread
|
||||||
roots:
|
roots:
|
||||||
|
|
||||||

|
{{% diagram name="threaded-dag-threads" alt="Diagram presenting a DAG with thread relationships as 3 related timelines" %}}
|
||||||
|
|
||||||
With this, we can demonstrate that:
|
With this, we can demonstrate that:
|
||||||
* A threaded read receipt on `I` would mark `A`, `B`, and `I` as read.
|
* A threaded read receipt on `I` would mark `A`, `B`, and `I` as read.
|
||||||
|
|
@ -210,13 +208,13 @@ event when the user expands that thread.
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
For efficiency, receipts SHOULD be batched into one event per room
|
For efficiency, receipts SHOULD be batched into one event per room and thread
|
||||||
before delivering them to clients.
|
before delivering them to clients.
|
||||||
|
|
||||||
Some receipts are sent across federation as EDUs with type `m.receipt`. The
|
Some receipts are sent across federation as EDUs with type `m.receipt`. The
|
||||||
format of the EDUs are:
|
format of the EDUs are:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{
|
{
|
||||||
<room_id>: {
|
<room_id>: {
|
||||||
<receipt_type>: {
|
<receipt_type>: {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
### Reference relations
|
### Reference relations
|
||||||
|
|
||||||
{{% added-in v="1.4" %}}
|
{{% added-in v="1.5" %}}
|
||||||
|
|
||||||
Generically referencing another event can be done with a `rel_type` of `m.reference`
|
Generically referencing another event can be done with a `rel_type` of `m.reference`
|
||||||
as a form of [relationship](#forming-relationships-between-events). There is no
|
as a form of [relationship](#forming-relationships-between-events). There is no
|
||||||
|
|
@ -19,11 +19,12 @@ messages.
|
||||||
|
|
||||||
##### Server-side aggregation of `m.reference`
|
##### Server-side aggregation of `m.reference`
|
||||||
|
|
||||||
The aggregation format of `m.reference` relations consists of a single `chunk` property,
|
The [aggregation](#aggregations-of-child-events) format of `m.reference`
|
||||||
which lists all the events which `m.reference` the event (the parent). Currently,
|
relations consists of a single `chunk` property, which lists all the events
|
||||||
only a single `event_id` field is present on the events in the `chunk`.
|
which `m.reference` the event (the parent). Currently, only a single `event_id`
|
||||||
|
field is present on the events in the `chunk`.
|
||||||
|
|
||||||
An example `m.reference` would be:
|
For example, given an event with the following `m.reference` relationship:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -38,7 +39,7 @@ An example `m.reference` would be:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The [bundle](#aggregations) under `m.relations` would appear similar to the following:
|
The aggregation would appear similar to the following:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,6 @@ Users may encounter content which they find inappropriate and should be
|
||||||
able to report it to the server administrators or room moderators for
|
able to report it to the server administrators or room moderators for
|
||||||
review. This module defines a way for users to report content.
|
review. This module defines a way for users to report content.
|
||||||
|
|
||||||
Content is reported based upon a negative score, where -100 is "most
|
|
||||||
offensive" and 0 is "inoffensive".
|
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="report_content" %}}
|
{{% http-api spec="client-server" api="report_content" %}}
|
||||||
|
|
@ -18,3 +15,23 @@ Servers are free to handle the reported content however they desire.
|
||||||
This may be a dedicated room to alert server administrators to the
|
This may be a dedicated room to alert server administrators to the
|
||||||
reported content or some other mechanism for notifying the appropriate
|
reported content or some other mechanism for notifying the appropriate
|
||||||
people.
|
people.
|
||||||
|
|
||||||
|
Particularly during waves of harmful content, users may report whole
|
||||||
|
rooms instead of individual events. Server administrators and safety teams
|
||||||
|
should, therefore, be cautious not to shut down rooms that might otherwise
|
||||||
|
be legitimate.
|
||||||
|
|
||||||
|
{{% changed-in v="1.8" %}} When processing event reports, servers MUST
|
||||||
|
verify that the reporting user is currently joined to the room the event
|
||||||
|
is in before accepting a report.
|
||||||
|
|
||||||
|
{{% added-in v="1.13" %}} Contrarily, servers MUST NOT restrict room reports
|
||||||
|
based on whether or not the reporting user is joined to the room. This is
|
||||||
|
because users can be exposed to harmful content without being joined to a
|
||||||
|
room. For instance, through room directories or invites.
|
||||||
|
|
||||||
|
{{% added-in v="1.14" %}} Similarly, servers MUST NOT restrict user reports
|
||||||
|
based on whether or not the reporting user is joined to any rooms that the
|
||||||
|
reported user is joined to. This is because users can be exposed to harmful
|
||||||
|
content without being joined to a room. For instance, through user
|
||||||
|
directories or invites.
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
|
|
||||||
### Rich replies
|
### Rich replies
|
||||||
|
|
||||||
{{% changed-in v="1.3" %}}
|
|
||||||
|
|
||||||
Rich replies are a
|
Rich replies are a
|
||||||
special kind of [relationship](#forming-relationships-between-events) which
|
special kind of [relationship](#forming-relationships-between-events) which
|
||||||
effectively quotes the referenced event for the client to render/process how
|
effectively quotes the referenced event for the client to render/process how
|
||||||
it wishes. They are normally used with [`m.room.message`](#mroommessage) events.
|
it wishes. They are normally used with [`m.room.message`](#mroommessage) events.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
|
{{% changed-in v="1.3" %}}
|
||||||
Until v1.3 of the spec, rich replies were limited to `m.room.message` events
|
Until v1.3 of the spec, rich replies were limited to `m.room.message` events
|
||||||
which could represent an HTML-formatted body. As of v1.3 this is now expanded
|
which could represent an HTML-formatted body. As of v1.3 this is now expanded
|
||||||
to *all* event types by dropping the requirement that an HTML-formatted body
|
to *all* event types by dropping the requirement that an HTML-formatted body
|
||||||
|
|
@ -18,9 +17,24 @@ Additionally, a rich reply can reference any other event type as of v1.3.
|
||||||
Previously, a rich reply could only reference another `m.room.message` event.
|
Previously, a rich reply could only reference another `m.room.message` event.
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
When possible, events SHOULD include a [fallback representation](#fallbacks-for-rich-replies)
|
{{% boxes/note %}}
|
||||||
to allow clients which do not render rich replies to still see something which
|
{{% changed-in v="1.13" %}}
|
||||||
appears to be a quoted reply.
|
In previous versions of the specification, rich replies could include a fallback
|
||||||
|
representation of the original message in the `body` (using a prefix sequence)
|
||||||
|
and `formatted_body` (using a custom HTML element) for clients that do not
|
||||||
|
support rich replies. This is no longer the case, but clients SHOULD still
|
||||||
|
remove this fallback before rendering the event.
|
||||||
|
|
||||||
|
To strip the fallback on the `body`, the client should iterate over each
|
||||||
|
line of the string, removing any lines that start with the fallback
|
||||||
|
prefix sequence (`> `, including the trailing space) and stopping when
|
||||||
|
a line is encountered without the prefix.
|
||||||
|
|
||||||
|
To strip the fallback on the `formatted_body` of an `m.room.message` event with
|
||||||
|
a `format` of `org.matrix.custom.html`: if the`formatted_body` begins with an
|
||||||
|
`<mx-reply>` start tag, the client should remove the entirety of the
|
||||||
|
`<mx-reply>` element.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
Though rich replies form a relationship to another event, they do not
|
Though rich replies form a relationship to another event, they do not
|
||||||
use `rel_type` to create this relationship. Instead, a subkey named `m.in_reply_to`
|
use `rel_type` to create this relationship. Instead, a subkey named `m.in_reply_to`
|
||||||
|
|
@ -31,7 +45,7 @@ the `rel_type` and `event_id` properties of `m.relates_to` become *optional*.
|
||||||
|
|
||||||
An example reply would be:
|
An example reply would be:
|
||||||
|
|
||||||
```json5
|
```json
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
|
|
@ -48,132 +62,35 @@ An example reply would be:
|
||||||
Note that the `event_id` of the `m.in_reply_to` object has the same requirements
|
Note that the `event_id` of the `m.in_reply_to` object has the same requirements
|
||||||
as if it were to be under `m.relates_to` directly instead.
|
as if it were to be under `m.relates_to` directly instead.
|
||||||
|
|
||||||
#### Fallbacks for rich replies
|
#### Mentioning the replied to user
|
||||||
|
|
||||||
Some clients may not have support for rich replies and therefore need a
|
{{% boxes/note %}}
|
||||||
fallback to use instead. Clients that do not support rich replies should
|
{{% changed-in v="1.16" %}}
|
||||||
render the event as if rich replies were not special.
|
Clients SHOULD no longer propagate mentioned users in the replied to event.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
Clients that do support rich replies SHOULD provide the fallback format on
|
In order to notify users of the reply, it MAY be desirable to include the `sender`
|
||||||
replies, and MUST strip the fallback before rendering the reply. The
|
of the replied to event. See [user and room mentions](#user-and-room-mentions) for
|
||||||
specific fallback text is different for each `msgtype`, however the
|
additional information.
|
||||||
general format for the `body` is:
|
|
||||||
|
|
||||||
```text
|
An example including mentioning the original sender:
|
||||||
> <@alice:example.org> This is the original body
|
|
||||||
|
|
||||||
This is where the reply goes
|
```json
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"m.relates_to": {
|
||||||
|
"m.in_reply_to": {
|
||||||
|
"event_id": "$another_event"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": "That sounds like a great idea!",
|
||||||
|
"m.mentions": {
|
||||||
|
"user_ids": [
|
||||||
|
// The sender of $another_event.
|
||||||
|
"@alice:example.org",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// other fields as required by events
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `formatted_body`, if present and using an associated `format` of
|
|
||||||
`org.matrix.custom.html`, should use the following template:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<mx-reply>
|
|
||||||
<blockquote>
|
|
||||||
<a href="https://matrix.to/#/!somewhere:example.org/$event:example.org">In reply to</a>
|
|
||||||
<a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a>
|
|
||||||
<br />
|
|
||||||
<!-- This is where the related event's HTML would be. -->
|
|
||||||
</blockquote>
|
|
||||||
</mx-reply>
|
|
||||||
This is where the reply goes.
|
|
||||||
```
|
|
||||||
|
|
||||||
If the related event does not have a `formatted_body`, the event's
|
|
||||||
`body` should be considered after encoding any HTML special characters.
|
|
||||||
Note that the `href` in both of the anchors use a [matrix.to
|
|
||||||
URI](/appendices#matrixto-navigation).
|
|
||||||
|
|
||||||
##### Stripping the fallback
|
|
||||||
|
|
||||||
Clients which support rich replies MUST strip the fallback from the
|
|
||||||
event before rendering the event. This is because the text provided in
|
|
||||||
the fallback cannot be trusted to be an accurate representation of the
|
|
||||||
event. After removing the fallback, clients are recommended to represent
|
|
||||||
the event referenced by `m.in_reply_to` similar to the fallback's
|
|
||||||
representation, although clients do have creative freedom for their user
|
|
||||||
interface. Clients should prefer the `formatted_body` over the `body`,
|
|
||||||
just like with other `m.room.message` events.
|
|
||||||
|
|
||||||
To strip the fallback on the `body`, the client should iterate over each
|
|
||||||
line of the string, removing any lines that start with the fallback
|
|
||||||
prefix ("> ", including the space, without quotes) and stopping when
|
|
||||||
a line is encountered without the prefix. This prefix is known as the
|
|
||||||
"fallback prefix sequence".
|
|
||||||
|
|
||||||
To strip the fallback on the `formatted_body`, the client should remove
|
|
||||||
the entirety of the `mx-reply` tag.
|
|
||||||
|
|
||||||
##### Fallback for `m.text`, `m.notice`, and unrecognised message types
|
|
||||||
|
|
||||||
Using the prefix sequence, the first line of the related event's `body`
|
|
||||||
should be prefixed with the user's ID, followed by each line being
|
|
||||||
prefixed with the fallback prefix sequence. For example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
> <@alice:example.org> This is the first line
|
|
||||||
> This is the second line
|
|
||||||
|
|
||||||
This is the reply
|
|
||||||
```
|
|
||||||
|
|
||||||
The `formatted_body` uses the template defined earlier in this section.
|
|
||||||
|
|
||||||
##### Fallback for `m.emote`
|
|
||||||
|
|
||||||
Similar to the fallback for `m.text`, each line gets prefixed with the
|
|
||||||
fallback prefix sequence. However an asterisk should be inserted before
|
|
||||||
the user's ID, like so:
|
|
||||||
|
|
||||||
```text
|
|
||||||
> * <@alice:example.org> feels like today is going to be a great day
|
|
||||||
|
|
||||||
This is the reply
|
|
||||||
```
|
|
||||||
|
|
||||||
The `formatted_body` has a subtle difference for the template where the
|
|
||||||
asterisk is also inserted ahead of the user's ID:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<mx-reply>
|
|
||||||
<blockquote>
|
|
||||||
<a href="https://matrix.to/#/!somewhere:example.org/$event:example.org">In reply to</a>
|
|
||||||
* <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a>
|
|
||||||
<br />
|
|
||||||
<!-- This is where the related event's HTML would be. -->
|
|
||||||
</blockquote>
|
|
||||||
</mx-reply>
|
|
||||||
This is where the reply goes.
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Fallback for `m.image`, `m.video`, `m.audio`, and `m.file`
|
|
||||||
|
|
||||||
The related event's `body` would be a file name, which may not be very
|
|
||||||
descriptive. The related event should additionally not have a `format`
|
|
||||||
or `formatted_body` in the `content` - if the event does have a `format`
|
|
||||||
and/or `formatted_body`, those fields should be ignored. Because the
|
|
||||||
filename alone may not be descriptive, the related event's `body` should
|
|
||||||
be considered to be `"sent a file."` such that the output looks similar
|
|
||||||
to the following:
|
|
||||||
|
|
||||||
```text
|
|
||||||
> <@alice:example.org> sent a file.
|
|
||||||
|
|
||||||
This is the reply
|
|
||||||
```
|
|
||||||
```html
|
|
||||||
<mx-reply>
|
|
||||||
<blockquote>
|
|
||||||
<a href="https://matrix.to/#/!somewhere:example.org/$event:example.org">In reply to</a>
|
|
||||||
<a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a>
|
|
||||||
<br />
|
|
||||||
sent a file.
|
|
||||||
</blockquote>
|
|
||||||
</mx-reply>
|
|
||||||
This is where the reply goes.
|
|
||||||
```
|
|
||||||
|
|
||||||
For `m.image`, the text should be `"sent an image."`. For `m.video`, the
|
|
||||||
text should be `"sent a video."`. For `m.audio`, the text should be
|
|
||||||
`"sent an audio file"`.
|
|
||||||
|
|
@ -6,14 +6,14 @@ It is sometimes desirable to offer a preview of a room, where a user can
|
||||||
This can be particularly effective when combined with [Guest Access](#guest-access).
|
This can be particularly effective when combined with [Guest Access](#guest-access).
|
||||||
|
|
||||||
Previews are implemented via the `world_readable` [Room History
|
Previews are implemented via the `world_readable` [Room History
|
||||||
Visibility](#room-history-visibility). setting, along with a special version of the [GET
|
Visibility](#room-history-visibility) setting, along with a special version of the [GET
|
||||||
/events](#get_matrixclientv3events) endpoint.
|
/events](#get_matrixclientv3events) endpoint.
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
A client wishing to view a room without joining it should call [GET
|
A client wishing to view a room without joining it should call [GET
|
||||||
/rooms/:room\_id/initialSync](#get_matrixclientv3roomsroomidinitialsync),
|
/rooms/:room\_id/initialSync](#get_matrixclientv3roomsroomidinitialsync),
|
||||||
followed by [GET /events](#get_matrixclientv3events). Clients will need to do
|
followed by [GET /events](#peeking_get_matrixclientv3events). Clients will need to do
|
||||||
this in parallel for each room they wish to view.
|
this in parallel for each room they wish to view.
|
||||||
|
|
||||||
Clients can of course also call other endpoints such as [GET
|
Clients can of course also call other endpoints such as [GET
|
||||||
|
|
@ -21,7 +21,7 @@ Clients can of course also call other endpoints such as [GET
|
||||||
and [GET /search](#post_matrixclientv3search) to
|
and [GET /search](#post_matrixclientv3search) to
|
||||||
access events outside the `/events` stream.
|
access events outside the `/events` stream.
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="peeking_events" %}}
|
{{% http-api spec="client-server" api="peeking_events" anchor_base="peeking" %}}
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,23 @@ server:
|
||||||
1. Checks that the user has permission to send `m.room.tombstone`
|
1. Checks that the user has permission to send `m.room.tombstone`
|
||||||
events in the room.
|
events in the room.
|
||||||
|
|
||||||
2. {{< changed-in v="1.4" >}} Creates a replacement room with a `m.room.create` event containing a
|
2. {{% changed-in v="1.4" %}} Creates a replacement room with a `m.room.create` event containing a
|
||||||
`predecessor` field, the applicable `room_version`, and a `type` field
|
`predecessor` field, the applicable `room_version`, and a `type` field
|
||||||
which is copied from the `predecessor` room. If no `type` is set on the
|
which is copied from the `predecessor` room. If no `type` is set on the
|
||||||
previous room, no `type` is specified on the new room's create event
|
previous room, no `type` is specified on the new room's create event
|
||||||
either.
|
either.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.16" %}} If both the new and old [room version](/rooms) support
|
||||||
|
additional creators, the server will not transfer those additional creators automatically.
|
||||||
|
They must be explicitly set during the `/upgrade` call.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
{{% added-in v="1.16" %}} When upgrading to room version 12 or later, the `predecessor` field MAY NOT contain
|
||||||
|
an `event_id`.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
3. Replicates transferable state events to the new room. The exact
|
3. Replicates transferable state events to the new room. The exact
|
||||||
details for what is transferred is left as an implementation detail,
|
details for what is transferred is left as an implementation detail,
|
||||||
however the recommended state events to transfer are:
|
however the recommended state events to transfer are:
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,10 @@ on certain keys of certain event types.
|
||||||
|
|
||||||
The supported keys to search over are:
|
The supported keys to search over are:
|
||||||
|
|
||||||
- `content.body` in `m.room.message`
|
- `content.body` in [`m.room.message`](/client-server-api/#mroommessage)
|
||||||
- `content.name` in `m.room.name`
|
- `content.name` in [`m.room.name`](/client-server-api/#mroomname)
|
||||||
- `content.topic` in `m.room.topic`
|
- In [`m.room.topic`](/client-server-api/#mroomtopic), `content.topic`
|
||||||
|
as well as the `body` of the `text/plain` representation in `content['m.topic']`.
|
||||||
|
|
||||||
The search will *not* include rooms that are end to end encrypted.
|
The search will *not* include rooms that are end to end encrypted.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ secret when storing, fetching, requesting, or sharing the secret.
|
||||||
Secrets are plain strings; structured data can be stored by encoding it
|
Secrets are plain strings; structured data can be stored by encoding it
|
||||||
as a string.
|
as a string.
|
||||||
|
|
||||||
|
The mechanism described in this section is known as "secure secret storage and
|
||||||
|
sharing", "SSSS", or "4S".
|
||||||
|
|
||||||
#### Storage
|
#### Storage
|
||||||
|
|
||||||
When secrets are stored on the server, they are stored in the user's
|
When secrets are stored on the server, they are stored in the user's
|
||||||
|
|
@ -55,8 +58,8 @@ available on all their clients. Unless the user specifies otherwise,
|
||||||
clients will try to use the default key to decrypt secrets.
|
clients will try to use the default key to decrypt secrets.
|
||||||
|
|
||||||
Clients that want to present a simplified interface to users by not supporting
|
Clients that want to present a simplified interface to users by not supporting
|
||||||
multiple keys should use the default key if one is specified. If not default
|
multiple keys should use the default key if one is specified. If no default
|
||||||
key is specified, the client may behave as if there is no key is present at
|
key is specified, the client may behave as if no key is present at
|
||||||
all. When such a client creates a key, it should mark that key as being the
|
all. When such a client creates a key, it should mark that key as being the
|
||||||
default key.
|
default key.
|
||||||
|
|
||||||
|
|
@ -66,6 +69,70 @@ default key.
|
||||||
|------------|-----------|------------------------------------------|
|
|------------|-----------|------------------------------------------|
|
||||||
| key | string | **Required.** The ID of the default key. |
|
| key | string | **Required.** The ID of the default key. |
|
||||||
|
|
||||||
|
|
||||||
|
###### `m.secret_storage.v1.aes-hmac-sha2`
|
||||||
|
|
||||||
|
For the purposes of allowing clients to check whether a user has correctly
|
||||||
|
entered the key, keys for use with the `m.secret_storage.v1.aes-hmac-sha2`
|
||||||
|
algorithm are stored with some additional data.
|
||||||
|
|
||||||
|
When storing a key, clients SHOULD:
|
||||||
|
|
||||||
|
1. Given the secret storage key, generate 64 bytes by performing an
|
||||||
|
HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and the empty
|
||||||
|
string as the info. The first 32 bytes are used as the AES key,
|
||||||
|
and the next 32 bytes are used as the MAC key.
|
||||||
|
|
||||||
|
2. Generate 16 random bytes, set bit 63 to 0 (in order to work around
|
||||||
|
differences in AES-CTR implementations), and use this as the AES
|
||||||
|
initialization vector (IV).
|
||||||
|
|
||||||
|
3. Encrypt a message consisting of 32 bytes of 0, using AES-CTR-256 using the
|
||||||
|
AES key and IV generated above.
|
||||||
|
|
||||||
|
4. Pass the raw encrypted data through HMAC-SHA-256 using the MAC key
|
||||||
|
generated above.
|
||||||
|
|
||||||
|
5. Encode the IV from step 2, and the MAC from step 4, using [unpadded
|
||||||
|
base64](/appendices/#unpadded-base64), and store the results in the `iv`
|
||||||
|
and `mac` properties respectively in the `m.secret_storage.key.[key ID]`
|
||||||
|
account-data. (The ciphertext from step 3 is discarded after passing
|
||||||
|
through the MAC calculation.)
|
||||||
|
|
||||||
|
This process can be repeated by a client checking if the key is correct: the
|
||||||
|
MAC should match if the key is correct. Note, however, that these properties
|
||||||
|
are **optional**. If they are not present, clients must assume that the key is
|
||||||
|
valid.
|
||||||
|
|
||||||
|
Note also, that although clients SHOULD use unpadded base64 as specified above,
|
||||||
|
some existing implementations use standard [RFC4648-compliant
|
||||||
|
base64](https://datatracker.ietf.org/doc/html/rfc4648#section-4) with padding,
|
||||||
|
so clients must accept either encoding.
|
||||||
|
|
||||||
|
The structure of a `m.secret_storage.key.[key ID]` account data object for use
|
||||||
|
with this algorithm is therefore as follows:
|
||||||
|
|
||||||
|
`AesHmacSha2KeyDescription`
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|-------------|--------|------------------------------------------------------------------------------------------------------|
|
||||||
|
| name | string | Optional. The name of the key. |
|
||||||
|
| algorithm | string | **Required.** The encryption algorithm to be used for this key: `m.secret_storage.v1.aes-hmac-sha2`. |
|
||||||
|
| passphrase | object | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
|
||||||
|
| iv | string | Optional. The 16-byte initialization vector for the validation check, encoded as base64. |
|
||||||
|
| mac | string | Optional. The MAC of the result of encrypting 32 bytes of 0, encoded as base64. |
|
||||||
|
|
||||||
|
For example, it could look like:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "m.default",
|
||||||
|
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
||||||
|
"iv": "random+data",
|
||||||
|
"mac": "mac+of+encrypted+zeros"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
##### Secret storage
|
##### Secret storage
|
||||||
|
|
||||||
Encrypted data is stored in the user's account data using the event
|
Encrypted data is stored in the user's account data using the event
|
||||||
|
|
@ -82,7 +149,7 @@ of the data.
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
|-----------|------------------|-------------|
|
|-----------|------------------|-------------|
|
||||||
| encrypted | {string: object} | **Required.** Map from key ID the encrypted data. The exact format for the encrypted data is dependent on the key algorithm. See the definition of `AesHmacSha2EncryptedData` in the [m.secret_storage.v1.aes-hmac-sha2](#msecret_storagev1aes-hmac-sha2) section. |
|
| encrypted | {string: object} | **Required.** Map from key ID the encrypted data. The exact format for the encrypted data is dependent on the key algorithm. See the definition of `AesHmacSha2EncryptedData` in the [m.secret_storage.v1.aes-hmac-sha2](#msecret_storagev1aes-hmac-sha2-1) section. |
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
@ -90,7 +157,7 @@ Some secret is encrypted using keys with ID `key_id_1` and `key_id_2`:
|
||||||
|
|
||||||
`org.example.some.secret`:
|
`org.example.some.secret`:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{
|
{
|
||||||
"encrypted": {
|
"encrypted": {
|
||||||
"key_id_1": {
|
"key_id_1": {
|
||||||
|
|
@ -110,7 +177,7 @@ and the key descriptions for the keys would be:
|
||||||
|
|
||||||
`m.secret_storage.key.key_id_1`:
|
`m.secret_storage.key.key_id_1`:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{
|
{
|
||||||
"name": "Some key",
|
"name": "Some key",
|
||||||
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
||||||
|
|
@ -120,7 +187,7 @@ and the key descriptions for the keys would be:
|
||||||
|
|
||||||
`m.secret_storage.key.key_id_2`:
|
`m.secret_storage.key.key_id_2`:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{
|
{
|
||||||
"name": "Some other key",
|
"name": "Some other key",
|
||||||
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
||||||
|
|
@ -132,7 +199,7 @@ If `key_id_1` is the default key, then we also have:
|
||||||
|
|
||||||
`m.secret_storage.default_key`:
|
`m.secret_storage.default_key`:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{
|
{
|
||||||
"key": "key_id_1"
|
"key": "key_id_1"
|
||||||
}
|
}
|
||||||
|
|
@ -147,58 +214,41 @@ HMAC-SHA-256. The secret is encrypted as follows:
|
||||||
1. Given the secret storage key, generate 64 bytes by performing an
|
1. Given the secret storage key, generate 64 bytes by performing an
|
||||||
HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and with the
|
HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and with the
|
||||||
secret name as the info. The first 32 bytes are used as the AES key,
|
secret name as the info. The first 32 bytes are used as the AES key,
|
||||||
and the next 32 bytes are used as the MAC key
|
and the next 32 bytes are used as the MAC key.
|
||||||
|
|
||||||
2. Generate 16 random bytes, set bit 63 to 0 (in order to work around
|
2. Generate 16 random bytes, set bit 63 to 0 (in order to work around
|
||||||
differences in AES-CTR implementations), and use this as the AES
|
differences in AES-CTR implementations), and use this as the AES
|
||||||
initialization vector. This becomes the `iv` property, encoded using
|
initialization vector (IV).
|
||||||
base64.
|
|
||||||
3. Encrypt the data using AES-CTR-256 using the AES key generated
|
3. Encrypt the data using AES-CTR-256 using the AES key and IV generated
|
||||||
above. This encrypted data, encoded using base64, becomes the
|
above.
|
||||||
`ciphertext` property.
|
|
||||||
4. Pass the raw encrypted data (prior to base64 encoding) through
|
4. Pass the raw encrypted data through HMAC-SHA-256 using the MAC key
|
||||||
HMAC-SHA-256 using the MAC key generated above. The resulting MAC is
|
generated above.
|
||||||
base64-encoded and becomes the `mac` property.
|
|
||||||
|
5. Encode the IV from step 2, the ciphertext from step 3, and MAC from step 4,
|
||||||
|
using [unpadded base64](/appendices/#unpadded-base64), and store them as
|
||||||
|
the `iv`, `ciphertext`, and `mac` properties respectively in the account
|
||||||
|
data object.
|
||||||
|
|
||||||
|
**Note**: some existing implementations encode these properties using
|
||||||
|
standard [RFC4648-compliant
|
||||||
|
base64](https://datatracker.ietf.org/doc/html/rfc4648#section-4) with
|
||||||
|
padding, so clients must accept either encoding.
|
||||||
|
|
||||||
|
The structure of the `encrypted` property of an account data object encrypted
|
||||||
|
with this algorithm is therefore as follows:
|
||||||
|
|
||||||
`AesHmacSha2EncryptedData`
|
`AesHmacSha2EncryptedData`
|
||||||
|
|
||||||
| Parameter | Type | Description
|
| Parameter | Type | Description
|
||||||
|------------|---------|------------------------------------------------------------------------|
|
|------------|---------|------------------------------------------------------------------------|
|
||||||
| iv | string | **Required.** The 16-byte initialization vector, encoded as base64. |
|
| iv | string | **Required.** The 16-byte initialization vector, encoded as base64. |
|
||||||
| ciphertext | string | **Required.** The AES-CTR-encrypted data, encoded as base64. |
|
| ciphertext | string | **Required.** The AES-CTR-encrypted data, encoded as base64. |
|
||||||
| mac | string | **Required.** The MAC, encoded as base64. |
|
| mac | string | **Required.** The MAC, encoded as base64. |
|
||||||
|
|
||||||
For the purposes of allowing clients to check whether a user has
|
|
||||||
correctly entered the key, clients should:
|
|
||||||
|
|
||||||
1. encrypt and MAC a message consisting of 32 bytes of 0 as described
|
For example, data encrypted using this algorithm could look like this:
|
||||||
above, using the empty string as the info parameter to the HKDF in
|
|
||||||
step 1.
|
|
||||||
2. store the `iv` and `mac` in the `m.secret_storage.key.[key ID]`
|
|
||||||
account-data.
|
|
||||||
|
|
||||||
`AesHmacSha2KeyDescription`
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
|-------------|--------|-----------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| name | string | Optional. The name of the key. |
|
|
||||||
| algorithm | string | **Required.** The encryption algorithm to be used for this key. Currently, only `m.secret_storage.v1.aes-hmac-sha2` is supported. |
|
|
||||||
| passphrase | object | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
|
|
||||||
| iv | string | The 16-byte initialization vector, encoded as base64. |
|
|
||||||
| mac | string | The MAC of the result of encrypting 32 bytes of 0, encoded as base64. |
|
|
||||||
|
|
||||||
For example, the `m.secret_storage.key.key_id` for a key using this
|
|
||||||
algorithm could look like:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "m.default",
|
|
||||||
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
|
||||||
"iv": "random+data",
|
|
||||||
"mac": "mac+of+encrypted+zeros"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
and data encrypted using this algorithm could look like this:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -212,27 +262,13 @@ and data encrypted using this algorithm could look like this:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Key representation
|
##### Key representation
|
||||||
|
|
||||||
When a user is given a raw key for `m.secret_storage.v1.aes-hmac-sha2`,
|
When a user is given a raw key for `m.secret_storage.v1.aes-hmac-sha2`,
|
||||||
it will be presented as a string constructed as follows:
|
the key should be presented as a string using the common [cryptographic key
|
||||||
|
representation](/appendices/#cryptographic-key-representation).
|
||||||
|
|
||||||
1. The key is prepended by the two bytes `0x8b` and `0x01`
|
##### Deriving keys from passphrases
|
||||||
2. All the bytes in the string above, including the two header bytes,
|
|
||||||
are XORed together to form a parity byte. This parity byte is
|
|
||||||
appended to the byte string.
|
|
||||||
3. The byte string is encoded using base58, using the same [mapping as
|
|
||||||
is used for Bitcoin
|
|
||||||
addresses](https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart),
|
|
||||||
that is, using the alphabet
|
|
||||||
`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`.
|
|
||||||
4. The string is formatted into groups of four characters separated by
|
|
||||||
spaces.
|
|
||||||
|
|
||||||
When decoding a raw key, the process should be reversed, with the
|
|
||||||
exception that whitespace is insignificant in the user's input.
|
|
||||||
|
|
||||||
###### Deriving keys from passphrases
|
|
||||||
|
|
||||||
A user may wish to use a chosen passphrase rather than a randomly
|
A user may wish to use a chosen passphrase rather than a randomly
|
||||||
generated key. In this case, information on how to generate the key from
|
generated key. In this case, information on how to generate the key from
|
||||||
|
|
@ -258,7 +294,7 @@ in the `iterations` parameter.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
{
|
{
|
||||||
"passphrase": {
|
"passphrase": {
|
||||||
"algorithm": "m.pbkdf2",
|
"algorithm": "m.pbkdf2",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
weight: 340
|
|
||||||
|
|
||||||
### Spaces
|
### Spaces
|
||||||
|
|
||||||
{{% added-in v="1.2" %}}
|
{{% added-in v="1.2" %}}
|
||||||
|
|
||||||
Often used to group rooms of similar subject matter (such as a public "Official
|
Often used to group rooms of similar subject matter (such as an "Official
|
||||||
matrix.org rooms" space or personal "Work stuff" space), spaces are a way to
|
matrix.org rooms" space or a "Work stuff" space), spaces are a way to
|
||||||
organise rooms while being represented as rooms themselves.
|
organise rooms while being represented as rooms themselves.
|
||||||
|
|
||||||
A space is defined by the [`m.space` room type](#types), making it known as a
|
A space is defined by the [`m.space` room type](#types), making it known as a
|
||||||
|
|
@ -20,11 +18,11 @@ In the default power level structure, this would be `100`. Clients might wish to
|
||||||
go a step further and explicitly ignore notification counts on space-rooms.
|
go a step further and explicitly ignore notification counts on space-rooms.
|
||||||
|
|
||||||
Membership of a space is defined and controlled by the existing mechanisms which
|
Membership of a space is defined and controlled by the existing mechanisms which
|
||||||
govern a room: [`m.room.member`](#mroommember), [`m.room.history_visibility`](#mroomhistory_visibility),
|
govern a room: [`m.room.member`](/client-server-api#mroommember), [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility),
|
||||||
and [`m.room.join_rules`](#mroomjoin_rules). Public spaces are encouraged to have
|
and [`m.room.join_rules`](/client-server-api#mroomjoin_rules). Canonical aliases and invites, including
|
||||||
a similar setup to public rooms: `world_readable` history visibility, published
|
third-party invites, still work just as they do in normal rooms as well. Furthermore,
|
||||||
canonical alias, and suitably public `join_rule`. Invites, including third-party
|
spaces can also be published in the [room directory](/client-server-api#published-room-directory) to make them
|
||||||
invites, still work just as they do in normal rooms as well.
|
discoverable.
|
||||||
|
|
||||||
All other aspects of regular rooms are additionally carried over, such as the
|
All other aspects of regular rooms are additionally carried over, such as the
|
||||||
ability to set arbitrary state events, hold room account data, etc. Spaces are
|
ability to set arbitrary state events, hold room account data, etc. Spaces are
|
||||||
|
|
@ -60,7 +58,7 @@ parent to the room. The `state_key` for the event is the child room's ID.
|
||||||
|
|
||||||
For example, to achieve the following:
|
For example, to achieve the following:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
#space:example.org
|
#space:example.org
|
||||||
#general:example.org (!abcdefg:example.org)
|
#general:example.org (!abcdefg:example.org)
|
||||||
!private:example.org
|
!private:example.org
|
||||||
|
|
@ -89,10 +87,9 @@ the state of `#space:example.org` would consist of:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
No state events in the child rooms themselves would be required (though they
|
No state events in the child rooms themselves would be required (though they can also
|
||||||
can also be present). This allows for users
|
be present). This allows for users to define spaces without needing explicit permission
|
||||||
to define personal/private spaces to organise their own rooms without needing explicit
|
from the room moderators/admins.
|
||||||
permission from the room moderators/admins.
|
|
||||||
|
|
||||||
Child rooms can be removed from a space by omitting the `via` key of `content` on the
|
Child rooms can be removed from a space by omitting the `via` key of `content` on the
|
||||||
relevant state event, such as through redaction or otherwise clearing the `content`.
|
relevant state event, such as through redaction or otherwise clearing the `content`.
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,12 @@ allow users to log into applications via a single web-based
|
||||||
authentication portal. Examples include OpenID Connect, "Central
|
authentication portal. Examples include OpenID Connect, "Central
|
||||||
Authentication Service" (CAS) and SAML.
|
Authentication Service" (CAS) and SAML.
|
||||||
|
|
||||||
This module allows a Matrix homeserver to delegate user authentication
|
This module allows a Matrix homeserver that supports the [legacy authentication
|
||||||
to an external authentication server supporting one of these protocols.
|
API](#legacy-api) to delegate user authentication to an external authentication
|
||||||
In this process, there are three systems involved:
|
server supporting one of these protocols. In this process, there are three
|
||||||
|
systems involved:
|
||||||
|
|
||||||
- A Matrix client, using the APIs defined this specification, which
|
- A Matrix client, using the APIs defined in this specification, which
|
||||||
is seeking to authenticate a user to a Matrix homeserver.
|
is seeking to authenticate a user to a Matrix homeserver.
|
||||||
- A Matrix homeserver, implementing the APIs defined in this
|
- A Matrix homeserver, implementing the APIs defined in this
|
||||||
specification, but which is delegating user authentication to the
|
specification, but which is delegating user authentication to the
|
||||||
|
|
@ -24,7 +25,7 @@ used to communicate with the authentication server. Different Matrix
|
||||||
homeserver implementations might support different SSO protocols.
|
homeserver implementations might support different SSO protocols.
|
||||||
|
|
||||||
Clients and homeservers implementing the SSO flow will need to consider
|
Clients and homeservers implementing the SSO flow will need to consider
|
||||||
both [login](#login) and [user-interactive authentication](#user-interactive-authentication-api). The flow is
|
both [login](#legacy-login) and [user-interactive authentication](#user-interactive-authentication-api). The flow is
|
||||||
similar in both cases, but there are slight differences.
|
similar in both cases, but there are slight differences.
|
||||||
|
|
||||||
Typically, SSO systems require a single "callback" URI to be configured
|
Typically, SSO systems require a single "callback" URI to be configured
|
||||||
|
|
@ -66,7 +67,7 @@ opening an embedded web view.
|
||||||
|
|
||||||
These steps are illustrated as follows:
|
These steps are illustrated as follows:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
Matrix Client Matrix Homeserver Auth Server
|
Matrix Client Matrix Homeserver Auth Server
|
||||||
| | |
|
| | |
|
||||||
|-------------(0) GET /login----------->| |
|
|-------------(0) GET /login----------->| |
|
||||||
|
|
@ -123,8 +124,8 @@ authentication is successful, the browser will be redirected to that
|
||||||
|
|
||||||
For example, consider a web-based client at
|
For example, consider a web-based client at
|
||||||
`https://client.example.com`, which wants to initiate SSO login on
|
`https://client.example.com`, which wants to initiate SSO login on
|
||||||
the homeserver at `server.example.org`. It does this by storing the
|
the homeserver with [server name](/appendices/#server-name) `server.example.org`. It does this by storing the
|
||||||
homeserver name in a query parameter for the `redirectUrl`: it
|
server name in a query parameter for the `redirectUrl`: it
|
||||||
redirects to
|
redirects to
|
||||||
`https://server.example.org/login/sso/redirect?redirectUrl=https://client.example.com?hs=server.example.org`.
|
`https://server.example.org/login/sso/redirect?redirectUrl=https://client.example.com?hs=server.example.org`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ when the sticker image is clicked.
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
Sticker events are received as a single `m.sticker` event in the
|
Sticker events are received as a single `m.sticker` event in the
|
||||||
`timeline` section of a room, in a `/sync`.
|
`timeline` section of a room, in a [`/sync`](#get_matrixclientv3sync).
|
||||||
|
|
||||||
{{% event event="m.sticker" %}}
|
{{% event event="m.sticker" %}}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
|
|
||||||
### Third party invites
|
### Third-party invites
|
||||||
|
|
||||||
This module adds in support for inviting new members to a room where
|
This module adds in support for inviting new members to a room where
|
||||||
their Matrix user ID is not known, instead addressing them by a third
|
their Matrix user ID is not known, instead addressing them by a third-party
|
||||||
party identifier such as an email address. There are two flows here; one
|
identifier such as an email address. There are two flows here; one
|
||||||
if a Matrix user ID is known for the third party identifier, and one if
|
if a Matrix user ID is known for the third-party identifier, and one if
|
||||||
not. Either way, the client calls `/invite` with the details of the
|
not. Either way, the client calls [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite)
|
||||||
third party identifier.
|
with the details of the third-party identifier.
|
||||||
|
|
||||||
The homeserver asks the identity server whether a Matrix user ID is
|
The homeserver asks the identity server whether a Matrix user ID is
|
||||||
known for that identifier:
|
known for that identifier:
|
||||||
|
|
@ -22,7 +22,7 @@ When the invitee's homeserver receives the notification of the binding,
|
||||||
it should insert an `m.room.member` event into the room's graph for that
|
it should insert an `m.room.member` event into the room's graph for that
|
||||||
user, with `content.membership` = `invite`, as well as a
|
user, with `content.membership` = `invite`, as well as a
|
||||||
`content.third_party_invite` property which contains proof that the
|
`content.third_party_invite` property which contains proof that the
|
||||||
invitee does indeed own that third party identifier. See the
|
invitee does indeed own that third-party identifier. See the
|
||||||
[m.room.member](#mroommember) schema for more information.
|
[m.room.member](#mroommember) schema for more information.
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
@ -31,18 +31,20 @@ invitee does indeed own that third party identifier. See the
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
A client asks a server to invite a user by their third party identifier.
|
A client asks a server to invite a user by their third-party identifier.
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="third_party_membership" %}}
|
{{% http-api spec="client-server" api="third_party_membership" anchor_base="thirdparty" %}}
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
Upon receipt of an `/invite`, the server is expected to look up the
|
Upon receipt of an [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite),
|
||||||
third party identifier with the provided identity server. If the lookup
|
the server is expected to look up the third-party identifier with the provided
|
||||||
yields a result for a Matrix User ID then the normal invite process can
|
identity server by making a call to [`/_matrix/identity/v2/lookup`](/identity-service-api/#post_matrixidentityv2lookup).
|
||||||
be initiated. This process ends up looking like this:
|
If the lookup yields a result for a Matrix User ID then the normal [invite
|
||||||
|
process](/server-server-api/#inviting-to-a-room) can be initiated. This process
|
||||||
|
ends up looking like this:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+---------+ +-------------+ +-----------------+
|
+---------+ +-------------+ +-----------------+
|
||||||
| Client | | Homeserver | | IdentityServer |
|
| Client | | Homeserver | | IdentityServer |
|
||||||
+---------+ +-------------+ +-----------------+
|
+---------+ +-------------+ +-----------------+
|
||||||
|
|
@ -66,12 +68,13 @@ be initiated. This process ends up looking like this:
|
||||||
| | |
|
| | |
|
||||||
```
|
```
|
||||||
|
|
||||||
However, if the lookup does not yield a bound User ID, the homeserver
|
However, if the lookup does not yield a bound User ID, the homeserver must store
|
||||||
must store the invite on the identity server and emit a valid
|
the invite on the identity server with a call to
|
||||||
`m.room.third_party_invite` event to the room. This process ends up
|
[`/_matrix/identity/v2/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
|
||||||
looking like this:
|
and emit a valid [`m.room.third_party_invite`](#mroomthird_party_invite) event
|
||||||
|
to the room. This process ends up looking like this:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+---------+ +-------------+ +-----------------+
|
+---------+ +-------------+ +-----------------+
|
||||||
| Client | | Homeserver | | IdentityServer |
|
| Client | | Homeserver | | IdentityServer |
|
||||||
+---------+ +-------------+ +-----------------+
|
+---------+ +-------------+ +-----------------+
|
||||||
|
|
@ -101,15 +104,18 @@ looking like this:
|
||||||
| | |
|
| | |
|
||||||
```
|
```
|
||||||
|
|
||||||
All homeservers MUST verify the signature in the event's
|
The third-party user will then need to verify their identity, which results in a
|
||||||
`content.third_party_invite.signed` object.
|
request to [`/_matrix/federation/v1/3pid/onbind`](/server-server-api/#put_matrixfederationv13pidonbind)
|
||||||
|
from the identity server to the homeserver that bound the third-party identifier
|
||||||
|
to a user. The homeserver then exchanges the `m.room.third_party_invite` event
|
||||||
|
in the room for a complete [`m.room.member`](#mroommember) event with
|
||||||
|
`content.membership: invite` and a `content.third_party_invite` property for the
|
||||||
|
user that has bound the third-party identifier. If the invitee is on a different
|
||||||
|
homeserver than the inviting user, the invitee's homeserver makes a request to
|
||||||
|
[`/_matrix/federation/v1/exchange_third_party_invite/{roomId}`](/server-server-api/#put_matrixfederationv1exchange_third_party_inviteroomid).
|
||||||
|
|
||||||
The third party user will then need to verify their identity, which
|
All homeservers MUST verify the signature in the `m.room.member` event's
|
||||||
results in a call from the identity server to the homeserver that bound
|
`content.third_party_invite.signed` object.
|
||||||
the third party identifier to a user. The homeserver then exchanges the
|
|
||||||
`m.room.third_party_invite` event in the room for a complete
|
|
||||||
`m.room.member` event for `membership: invite` for the user that has
|
|
||||||
bound the third party identifier.
|
|
||||||
|
|
||||||
If a homeserver is joining a room for the first time because of an
|
If a homeserver is joining a room for the first time because of an
|
||||||
`m.room.third_party_invite`, the server which is already participating
|
`m.room.third_party_invite`, the server which is already participating
|
||||||
|
|
@ -123,11 +129,11 @@ view of the room. They may, however, indicate to their clients that a
|
||||||
member's membership is questionable.
|
member's membership is questionable.
|
||||||
|
|
||||||
For example, given H1, H2, and H3 as homeservers, UserA as a user of H1,
|
For example, given H1, H2, and H3 as homeservers, UserA as a user of H1,
|
||||||
and an identity server IS, the full sequence for a third party invite
|
and an identity server IS, the full sequence for a third-party invite
|
||||||
would look like the following. This diagram assumes H1 and H2 are
|
would look like the following. This diagram assumes H1 and H2 are
|
||||||
residents of the room while H3 is attempting to join.
|
residents of the room while H3 is attempting to join.
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+-------+ +-----------------+ +-----+ +-----+ +-----+ +-----+
|
+-------+ +-----------------+ +-----+ +-----+ +-----+ +-----+
|
||||||
| UserA | | ThirdPartyUser | | H1 | | H2 | | H3 | | IS |
|
| UserA | | ThirdPartyUser | | H1 | | H2 | | H3 | | IS |
|
||||||
+-------+ +-----------------+ +-----+ +-----+ +-----+ +-----+
|
+-------+ +-----------------+ +-----+ +-----+ +-----+ +-----+
|
||||||
|
|
@ -144,7 +150,7 @@ residents of the room while H3 is attempting to join.
|
||||||
| | | POST /store-invite | | |
|
| | | POST /store-invite | | |
|
||||||
| | |---------------------------------------------------------------------------------------------->|
|
| | |---------------------------------------------------------------------------------------------->|
|
||||||
| | | | | |
|
| | | | | |
|
||||||
| | | | Token, keys, etc for third party invite |
|
| | | | Token, keys, etc for third-party invite |
|
||||||
| | |<----------------------------------------------------------------------------------------------|
|
| | |<----------------------------------------------------------------------------------------------|
|
||||||
| | | | | |
|
| | | | | |
|
||||||
| | | (Federation) Emit m.room.third_party_invite | | |
|
| | | (Federation) Emit m.room.third_party_invite | | |
|
||||||
|
|
@ -186,15 +192,15 @@ residents of the room while H3 is attempting to join.
|
||||||
|
|
||||||
Note that when H1 sends the `m.room.member` event to H2 and H3 it does
|
Note that when H1 sends the `m.room.member` event to H2 and H3 it does
|
||||||
not have to block on either server's receipt of the event. Likewise, H1
|
not have to block on either server's receipt of the event. Likewise, H1
|
||||||
may complete the `/exchange_third_party_invite/:roomId` request at the
|
may complete the [`/exchange_third_party_invite`](/server-server-api/#put_matrixfederationv1exchange_third_party_inviteroomid) request at the
|
||||||
same time as sending the `m.room.member` event to H2 and H3.
|
same time as sending the `m.room.member` event to H2 and H3.
|
||||||
Additionally, H3 may complete the `/3pid/onbind` request it got from IS
|
Additionally, H3 may complete the [`/3pid/onbind`](/server-server-api/#put_matrixfederationv13pidonbind) request it got from IS
|
||||||
at any time - the completion is not shown in the diagram.
|
at any time - the completion is not shown in the diagram.
|
||||||
|
|
||||||
H1 MUST verify the request from H3 to ensure the `signed` property is
|
H1 MUST verify the request from H3 to ensure the `signed` property is
|
||||||
correct as well as the `key_validity_url` as still being valid. This is
|
correct as well as the `key_validity_url` as still being valid. This is
|
||||||
done by making a request to the [identity server
|
done by making a request to the identity server's
|
||||||
/isvalid](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
|
[`/pubkey/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
|
||||||
endpoint, using the provided URL rather than constructing a new one. The
|
endpoint, using the provided URL rather than constructing a new one. The
|
||||||
query string and response for the provided URL must match the Identity
|
query string and response for the provided URL must match the Identity
|
||||||
Service Specification.
|
Service Specification.
|
||||||
|
|
@ -214,13 +220,13 @@ still be performed, so the attack surface here is minimized.
|
||||||
There are a number of privacy and trust implications to this module.
|
There are a number of privacy and trust implications to this module.
|
||||||
|
|
||||||
It is important for user privacy that leaking the mapping between a
|
It is important for user privacy that leaking the mapping between a
|
||||||
matrix user ID and a third party identifier is hard. In particular,
|
matrix user ID and a third-party identifier is hard. In particular,
|
||||||
being able to look up all third party identifiers from a matrix user ID
|
being able to look up all third-party identifiers from a matrix user ID
|
||||||
(and accordingly, being able to link each third party identifier) should
|
(and accordingly, being able to link each third-party identifier) should
|
||||||
be avoided wherever possible. To this end, the third party identifier is
|
be avoided wherever possible. To this end, the third-party identifier is
|
||||||
not put in any event, rather an opaque display name provided by the
|
not put in any event, rather an opaque display name provided by the
|
||||||
identity server is put into the events. Clients should not remember or
|
identity server is put into the events. Clients should not remember or
|
||||||
display third party identifiers from invites, other than for the use of
|
display third-party identifiers from invites, other than for the use of
|
||||||
the inviter themself.
|
the inviter themself.
|
||||||
|
|
||||||
Homeservers are not required to trust any particular identity server(s).
|
Homeservers are not required to trust any particular identity server(s).
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
### Third Party Networks
|
### Third-party Networks
|
||||||
|
|
||||||
Application services can provide access to third party networks via
|
Application services can provide access to third-party networks via
|
||||||
bridging. This allows Matrix users to communicate with users on other
|
bridging. This allows Matrix users to communicate with users on other
|
||||||
communication platforms, with messages ferried back and forth by the
|
communication platforms, with messages ferried back and forth by the
|
||||||
application service. A single application service may bridge multiple
|
application service. A single application service may bridge multiple
|
||||||
third party networks, and many individual locations within those
|
third-party networks, and many individual locations within those
|
||||||
networks. A single third party network location may be bridged to
|
networks. A single third-party network location may be bridged to
|
||||||
multiple Matrix rooms.
|
multiple Matrix rooms.
|
||||||
|
|
||||||
#### Third Party Lookups
|
#### Third-party Lookups
|
||||||
|
|
||||||
A client may wish to provide a rich interface for joining third party
|
A client may wish to provide a rich interface for joining third-party
|
||||||
locations and connecting with third party users. Information necessary
|
locations and connecting with third-party users. Information necessary
|
||||||
for such an interface is provided by third party lookups.
|
for such an interface is provided by third-party lookups.
|
||||||
|
|
||||||
{{% http-api spec="client-server" api="third_party_lookup" %}}
|
{{% http-api spec="client-server" api="third_party_lookup" %}}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,16 @@ Clients SHOULD render threads differently to regular messages or replies in the
|
||||||
as by providing some context to what is going on in the thread but keeping the full conversation
|
as by providing some context to what is going on in the thread but keeping the full conversation
|
||||||
history behind a disclosure.
|
history behind a disclosure.
|
||||||
|
|
||||||
Threads are established using a `rel_type` of `m.thread` and reference the *thread root* (the
|
Threads are established using a `rel_type` of `m.thread` and reference the
|
||||||
first event in a thread). It is not possible to create a thread from an event with a `rel_type`,
|
*thread root* (the main timeline event to which the thread events refer). It is not possible to create a thread from an event which itself
|
||||||
which includes not being able to nest threads. All conversation in a thread reference the thread
|
is the child of an event relationship (i.e., one with an `m.relates_to`
|
||||||
root instead of the most recent message, unlike rich reply chains.
|
property with a `rel_type` property - see [Relationship types](#relationship-types)).
|
||||||
|
It is therefore also not possible to nest threads.
|
||||||
|
|
||||||
As a worked example, the following represents a thread and how it'd be formed:
|
Unlike rich reply chains, all events in a thread reference the thread root
|
||||||
|
instead of the most recent message.
|
||||||
|
|
||||||
|
As a worked example, the following represents a thread and how it would be formed:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -74,7 +78,7 @@ Clients which understand how to work with threads should simply do so, however c
|
||||||
might not be aware of threads (due to age or scope) might not be able to helpfully represent
|
might not be aware of threads (due to age or scope) might not be able to helpfully represent
|
||||||
the conversation history to its users.
|
the conversation history to its users.
|
||||||
|
|
||||||
To work around this, events sent by clients which understand threads include [rich reply](#rich-replies)
|
To work around this, events sent by clients which understand threads SHOULD include [rich reply](#rich-replies)
|
||||||
metadata to attempt to form a reply chain representation of the conversation. This representation
|
metadata to attempt to form a reply chain representation of the conversation. This representation
|
||||||
is not ideal for heavily threaded rooms, but allows for users to have context as to what is
|
is not ideal for heavily threaded rooms, but allows for users to have context as to what is
|
||||||
being discussed with respect to other messages in the room.
|
being discussed with respect to other messages in the room.
|
||||||
|
|
@ -102,10 +106,6 @@ flag to `true`.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For `m.room.message` events represented this way, no [reply fallback](#fallbacks-for-rich-replies)
|
|
||||||
is specified. This allows thread-aware clients to discard the `m.in_reply_to` object entirely
|
|
||||||
when `is_falling_back` is `true`.
|
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
Clients which are acutely aware of threads (they do not render threads, but are otherwise
|
Clients which are acutely aware of threads (they do not render threads, but are otherwise
|
||||||
aware of the feature existing in the spec) can treat rich replies to an event with a `rel_type`
|
aware of the feature existing in the spec) can treat rich replies to an event with a `rel_type`
|
||||||
|
|
@ -128,11 +128,11 @@ clients is used to create a reply within a thread: clients should render the eve
|
||||||
|
|
||||||
##### Validation of `m.thread` relationships
|
##### Validation of `m.thread` relationships
|
||||||
|
|
||||||
Servers SHOULD reject client requests which attempt to start a thread off an event with a
|
Servers SHOULD reject client requests which attempt to start a thread off an
|
||||||
`rel_type`. If the client attempts to target an event which already has an `m.thread`,
|
event with an `m.relates_to` property. If the client attempts to target an event which itself
|
||||||
`m.reference`, or any other `rel_type` then it should receive a HTTP 400 error response
|
has an `m.relates_to` property, then it should receive a HTTP 400 error
|
||||||
with appropriate error message, as per the [standard error response](#standard-error-response)
|
response with appropriate error message, as per the [standard error
|
||||||
structure.
|
response](#standard-error-response) structure.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
A specific error code is not currently available for this case: servers should use `M_UNKNOWN`
|
A specific error code is not currently available for this case: servers should use `M_UNKNOWN`
|
||||||
|
|
@ -141,12 +141,16 @@ alongside the HTTP 400 status code.
|
||||||
|
|
||||||
##### Server-side aggregation of `m.thread` relationships
|
##### Server-side aggregation of `m.thread` relationships
|
||||||
|
|
||||||
Given threads always reference the thread root, an event can have multiple "child" events which
|
Given threads always reference the thread root, an event can have multiple
|
||||||
then form the thread itself. These events should be [aggregated](#aggregations) by the server.
|
"child" events which then form the thread itself. These events should be
|
||||||
|
[aggregated](#aggregations-of-child-events) by the server.
|
||||||
|
|
||||||
The aggregation for threads includes some information about the user's participation in the thread,
|
The aggregation for threads includes some information about the user's participation in the thread,
|
||||||
the approximate number of events in the thread (as known to the server), and the most recent event
|
the approximate number of events in the thread (as known to the server), and the most recent event
|
||||||
in the thread (topologically). This is then bundled into the event as `m.thread`:
|
in the thread (topologically).
|
||||||
|
|
||||||
|
As with any other aggregation of child events, the `m.thread` aggregation is
|
||||||
|
included under the `m.relations` property in `unsigned` for the thread root. For example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -165,6 +169,11 @@ in the thread (topologically). This is then bundled into the event as `m.thread`
|
||||||
"content": {
|
"content": {
|
||||||
"msgtype": "m.text",
|
"msgtype": "m.text",
|
||||||
"body": "Woo! Threads!"
|
"body": "Woo! Threads!"
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"m.relations": {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"count": 7,
|
"count": 7,
|
||||||
|
|
@ -176,17 +185,19 @@ in the thread (topologically). This is then bundled into the event as `m.thread`
|
||||||
```
|
```
|
||||||
|
|
||||||
`latest_event` is the most recent event (topologically to the server) in the thread sent by an
|
`latest_event` is the most recent event (topologically to the server) in the thread sent by an
|
||||||
un-[ignored user](#ignoring-users).
|
un-[ignored user](#ignoring-users). It should be serialized in the same form as the event itself.
|
||||||
|
|
||||||
Note that any bundled aggregations on `latest_event` should also be present. The server should be
|
Note that, as in the example above, child events of the `latest_event` should
|
||||||
careful to avoid loops, though loops are not currently possible due to `m.thread` not being possible
|
themselves be aggregated and included under `m.relations` for that event. The
|
||||||
to target an event with a `rel_type` already.
|
server should be careful to avoid loops, though loops are not currently
|
||||||
|
possible due to `m.thread` not being permitted to target an event with an
|
||||||
|
`m.relates_to` property.
|
||||||
|
|
||||||
`count` is simply the number of events using `m.thread` as a `rel_type` pointing to the target event.
|
`count` is simply the number of events using `m.thread` as a `rel_type` pointing to the target event.
|
||||||
It does not include events sent by [ignored users](#ignoring-users).
|
It does not include events sent by [ignored users](#ignoring-users).
|
||||||
|
|
||||||
`current_user_participated` is `true` when the authenticated user is either:
|
`current_user_participated` is `true` when the authenticated user is either:
|
||||||
1. The `sender` of the event receiving the bundle (they sent the thread root).
|
1. The `sender` of the thread root event.
|
||||||
2. The `sender` of an event which references the thread root with a `rel_type` of `m.thread`.
|
2. The `sender` of an event which references the thread root with a `rel_type` of `m.thread`.
|
||||||
|
|
||||||
#### Querying threads in a room
|
#### Querying threads in a room
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,130 @@ This module outlines how two users in a room can set up a Voice over IP
|
||||||
WebRTC 1.0 standard. Call signalling is achieved by sending [message
|
WebRTC 1.0 standard. Call signalling is achieved by sending [message
|
||||||
events](#events) to the room. In this version of the spec, only two-party
|
events](#events) to the room. In this version of the spec, only two-party
|
||||||
communication is supported (e.g. between two peers, or between a peer
|
communication is supported (e.g. between two peers, or between a peer
|
||||||
and a multi-point conferencing unit). This means that clients MUST only
|
and a multi-point conferencing unit). Calls can take place in rooms with
|
||||||
send call events to rooms with exactly two participants.
|
multiple members, but only two devices can take part in the call.
|
||||||
|
|
||||||
|
All VoIP events have a `version` field. This is used to determine whether
|
||||||
|
devices support this new version of the protocol. For example, clients can use
|
||||||
|
this field to know whether to expect an `m.call.select_answer` event from their
|
||||||
|
opponent. If clients see events with `version` other than `0` or `"1"`
|
||||||
|
(including, for example, the numeric value `1`), they should treat these the
|
||||||
|
same as if they had `version` == `"1"`.
|
||||||
|
|
||||||
|
Note that this implies any and all future versions of VoIP events should be
|
||||||
|
backwards-compatible. If it does become necessary to introduce a non
|
||||||
|
backwards-compatible VoIP spec, the intention would be for it to simply use a
|
||||||
|
separate set of event types.
|
||||||
|
|
||||||
|
#### Party Identifiers
|
||||||
|
Whenever a client first participates in a new call, it generates a `party_id` for itself to use for the
|
||||||
|
duration of the call. This needs to be long enough that the chance of a collision between multiple devices
|
||||||
|
both generating an answer at the same time generating the same party ID is vanishingly small: 8 uppercase +
|
||||||
|
lowercase alphanumeric characters is recommended. Parties in the call are identified by the tuple of
|
||||||
|
`(user_id, party_id)`.
|
||||||
|
|
||||||
|
The client adds a `party_id` field containing this ID to the top-level of the content of all VoIP events
|
||||||
|
it sends on the call, including `m.call.invite`. Clients use this to identify remote echo of their own
|
||||||
|
events: since a user may call themselves, they cannot simply ignore events from their own user. This
|
||||||
|
field also identifies different answers sent by different clients to an invite, and matches `m.call.candidates`
|
||||||
|
events to their respective answer/invite.
|
||||||
|
|
||||||
|
A client implementation may choose to use the device ID used in end-to-end cryptography for this purpose,
|
||||||
|
or it may choose, for example, to use a different one for each call to avoid leaking information on which
|
||||||
|
devices were used in a call (in an unencrypted room) or if a single device (ie. access token) were used to
|
||||||
|
send signalling for more than one call party.
|
||||||
|
|
||||||
|
A grammar for `party_id` is defined [below](#grammar-for-voip-ids).
|
||||||
|
|
||||||
|
#### Politeness
|
||||||
|
In line with [WebRTC perfect negotiation](https://w3c.github.io/webrtc-pc/#perfect-negotiation-example)
|
||||||
|
there are rules to establish which party is polite in the process of renegotiation. The callee is
|
||||||
|
always the polite party. In a glare situation, the politeness of a party is therefore determined by
|
||||||
|
whether the inbound or outbound call is used: if a client discards its outbound call in favour of
|
||||||
|
an inbound call, it becomes the polite party.
|
||||||
|
|
||||||
|
#### Call Event Liveness
|
||||||
|
`m.call.invite` contains a `lifetime` field that indicates how long the offer is valid for. When
|
||||||
|
a client receives an invite, it should use the event's `age` field in the sync response plus the
|
||||||
|
time since it received the event from the homeserver to determine whether the invite is still valid.
|
||||||
|
The use of the `age` field ensures that incorrect clocks on client devices don't break calls.
|
||||||
|
|
||||||
|
If the invite is still valid *and will remain valid for long enough for the user to accept the call*,
|
||||||
|
it should signal an incoming call. The amount of time allowed for the user to accept the call may
|
||||||
|
vary between clients. For example, it may be longer on a locked mobile device than on an unlocked
|
||||||
|
desktop device.
|
||||||
|
|
||||||
|
The client should only signal an incoming call in a given room once it has completed processing the
|
||||||
|
entire sync response and, for encrypted rooms, attempted to decrypt all encrypted events in the
|
||||||
|
sync response for that room. This ensures that if the sync response contains subsequent events that
|
||||||
|
indicate the call has been hung up, rejected, or answered elsewhere, the client does not signal it.
|
||||||
|
|
||||||
|
If on startup, after processing locally stored events, the client determines that there is an invite
|
||||||
|
that is still valid, it should still signal it but only after it has completed a sync from the homeserver.
|
||||||
|
|
||||||
|
The minimal recommended lifetime is 90 seconds - this should give the user enough time to actually pick
|
||||||
|
up the call.
|
||||||
|
|
||||||
|
#### ICE Candidate Batching
|
||||||
|
Clients should aim to send a small number of candidate events, with guidelines:
|
||||||
|
* ICE candidates which can be discovered immediately or almost immediately in the invite/answer
|
||||||
|
event itself (eg. host candidates). If server reflexive or relay candidates can be gathered in
|
||||||
|
a sufficiently short period of time, these should be sent here too. A delay of around 200ms is
|
||||||
|
suggested as a starting point.
|
||||||
|
* The client should then allow some time for further candidates to be gathered in order to batch them,
|
||||||
|
rather than sending each candidate as it arrives. A starting point of 2 seconds after sending the
|
||||||
|
invite or 500ms after sending the answer is suggested as a starting point (since a delay is natural
|
||||||
|
anyway after the invite whilst the client waits for the user to accept it).
|
||||||
|
|
||||||
|
#### End-of-candidates
|
||||||
|
An ICE candidate whose value is the empty string means that no more ICE candidates will
|
||||||
|
be sent. Clients must send such a candidate in an `m.call.candidates` message.
|
||||||
|
The WebRTC spec requires browsers to generate such a candidate, however note that at time of writing,
|
||||||
|
not all browsers do (Chrome does not, but does generate an `icegatheringstatechange` event). The
|
||||||
|
client should send any remaining candidates once candidate generation finishes, ignoring timeouts above.
|
||||||
|
This allows bridges to batch the candidates together when bridging to protocols that don't support
|
||||||
|
trickle ICE.
|
||||||
|
|
||||||
|
#### DTMF
|
||||||
|
Matrix clients can send DTMF as specified by WebRTC. The WebRTC standard as of August
|
||||||
|
2020 does not support receiving DTMF but a Matrix client can receive and interpret the DTMF sent
|
||||||
|
in the RTP payload.
|
||||||
|
|
||||||
|
#### Grammar for VoIP IDs
|
||||||
|
|
||||||
|
`call_id`s and `party_id` must follow the [Opaque Identifier Grammar](/appendices#opaque-identifiers).
|
||||||
|
|
||||||
|
#### Behaviour on Room Leave
|
||||||
|
If the client sees the user it is in a call with leave the room, the client should treat this
|
||||||
|
as a hangup event for any calls that are in progress. No specific requirement is given for the
|
||||||
|
situation where a client has sent an invite and the invitee leaves the room, but the client may
|
||||||
|
wish to treat it as a rejection if there are no more users in the room who could answer the call
|
||||||
|
(eg. the user is now alone or the `invitee` field was set on the invite).
|
||||||
|
|
||||||
|
The same behaviour applies when a client is looking at historic calls.
|
||||||
|
|
||||||
|
#### Supported Codecs
|
||||||
|
The Matrix spec does not mandate particular audio or video codecs, but instead defers to the
|
||||||
|
WebRTC spec. A compliant Matrix VoIP client will behave in the same way as a supported 'browser'
|
||||||
|
in terms of what codecs it supports and what variants thereof. The latest WebRTC specification
|
||||||
|
applies, so clients should keep up to date with new versions of the WebRTC specification whether
|
||||||
|
or not there have been any changes to the Matrix spec.
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
|
##### Common Fields
|
||||||
|
|
||||||
|
{{% event-fields event_type="call_event" %}}
|
||||||
|
|
||||||
|
##### Events
|
||||||
|
|
||||||
{{% event-group group_name="m.call" %}}
|
{{% event-group group_name="m.call" %}}
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
A call is set up with message events exchanged as follows:
|
A call is set up with message events exchanged as follows:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
Caller Callee
|
Caller Callee
|
||||||
[Place Call]
|
[Place Call]
|
||||||
m.call.invite ----------->
|
m.call.invite ----------->
|
||||||
|
|
@ -25,13 +137,14 @@ A call is set up with message events exchanged as follows:
|
||||||
[..candidates..] -------->
|
[..candidates..] -------->
|
||||||
[Answers call]
|
[Answers call]
|
||||||
<--------------- m.call.answer
|
<--------------- m.call.answer
|
||||||
|
m.call.select_answer ----------->
|
||||||
[Call is active and ongoing]
|
[Call is active and ongoing]
|
||||||
<--------------- m.call.hangup
|
<--------------- m.call.hangup
|
||||||
```
|
```
|
||||||
|
|
||||||
Or a rejected call:
|
Or a rejected call:
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
Caller Callee
|
Caller Callee
|
||||||
m.call.invite ------------>
|
m.call.invite ------------>
|
||||||
m.call.candidate --------->
|
m.call.candidate --------->
|
||||||
|
|
@ -42,6 +155,62 @@ Or a rejected call:
|
||||||
|
|
||||||
Calls are negotiated according to the WebRTC specification.
|
Calls are negotiated according to the WebRTC specification.
|
||||||
|
|
||||||
|
In response to an incoming invite, a client may do one of several things:
|
||||||
|
* Attempt to accept the call by sending an `m.call.answer`.
|
||||||
|
* Actively reject the call everywhere: send an `m.call.reject` as per above, which will stop the call from
|
||||||
|
ringing on all the user's devices and the caller's client will inform them that the user has
|
||||||
|
rejected their call.
|
||||||
|
* Ignore the call: send no events, but stop alerting the user about the call. The user's other
|
||||||
|
devices will continue to ring, and the caller's device will continue to indicate that the call
|
||||||
|
is ringing, and will time the call out in the normal way if no other device responds.
|
||||||
|
|
||||||
|
##### Streams
|
||||||
|
|
||||||
|
Clients may send more than one stream in a VoIP call. The streams should be
|
||||||
|
differentiated by including metadata in the [`m.call.invite`](/client-server-api/#mcallinvite),
|
||||||
|
[`m.call.answer`](/client-server-api/#mcallanswer) and [`m.call.negotiate`](/client-server-api/#mcallnegotiate)
|
||||||
|
events, using the `sdp_stream_metadata` property. An [`m.call.sdp_stream_metadata_changed`](/client-server-api/#mcallsdp_stream_metadata_changed)
|
||||||
|
event can be sent when the metadata changes but no negotiation is required.
|
||||||
|
|
||||||
|
Clients are recommended to not mute the audio of WebRTC tracks locally when an
|
||||||
|
incoming stream has the `audio_muted` field set to `true`. This is because when
|
||||||
|
the other user unmutes themselves, there may be a slight delay between their
|
||||||
|
client sending audio and the [`m.call.sdp_stream_metadata_changed`](/client-server-api/#mcallsdp_stream_metadata_changed)
|
||||||
|
event arriving and any audio sent in between will not be heard. The other user
|
||||||
|
will still stop transmitting audio once they mute on their side, so no audio is
|
||||||
|
sent without the user's knowledge.
|
||||||
|
|
||||||
|
The same suggestion does not apply to `video_muted`. Clients _should_ mute video
|
||||||
|
locally, so that the receiving side doesn't see a black video.
|
||||||
|
|
||||||
|
If `sdp_stream_metadata` is present and an incoming stream is not listed in it,
|
||||||
|
the stream should be ignored. If a stream has a `purpose` of an unknown type, it
|
||||||
|
should also be ignored.
|
||||||
|
|
||||||
|
For backwards compatibility, if `sdp_stream_metadata` is not present in the
|
||||||
|
initial [`m.call.invite`](/client-server-api/#mcallinvite) or [`m.call.answer`](/client-server-api/#mcallanswer)
|
||||||
|
event sent by the other party, the client should assume that this property is
|
||||||
|
not supported by the other party. It means that multiple streams cannot be
|
||||||
|
differentiated: the client should only use the first incoming stream and
|
||||||
|
shouldn't send more than one stream.
|
||||||
|
|
||||||
|
Clients implementing this specification should ignore any streamless tracks.
|
||||||
|
|
||||||
|
##### Invitees
|
||||||
|
The `invitee` field should be added whenever the call is intended for one
|
||||||
|
specific user, and should be set to the Matrix user ID of that user. Invites
|
||||||
|
without an `invitee` field are defined to be intended for any member of the
|
||||||
|
room other than the sender of the event.
|
||||||
|
|
||||||
|
Clients should consider an incoming call if they see a non-expired invite event
|
||||||
|
where the `invitee` field is either absent or equal to their user's Matrix ID.
|
||||||
|
They should, however, evaluate whether or not to ring based on their user's trust
|
||||||
|
relationship with the callers and/or where the call was placed. As a starting
|
||||||
|
point, it is RECOMMENDED that clients ignore call invites in rooms with a
|
||||||
|
[join rule](#mroomjoin_rules) of `public`. When clients suppress ringing for an
|
||||||
|
incoming call invite, they SHOULD still display the call invite in the room and
|
||||||
|
annotate that it was ignored.
|
||||||
|
|
||||||
##### Glare
|
##### Glare
|
||||||
|
|
||||||
"Glare" is a problem which occurs when two users call each other at
|
"Glare" is a problem which occurs when two users call each other at
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,15 @@
|
||||||
title: "Identity Service API"
|
title: "Identity Service API"
|
||||||
weight: 40
|
weight: 40
|
||||||
type: docs
|
type: docs
|
||||||
|
description: |
|
||||||
|
The Matrix client-server and server-server APIs are largely expressed in
|
||||||
|
Matrix user identifiers. Sometimes it is useful to refer to users by other
|
||||||
|
(“third-party”) identifiers such as email addresses or phone numbers. The
|
||||||
|
Identity Service API describes how mappings between 3PIDs and Matrix user
|
||||||
|
IDs can be established, validated, and used; in practice this has been
|
||||||
|
applied to email addresses and phone numbers.
|
||||||
---
|
---
|
||||||
|
|
||||||
The Matrix client-server and server-server APIs are largely expressed in
|
|
||||||
Matrix user identifiers. From time to time, it is useful to refer to
|
|
||||||
users by other ("third-party") identifiers, or "3PID"s, e.g. their email
|
|
||||||
address or phone number. This Identity Service Specification describes
|
|
||||||
how mappings between third-party identifiers and Matrix user identifiers
|
|
||||||
can be established, validated, and used. This description technically
|
|
||||||
may apply to any 3PID, but in practice has only been applied
|
|
||||||
specifically to email addresses and phone numbers.
|
|
||||||
|
|
||||||
## General principles
|
## General principles
|
||||||
|
|
||||||
The purpose of an identity server is to validate, store, and answer
|
The purpose of an identity server is to validate, store, and answer
|
||||||
|
|
@ -98,20 +96,25 @@ There was an error sending an email. Typically seen when attempting to
|
||||||
verify ownership of a given email address.
|
verify ownership of a given email address.
|
||||||
|
|
||||||
`M_INVALID_ADDRESS`
|
`M_INVALID_ADDRESS`
|
||||||
The provided third party address was not valid.
|
The provided third-party address was not valid.
|
||||||
|
|
||||||
`M_SEND_ERROR`
|
`M_SEND_ERROR`
|
||||||
There was an error sending a notification. Typically seen when
|
There was an error sending a notification. Typically seen when
|
||||||
attempting to verify ownership of a given third party address.
|
attempting to verify ownership of a given third-party address.
|
||||||
|
|
||||||
`M_UNRECOGNIZED`
|
`M_UNRECOGNIZED`
|
||||||
The request contained an unrecognised value, such as an unknown token or
|
The request contained an unrecognised value, such as an unknown token or
|
||||||
medium.
|
medium.
|
||||||
|
|
||||||
|
This is also used as the response if a server did not understand the request.
|
||||||
|
This is expected to be returned with a 404 HTTP status code if the endpoint is
|
||||||
|
not implemented or a 405 HTTP status code if the endpoint is implemented, but
|
||||||
|
the incorrect HTTP method is used.
|
||||||
|
|
||||||
`M_THREEPID_IN_USE`
|
`M_THREEPID_IN_USE`
|
||||||
The third party identifier is already in use by another user. Typically
|
The third-party identifier is already in use by another user. Typically
|
||||||
this error will have an additional `mxid` property to indicate who owns
|
this error will have an additional `mxid` property to indicate who owns
|
||||||
the third party identifier.
|
the third-party identifier.
|
||||||
|
|
||||||
`M_UNKNOWN`
|
`M_UNKNOWN`
|
||||||
An unknown error has occurred.
|
An unknown error has occurred.
|
||||||
|
|
@ -157,15 +160,20 @@ of access tokens to authenticate users. The access tokens provided by an
|
||||||
Identity Server cannot be used to authenticate Client-Server API
|
Identity Server cannot be used to authenticate Client-Server API
|
||||||
requests.
|
requests.
|
||||||
|
|
||||||
An access token is provided to an endpoint in one of two ways:
|
Access tokens may be provided via a request header, using the
|
||||||
|
Authentication Bearer scheme: `Authorization: Bearer TheTokenHere`.
|
||||||
|
|
||||||
1. Via a query string parameter, `access_token=TheTokenHere`.
|
Clients may alternatively provide the access token via a query string
|
||||||
2. Via a request header, `Authorization: Bearer TheTokenHere`.
|
parameter: `access_token=TheTokenHere`. This method is deprecated to
|
||||||
|
prevent the access token being leaked in access/HTTP logs and SHOULD NOT
|
||||||
|
be used by clients.
|
||||||
|
|
||||||
Clients are encouraged to the use the `Authorization` header where
|
Identity Servers MUST support both methods.
|
||||||
possible to prevent the access token being leaked in access/HTTP logs.
|
|
||||||
The query string should only be used in cases where the `Authorization`
|
{{% boxes/note %}}
|
||||||
header is inaccessible for the client.
|
{{% changed-in v="1.11" %}}
|
||||||
|
Sending the access token as a query string parameter is now deprecated.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
When credentials are required but missing or invalid, the HTTP call will
|
When credentials are required but missing or invalid, the HTTP call will
|
||||||
return with a status of 401 and the error code `M_UNAUTHORIZED`.
|
return with a status of 401 and the error code `M_UNAUTHORIZED`.
|
||||||
|
|
@ -364,7 +372,7 @@ To start a session, the client makes a request to the appropriate
|
||||||
token to the user, and the user provides the token to the client. The
|
token to the user, and the user provides the token to the client. The
|
||||||
client then provides the token to the appropriate `/submitToken`
|
client then provides the token to the appropriate `/submitToken`
|
||||||
endpoint, completing the session. At this point, the client should
|
endpoint, completing the session. At this point, the client should
|
||||||
`/bind` the third party identifier or leave it for another entity to
|
`/bind` the third-party identifier or leave it for another entity to
|
||||||
bind.
|
bind.
|
||||||
|
|
||||||
### Format of a validation token
|
### Format of a validation token
|
||||||
|
|
|
||||||
10
content/olm-megolm/_index.md
Normal file
10
content/olm-megolm/_index.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
title: "Olm & Megolm"
|
||||||
|
weight: 61
|
||||||
|
type: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
Matrix uses the Olm and Megolm cryptographic ratchets for [end-to-end encryption](../client-server-api/#end-to-end-encryption).
|
||||||
|
|
||||||
|
- [Olm: A Cryptographic Ratchet](/olm-megolm/olm/)
|
||||||
|
- [Megolm group ratchet](/olm-megolm/megolm/)
|
||||||
378
content/olm-megolm/megolm.md
Normal file
378
content/olm-megolm/megolm.md
Normal file
|
|
@ -0,0 +1,378 @@
|
||||||
|
---
|
||||||
|
title: "Megolm group ratchet"
|
||||||
|
weight: 20
|
||||||
|
type: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
An AES-based cryptographic ratchet intended for group communications.
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
The Megolm ratchet is intended for encrypted messaging applications where there
|
||||||
|
may be a large number of recipients of each message, thus precluding the use of
|
||||||
|
peer-to-peer encryption systems such as [Olm][].
|
||||||
|
|
||||||
|
It also allows a recipient to decrypt received messages multiple times. For
|
||||||
|
instance, in client/server applications, a copy of the ciphertext can be stored
|
||||||
|
on the (untrusted) server, while the client need only store the session keys.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Each participant in a conversation uses their own outbound session for
|
||||||
|
encrypting messages. A session consists of a ratchet and an [Ed25519][] keypair.
|
||||||
|
|
||||||
|
Secrecy is provided by the ratchet, which can be wound forwards but not
|
||||||
|
backwards, and is used to derive a distinct message key for each message.
|
||||||
|
|
||||||
|
Authenticity is provided via Ed25519 signatures.
|
||||||
|
|
||||||
|
The value of the ratchet, and the public part of the Ed25519 key, are shared
|
||||||
|
with other participants in the conversation via secure peer-to-peer
|
||||||
|
channels. Provided that peer-to-peer channel provides authenticity of the
|
||||||
|
messages to the participants and deniability of the messages to third parties,
|
||||||
|
the Megolm session will inherit those properties.
|
||||||
|
|
||||||
|
## The Megolm ratchet algorithm
|
||||||
|
|
||||||
|
The Megolm ratchet \(R_i\) consists of four parts, \(R_{i,j}\) for
|
||||||
|
\(j \in {0,1,2,3}\). The length of each part depends on the hash function
|
||||||
|
in use (256 bits for this version of Megolm).
|
||||||
|
|
||||||
|
The ratchet is initialised with cryptographically-secure random data, and
|
||||||
|
advanced as follows:
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
R_{i,0} &=
|
||||||
|
\begin{cases}
|
||||||
|
H_0\left(R_{2^{24}(n-1),0}\right) &\text{if }\exists n | i = 2^{24}n\\
|
||||||
|
R_{i-1,0} &\text{otherwise}
|
||||||
|
\end{cases}\\
|
||||||
|
R_{i,1} &=
|
||||||
|
\begin{cases}
|
||||||
|
H_1\left(R_{2^{24}(n-1),0}\right) &\text{if }\exists n | i = 2^{24}n\\
|
||||||
|
H_1\left(R_{2^{16}(m-1),1}\right) &\text{if }\exists m | i = 2^{16}m\\
|
||||||
|
R_{i-1,1} &\text{otherwise}
|
||||||
|
\end{cases}\\
|
||||||
|
R_{i,2} &=
|
||||||
|
\begin{cases}
|
||||||
|
H_2\left(R_{2^{24}(n-1),0}\right) &\text{if }\exists n | i = 2^{24}n\\
|
||||||
|
H_2\left(R_{2^{16}(m-1),1}\right) &\text{if }\exists m | i = 2^{16}m\\
|
||||||
|
H_2\left(R_{2^8(p-1),2}\right) &\text{if }\exists p | i = 2^8p\\
|
||||||
|
R_{i-1,2} &\text{otherwise}
|
||||||
|
\end{cases}\\
|
||||||
|
R_{i,3} &=
|
||||||
|
\begin{cases}
|
||||||
|
H_3\left(R_{2^{24}(n-1),0}\right) &\text{if }\exists n | i = 2^{24}n\\
|
||||||
|
H_3\left(R_{2^{16}(m-1),1}\right) &\text{if }\exists m | i = 2^{16}m\\
|
||||||
|
H_3\left(R_{2^8(p-1),2}\right) &\text{if }\exists p | i = 2^8p\\
|
||||||
|
H_3\left(R_{i-1,3}\right) &\text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
where \(H_0\), \(H_1\), \(H_2\), and \(H_3\) are different hash
|
||||||
|
functions. In summary: every \(2^8\) iterations, \(R_{i,3}\) is
|
||||||
|
reseeded from \(R_{i,2}\). Every \(2^{16}\) iterations, \(R_{i,2}\)
|
||||||
|
and \(R_{i,3}\) are reseeded from \(R_{i,1}\). Every \(2^{24}\)
|
||||||
|
iterations, \(R_{i,1}\), \(R_{i,2}\) and \(R_{i,3}\) are reseeded
|
||||||
|
from \(R_{i,0}\).
|
||||||
|
|
||||||
|
The complete ratchet value, \(R_{i}\), is hashed to generate the keys used
|
||||||
|
to encrypt each message. This scheme allows the ratchet to be advanced an
|
||||||
|
arbitrary amount forwards while needing at most 1020 hash computations. A
|
||||||
|
client can decrypt chat history onwards from the earliest value of the ratchet
|
||||||
|
it is aware of, but cannot decrypt history from before that point without
|
||||||
|
reversing the hash function.
|
||||||
|
|
||||||
|
This allows a participant to share its ability to decrypt chat history with
|
||||||
|
another from a point in the conversation onwards by giving a copy of the
|
||||||
|
ratchet at that point in the conversation.
|
||||||
|
|
||||||
|
|
||||||
|
## The Megolm protocol
|
||||||
|
|
||||||
|
### Session setup
|
||||||
|
|
||||||
|
Each participant in a conversation generates their own Megolm session. A
|
||||||
|
session consists of three parts:
|
||||||
|
|
||||||
|
* a 32 bit counter, \(i\).
|
||||||
|
* an [Ed25519][] keypair, \(K\).
|
||||||
|
* a ratchet, \(R_i\), which consists of four 256-bit values,
|
||||||
|
\(R_{i,j}\) for \(j \in {0,1,2,3}\).
|
||||||
|
|
||||||
|
The counter \(i\) is initialised to \(0\). A new Ed25519 keypair is
|
||||||
|
generated for \(K\). The ratchet is simply initialised with 1024 bits of
|
||||||
|
cryptographically-secure random data.
|
||||||
|
|
||||||
|
A single participant may use multiple sessions over the lifetime of a
|
||||||
|
conversation. The public part of \(K\) is used as an identifier to
|
||||||
|
discriminate between sessions.
|
||||||
|
|
||||||
|
### Sharing session data
|
||||||
|
|
||||||
|
To allow other participants in the conversation to decrypt messages, the
|
||||||
|
session data is formatted as described in [Session-sharing format](#session-sharing-format). It is then
|
||||||
|
shared with other participants in the conversation via a secure peer-to-peer
|
||||||
|
channel (such as that provided by [Olm][]).
|
||||||
|
|
||||||
|
When the session data is received from other participants, the recipient first
|
||||||
|
checks that the signature matches the public key. They then store their own
|
||||||
|
copy of the counter, ratchet, and public key.
|
||||||
|
|
||||||
|
### Message encryption
|
||||||
|
|
||||||
|
This version of Megolm uses [AES-256][] in [CBC][] mode with [PKCS#7][] padding and
|
||||||
|
[HMAC-SHA-256][] (truncated to 64 bits). The 256 bit AES key, 256 bit HMAC key,
|
||||||
|
and 128 bit AES IV are derived from the megolm ratchet \(R_i\):
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
\mathit{AES\_KEY}_{i}\;\parallel\;\mathit{HMAC\_KEY}_{i}\;\parallel\;\mathit{AES\_IV}_{i}
|
||||||
|
&= \operatorname{HKDF}\left(0,\,R_{i},\text{"MEGOLM\_KEYS"},\,80\right) \\
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
where \(\parallel\) represents string splitting, and
|
||||||
|
\(\operatorname{HKDF}\left(\mathit{salt},\,\mathit{IKM},\,\mathit{info},\,L\right)\)
|
||||||
|
refers to the [HMAC-based key
|
||||||
|
derivation function][] using using [SHA-256][] as the hash function
|
||||||
|
([HKDF-SHA-256][]) with a salt value of \(\mathit{salt}\), input key material of
|
||||||
|
\(\mathit{IKM}\), context string \(\mathit{info}\), and output keying material length of
|
||||||
|
\(L\) bytes.
|
||||||
|
|
||||||
|
The plain-text is encrypted with AES-256, using the key \(\mathit{AES\_KEY}_{i}\)
|
||||||
|
and the IV \(\mathit{AES\_IV}_{i}\) to give the cipher-text, \(X_{i}\).
|
||||||
|
|
||||||
|
The ratchet index \(i\), and the cipher-text \(X_{i}\), are then packed
|
||||||
|
into a message as described in [Message format](#message-format). Then the entire message
|
||||||
|
(including the version bytes and all payload bytes) are passed through
|
||||||
|
HMAC-SHA-256. The first 8 bytes of the MAC are appended to the message.
|
||||||
|
|
||||||
|
Finally, the authenticated message is signed using the Ed25519 keypair; the 64
|
||||||
|
byte signature is appended to the message.
|
||||||
|
|
||||||
|
The complete signed message, together with the public part of \(K\) (acting
|
||||||
|
as a session identifier), can then be sent over an insecure channel. The
|
||||||
|
message can then be authenticated and decrypted only by recipients who have
|
||||||
|
received the session data.
|
||||||
|
|
||||||
|
### Advancing the ratchet
|
||||||
|
|
||||||
|
After each message is encrypted, the ratchet is advanced. This is done as
|
||||||
|
described in [The Megolm ratchet algorithm](#the-megolm-ratchet-algorithm), using the following definitions:
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
H_0(A) &\equiv \operatorname{HMAC}(A,\text{``\char`\\x00"}) \\
|
||||||
|
H_1(A) &\equiv \operatorname{HMAC}(A,\text{``\char`\\x01"}) \\
|
||||||
|
H_2(A) &\equiv \operatorname{HMAC}(A,\text{``\char`\\x02"}) \\
|
||||||
|
H_3(A) &\equiv \operatorname{HMAC}(A,\text{``\char`\\x03"}) \\
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
where \(\operatorname{HMAC}(A, T)\) is the HMAC-SHA-256 of ``T``, using ``A`` as the
|
||||||
|
key.
|
||||||
|
|
||||||
|
For outbound sessions, the updated ratchet and counter are stored in the
|
||||||
|
session.
|
||||||
|
|
||||||
|
In order to maintain the ability to decrypt conversation history, inbound
|
||||||
|
sessions should store a copy of their earliest known ratchet value (unless they
|
||||||
|
explicitly want to drop the ability to decrypt that history - see [Partial
|
||||||
|
Forward Secrecy](#partial-forward-secrecy)). They may also choose to cache calculated ratchet values,
|
||||||
|
but the decision of which ratchet states to cache is left to the application.
|
||||||
|
|
||||||
|
## Data exchange formats
|
||||||
|
|
||||||
|
### Session sharing format
|
||||||
|
|
||||||
|
This format is used for the initial sharing of a Megolm session with other
|
||||||
|
group participants who need to be able to read messages encrypted by this
|
||||||
|
session.
|
||||||
|
|
||||||
|
The session sharing format is as follows:
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
+---+----+--------+--------+--------+--------+------+-----------+
|
||||||
|
| V | i | R(i,0) | R(i,1) | R(i,2) | R(i,3) | Kpub | Signature |
|
||||||
|
+---+----+--------+--------+--------+--------+------+-----------+
|
||||||
|
0 1 5 37 69 101 133 165 229 bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
The version byte, ``V``, is ``"\x02"``.
|
||||||
|
|
||||||
|
This is followed by the ratchet index, \(i\), which is encoded as a
|
||||||
|
big-endian 32-bit integer; the ratchet values \(R_{i,j}\); and the public
|
||||||
|
part of the Ed25519 keypair \(K\).
|
||||||
|
|
||||||
|
The data is then signed using the Ed25519 keypair, and the 64-byte signature is
|
||||||
|
appended.
|
||||||
|
|
||||||
|
### Session export format
|
||||||
|
|
||||||
|
Once the session is initially shared with the group participants, each
|
||||||
|
participant needs to retain a copy of the session if they want to maintain
|
||||||
|
their ability to decrypt messages encrypted with that session.
|
||||||
|
|
||||||
|
For forward-secrecy purposes, a participant may choose to store a ratcheted
|
||||||
|
version of the session. But since the ratchet index is covered by the
|
||||||
|
signature, this would invalidate the signature. So we define a similar format,
|
||||||
|
called the *session export format*, which is identical to the [session sharing
|
||||||
|
format](#session-sharing-format) except for dropping the signature.
|
||||||
|
|
||||||
|
The Megolm session export format is thus as follows:
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
+---+----+--------+--------+--------+--------+------+
|
||||||
|
| V | i | R(i,0) | R(i,1) | R(i,2) | R(i,3) | Kpub |
|
||||||
|
+---+----+--------+--------+--------+--------+------+
|
||||||
|
0 1 5 37 69 101 133 165 bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
The version byte, ``V``, is ``"\x01"``.
|
||||||
|
|
||||||
|
This is followed by the ratchet index, \(i\), which is encoded as a
|
||||||
|
big-endian 32-bit integer; the ratchet values \(R_{i,j}\); and the public
|
||||||
|
part of the Ed25519 keypair \(K\).
|
||||||
|
|
||||||
|
### Message format
|
||||||
|
|
||||||
|
Megolm messages consist of a one byte version, followed by a variable length
|
||||||
|
payload, a fixed length message authentication code, and a fixed length
|
||||||
|
signature.
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
+---+------------------------------------+-----------+------------------+
|
||||||
|
| V | Payload Bytes | MAC Bytes | Signature Bytes |
|
||||||
|
+---+------------------------------------+-----------+------------------+
|
||||||
|
0 1 N N+8 N+72 bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
The version byte, ``V``, is ``"\x03"``.
|
||||||
|
|
||||||
|
The payload uses a format based on the [Protocol Buffers encoding][]. It
|
||||||
|
consists of the following key-value pairs:
|
||||||
|
|
||||||
|
**Name**|**Tag**|**Type**|**Meaning**
|
||||||
|
:-----:|:-----:|:-----:|:-----:
|
||||||
|
Message-Index|0x08|Integer|The index of the ratchet, i
|
||||||
|
Cipher-Text|0x12|String|The cipher-text, Xi, of the message
|
||||||
|
|
||||||
|
Within the payload, integers are encoded using a variable length encoding. Each
|
||||||
|
integer is encoded as a sequence of bytes with the high bit set followed by a
|
||||||
|
byte with the high bit clear. The seven low bits of each byte store the bits of
|
||||||
|
the integer. The least significant bits are stored in the first byte.
|
||||||
|
|
||||||
|
Strings are encoded as a variable-length integer followed by the string itself.
|
||||||
|
|
||||||
|
Each key-value pair is encoded as a variable-length integer giving the tag,
|
||||||
|
followed by a string or variable-length integer giving the value.
|
||||||
|
|
||||||
|
The payload is followed by the MAC. The length of the MAC is determined by the
|
||||||
|
authenticated encryption algorithm being used (8 bytes in this version of the
|
||||||
|
protocol). The MAC protects all of the bytes preceding the MAC.
|
||||||
|
|
||||||
|
The length of the signature is determined by the signing algorithm being used
|
||||||
|
(64 bytes in this version of the protocol). The signature covers all of the
|
||||||
|
bytes preceding the signature.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
### Message Replays
|
||||||
|
|
||||||
|
A message can be decrypted successfully multiple times. This means that an
|
||||||
|
attacker can re-send a copy of an old message, and the recipient will treat it
|
||||||
|
as a new message.
|
||||||
|
|
||||||
|
To mitigate this it is recommended that applications track the ratchet indices
|
||||||
|
they have received and that they reject messages with a ratchet index that
|
||||||
|
they have already decrypted.
|
||||||
|
|
||||||
|
### Lack of Transcript Consistency
|
||||||
|
|
||||||
|
In a group conversation, there is no guarantee that all recipients have
|
||||||
|
received the same messages. For example, if Alice is in a conversation with Bob
|
||||||
|
and Charlie, she could send different messages to Bob and Charlie, or could
|
||||||
|
send some messages to Bob but not Charlie, or vice versa.
|
||||||
|
|
||||||
|
Solving this is, in general, a hard problem, particularly in a protocol which
|
||||||
|
does not guarantee in-order message delivery. For now it remains the subject of
|
||||||
|
future research.
|
||||||
|
|
||||||
|
### Lack of Backward Secrecy
|
||||||
|
|
||||||
|
[Backward secrecy](https://intensecrypto.org/public/lec_08_hash_functions_part2.html#sec-forward-and-backward-secrecy)
|
||||||
|
(also called 'future secrecy' or 'post-compromise security') is the property
|
||||||
|
that if current private keys are compromised, an attacker cannot decrypt
|
||||||
|
future messages in a given session. In other words, when looking
|
||||||
|
**backwards** in time at a compromise which has already happened, **current**
|
||||||
|
messages are still secret.
|
||||||
|
|
||||||
|
By itself, Megolm does not possess this property: once the key to a Megolm
|
||||||
|
session is compromised, the attacker can decrypt any message that was
|
||||||
|
encrypted using a key derived from the compromised or subsequent ratchet
|
||||||
|
values.
|
||||||
|
|
||||||
|
In order to mitigate this, the application should ensure that Megolm sessions
|
||||||
|
are not used indefinitely. Instead it should periodically start a new session,
|
||||||
|
with new keys shared over a secure channel.
|
||||||
|
|
||||||
|
<!-- TODO: Can we recommend sensible lifetimes for Megolm sessions? Probably
|
||||||
|
depends how paranoid we're feeling, but some guidelines might be useful. -->
|
||||||
|
|
||||||
|
### Partial Forward Secrecy
|
||||||
|
|
||||||
|
[Forward secrecy](https://intensecrypto.org/public/lec_08_hash_functions_part2.html#sec-forward-and-backward-secrecy)
|
||||||
|
(also called 'perfect forward secrecy') is the property that if the current
|
||||||
|
private keys are compromised, an attacker cannot decrypt *past* messages in
|
||||||
|
a given session. In other words, when looking **forwards** in time towards a
|
||||||
|
potential future compromise, **current** messages will be secret.
|
||||||
|
|
||||||
|
In Megolm, each recipient maintains a record of the ratchet value which allows
|
||||||
|
them to decrypt any messages sent in the session after the corresponding point
|
||||||
|
in the conversation. If this value is compromised, an attacker can similarly
|
||||||
|
decrypt past messages which were encrypted by a key derived from the
|
||||||
|
compromised or subsequent ratchet values. This gives 'partial' forward
|
||||||
|
secrecy.
|
||||||
|
|
||||||
|
To mitigate this issue, the application should offer the user the option to
|
||||||
|
discard historical conversations, by winding forward any stored ratchet values,
|
||||||
|
or discarding sessions altogether.
|
||||||
|
|
||||||
|
### Dependency on secure channel for key exchange
|
||||||
|
|
||||||
|
The design of the Megolm ratchet relies on the availability of a secure
|
||||||
|
peer-to-peer channel for the exchange of session keys. Any vulnerabilities in
|
||||||
|
the underlying channel are likely to be amplified when applied to Megolm
|
||||||
|
session setup.
|
||||||
|
|
||||||
|
For example, if the peer-to-peer channel is vulnerable to an unknown key-share
|
||||||
|
attack, the entire Megolm session become similarly vulnerable. For example:
|
||||||
|
Alice starts a group chat with Eve, and shares the session keys with Eve. Eve
|
||||||
|
uses the unknown key-share attack to forward the session keys to Bob, who
|
||||||
|
believes Alice is starting the session with him. Eve then forwards messages
|
||||||
|
from the Megolm session to Bob, who again believes they are coming from
|
||||||
|
Alice. Provided the peer-to-peer channel is not vulnerable to this attack, Bob
|
||||||
|
will realise that the key-sharing message was forwarded by Eve, and can treat
|
||||||
|
the Megolm session as a forgery.
|
||||||
|
|
||||||
|
A second example: if the peer-to-peer channel is vulnerable to a replay
|
||||||
|
attack, this can be extended to entire Megolm sessions.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The Megolm specification (this document) is licensed under the Apache License,
|
||||||
|
Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
|
||||||
|
[Ed25519]: http://ed25519.cr.yp.to/
|
||||||
|
[HMAC-based key derivation function]: https://tools.ietf.org/html/rfc5869
|
||||||
|
[HKDF-SHA-256]: https://tools.ietf.org/html/rfc5869
|
||||||
|
[HMAC-SHA-256]: https://tools.ietf.org/html/rfc2104
|
||||||
|
[SHA-256]: https://tools.ietf.org/html/rfc6234
|
||||||
|
[AES-256]: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
|
[CBC]: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
[PKCS#7]: https://tools.ietf.org/html/rfc2315
|
||||||
|
[Olm]: https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/olm.md
|
||||||
|
[Protocol Buffers encoding]: https://developers.google.com/protocol-buffers/docs/encoding
|
||||||
334
content/olm-megolm/olm.md
Normal file
334
content/olm-megolm/olm.md
Normal file
|
|
@ -0,0 +1,334 @@
|
||||||
|
---
|
||||||
|
title: "Olm: A Cryptographic Ratchet"
|
||||||
|
weight: 10
|
||||||
|
type: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
An implementation of the double cryptographic ratchet described by
|
||||||
|
https://whispersystems.org/docs/specifications/doubleratchet/.
|
||||||
|
|
||||||
|
## Notation
|
||||||
|
|
||||||
|
This document uses \(\parallel\) to represent string concatenation. When
|
||||||
|
\(\parallel\) appears on the right hand side of an \(=\) it means that
|
||||||
|
the inputs are concatenated. When \(\parallel\) appears on the left hand
|
||||||
|
side of an \(=\) it means that the output is split.
|
||||||
|
|
||||||
|
When this document uses \(\operatorname{ECDH}\left(K_A,K_B\right)\) it means
|
||||||
|
that each party computes a Diffie-Hellman agreement using their private key
|
||||||
|
and the remote party's public key.
|
||||||
|
So party \(A\) computes \(\operatorname{ECDH}\left(K_B^{public},K_A^{private}\right)\)
|
||||||
|
and party \(B\) computes \(\operatorname{ECDH}\left(K_A^{public},K_B^{private}\right)\).
|
||||||
|
|
||||||
|
Where this document uses \(\operatorname{HKDF}\left(salt,IKM,info,L\right)\) it
|
||||||
|
refers to the [HMAC-based key derivation function][] with a salt value of
|
||||||
|
\(salt\), input key material of \(IKM\), context string \(info\),
|
||||||
|
and output keying material length of \(L\) bytes.
|
||||||
|
|
||||||
|
## The Olm Algorithm
|
||||||
|
|
||||||
|
### Initial setup
|
||||||
|
|
||||||
|
The setup takes four [Curve25519][] inputs: Identity keys for Alice and Bob,
|
||||||
|
\(I_A\) and \(I_B\), and one-time keys for Alice and Bob,
|
||||||
|
\(E_A\) and \(E_B\). A shared secret, \(S\), is generated using
|
||||||
|
[Triple Diffie-Hellman][]. The initial 256 bit root key, \(R_0\), and 256
|
||||||
|
bit chain key, \(C_{0,0}\), are derived from the shared secret using an
|
||||||
|
HMAC-based Key Derivation Function using [SHA-256][] as the hash function
|
||||||
|
([HKDF-SHA-256][]) with default salt and ``"OLM_ROOT"`` as the info.
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
S&=\operatorname{ECDH}\left(I_A,E_B\right)\;\parallel\;
|
||||||
|
\operatorname{ECDH}\left(E_A,I_B\right)\;\parallel\;
|
||||||
|
\operatorname{ECDH}\left(E_A,E_B\right)\\
|
||||||
|
R_0\;\parallel\;C_{0,0}&=
|
||||||
|
\operatorname{HKDF}\left(0,S,\text{``OLM\_ROOT"},64\right)
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
### Advancing the root key
|
||||||
|
|
||||||
|
Advancing a root key takes the previous root key, \(R_{i-1}\), and two
|
||||||
|
Curve25519 inputs: the previous ratchet key, \(T_{i-1}\), and the current
|
||||||
|
ratchet key \(T_i\). The even ratchet keys are generated by Alice.
|
||||||
|
The odd ratchet keys are generated by Bob. A shared secret is generated
|
||||||
|
using Diffie-Hellman on the ratchet keys. The next root key, \(R_i\), and
|
||||||
|
chain key, \(C_{i,0}\), are derived from the shared secret using
|
||||||
|
[HKDF-SHA-256][] using \(R_{i-1}\) as the salt and ``"OLM_RATCHET"`` as the
|
||||||
|
info.
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
R_i\;\parallel\;C_{i,0}&=
|
||||||
|
\operatorname{HKDF}\left(
|
||||||
|
R_{i-1},
|
||||||
|
\operatorname{ECDH}\left(T_{i-1},T_i\right),
|
||||||
|
\text{``OLM\_RATCHET"},
|
||||||
|
64
|
||||||
|
\right)
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
### Advancing the chain key
|
||||||
|
|
||||||
|
Advancing a chain key takes the previous chain key, \(C_{i,j-1}\). The next
|
||||||
|
chain key, \(C_{i,j}\), is the [HMAC-SHA-256][] of ``"\x02"`` using the
|
||||||
|
previous chain key as the key.
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
C_{i,j}&=\operatorname{HMAC}\left(C_{i,j-1},\text{``\char`\\x02"}\right)
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
### Creating a message key
|
||||||
|
|
||||||
|
Creating a message key takes the current chain key, \(C_{i,j}\). The
|
||||||
|
message key, \(M_{i,j}\), is the [HMAC-SHA-256][] of ``"\x01"`` using the
|
||||||
|
current chain key as the key. The message keys where \(i\) is even are used
|
||||||
|
by Alice to encrypt messages. The message keys where \(i\) is odd are used
|
||||||
|
by Bob to encrypt messages.
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
M_{i,j}&=\operatorname{HMAC}\left(C_{i,j},\text{``\char`\\x01"}\right)
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
## The Olm Protocol
|
||||||
|
|
||||||
|
### Creating an outbound session
|
||||||
|
|
||||||
|
Bob publishes the public parts of his identity key, \(I_B\), and some
|
||||||
|
single-use one-time keys \(E_B\).
|
||||||
|
|
||||||
|
Alice downloads Bob's identity key, \(I_B\), and a one-time key,
|
||||||
|
\(E_B\). She generates a new single-use key, \(E_A\), and computes a
|
||||||
|
root key, \(R_0\), and a chain key \(C_{0,0}\). She also generates a
|
||||||
|
new ratchet key \(T_0\).
|
||||||
|
|
||||||
|
### Sending the first pre-key messages
|
||||||
|
|
||||||
|
Alice computes a message key, \(M_{0,j}\), and a new chain key,
|
||||||
|
\(C_{0,j+1}\), using the current chain key. She replaces the current chain
|
||||||
|
key with the new one.
|
||||||
|
|
||||||
|
Alice encrypts her plain-text with the message key, \(M_{0,j}\), using an
|
||||||
|
authenticated encryption scheme (see below) to get a cipher-text,
|
||||||
|
\(X_{0,j}\).
|
||||||
|
|
||||||
|
She then sends the following to Bob:
|
||||||
|
* The public part of her identity key, \(I_A\)
|
||||||
|
* The public part of her single-use key, \(E_A\)
|
||||||
|
* The public part of Bob's single-use key, \(E_B\)
|
||||||
|
* The current chain index, \(j\)
|
||||||
|
* The public part of her ratchet key, \(T_0\)
|
||||||
|
* The cipher-text, \(X_{0,j}\)
|
||||||
|
|
||||||
|
Alice will continue to send pre-key messages until she receives a message from
|
||||||
|
Bob.
|
||||||
|
|
||||||
|
### Creating an inbound session from a pre-key message
|
||||||
|
|
||||||
|
Bob receives a pre-key message as above.
|
||||||
|
|
||||||
|
Bob looks up the private part of his single-use key, \(E_B\). He can now
|
||||||
|
compute the root key, \(R_0\), and the chain key, \(C_{0,0}\), from
|
||||||
|
\(I_A\), \(E_A\), \(I_B\), and \(E_B\).
|
||||||
|
|
||||||
|
Bob then advances the chain key \(j\) times, to compute the chain key used
|
||||||
|
by the message, \(C_{0,j}\). He now creates the
|
||||||
|
message key, \(M_{0,j}\), and attempts to decrypt the cipher-text,
|
||||||
|
\(X_{0,j}\). If the cipher-text's authentication is correct then Bob can
|
||||||
|
discard the private part of his single-use one-time key, \(E_B\).
|
||||||
|
|
||||||
|
Bob stores Alice's initial ratchet key, \(T_0\), until he wants to
|
||||||
|
send a message.
|
||||||
|
|
||||||
|
### Sending normal messages
|
||||||
|
|
||||||
|
Once a message has been received from the other side, a session is considered
|
||||||
|
established, and a more compact form is used.
|
||||||
|
|
||||||
|
To send a message, the user checks if they have a sender chain key,
|
||||||
|
\(C_{i,j}\). Alice uses chain keys where \(i\) is even. Bob uses chain
|
||||||
|
keys where \(i\) is odd. If the chain key doesn't exist then a new ratchet
|
||||||
|
key \(T_i\) is generated and a new root key \(R_i\) and chain key
|
||||||
|
\(C_{i,0}\) are computed using \(R_{i-1}\), \(T_{i-1}\) and
|
||||||
|
\(T_i\).
|
||||||
|
|
||||||
|
A message key,
|
||||||
|
\(M_{i,j}\) is computed from the current chain key, \(C_{i,j}\), and
|
||||||
|
the chain key is replaced with the next chain key, \(C_{i,j+1}\). The
|
||||||
|
plain-text is encrypted with \(M_{i,j}\), using an authenticated encryption
|
||||||
|
scheme (see below) to get a cipher-text, \(X_{i,j}\).
|
||||||
|
|
||||||
|
The user then sends the following to the recipient:
|
||||||
|
* The current chain index, \(j\)
|
||||||
|
* The public part of the current ratchet key, \(T_i\)
|
||||||
|
* The cipher-text, \(X_{i,j}\)
|
||||||
|
|
||||||
|
### Receiving messages
|
||||||
|
|
||||||
|
The user receives a message as above with the sender's current chain index, \(j\),
|
||||||
|
the sender's ratchet key, \(T_i\), and the cipher-text, \(X_{i,j}\).
|
||||||
|
|
||||||
|
The user checks if they have a receiver chain with the correct
|
||||||
|
\(i\) by comparing the ratchet key, \(T_i\). If the chain doesn't exist
|
||||||
|
then they compute a new root key, \(R_i\), and a new receiver chain, with
|
||||||
|
chain key \(C_{i,0}\), using \(R_{i-1}\), \(T_{i-1}\) and
|
||||||
|
\(T_i\).
|
||||||
|
|
||||||
|
If the \(j\) of the message is less than
|
||||||
|
the current chain index on the receiver then the message may only be decrypted
|
||||||
|
if the receiver has stored a copy of the message key \(M_{i,j}\). Otherwise
|
||||||
|
the receiver computes the chain key, \(C_{i,j}\). The receiver computes the
|
||||||
|
message key, \(M_{i,j}\), from the chain key and attempts to decrypt the
|
||||||
|
cipher-text, \(X_{i,j}\).
|
||||||
|
|
||||||
|
If the decryption succeeds the receiver updates the chain key for \(T_i\)
|
||||||
|
with \(C_{i,j+1}\) and stores the message keys that were skipped in the
|
||||||
|
process so that they can decode out of order messages. If the receiver created
|
||||||
|
a new receiver chain then they discard their current sender chain so that
|
||||||
|
they will create a new chain when they next send a message.
|
||||||
|
|
||||||
|
## The Olm Message Format
|
||||||
|
|
||||||
|
Olm uses two types of messages. The underlying transport protocol must provide
|
||||||
|
a means for recipients to distinguish between them.
|
||||||
|
|
||||||
|
### Normal Messages
|
||||||
|
|
||||||
|
Olm messages start with a one byte version followed by a variable length
|
||||||
|
payload followed by a fixed length message authentication code.
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
+--------------+------------------------------------+-----------+
|
||||||
|
| Version Byte | Payload Bytes | MAC Bytes |
|
||||||
|
+--------------+------------------------------------+-----------+
|
||||||
|
```
|
||||||
|
|
||||||
|
The version byte is ``"\x03"``.
|
||||||
|
|
||||||
|
The payload consists of key-value pairs where the keys are integers and the
|
||||||
|
values are integers and strings. The keys are encoded as a variable length
|
||||||
|
integer tag where the 3 lowest bits indicates the type of the value:
|
||||||
|
0 for integers, 2 for strings. If the value is an integer then the tag is
|
||||||
|
followed by the value encoded as a variable length integer. If the value is
|
||||||
|
a string then the tag is followed by the length of the string encoded as
|
||||||
|
a variable length integer followed by the string itself.
|
||||||
|
|
||||||
|
Olm uses a variable length encoding for integers. Each integer is encoded as a
|
||||||
|
sequence of bytes with the high bit set followed by a byte with the high bit
|
||||||
|
clear. The seven low bits of each byte store the bits of the integer. The least
|
||||||
|
significant bits are stored in the first byte.
|
||||||
|
|
||||||
|
**Name**|**Tag**|**Type**|**Meaning**
|
||||||
|
:-----:|:-----:|:-----:|:-----:
|
||||||
|
Ratchet-Key|0x0A|String|The public part of the ratchet key, Ti, of the message
|
||||||
|
Chain-Index|0x10|Integer|The chain index, j, of the message
|
||||||
|
Cipher-Text|0x22|String|The cipher-text, Xi, j, of the message
|
||||||
|
|
||||||
|
The length of the MAC is determined by the authenticated encryption algorithm
|
||||||
|
being used. (Olm version 1 uses [HMAC-SHA-256][], truncated to 8 bytes). The
|
||||||
|
MAC protects all of the bytes preceding the MAC.
|
||||||
|
|
||||||
|
### Pre-Key Messages
|
||||||
|
|
||||||
|
Olm pre-key messages start with a one byte version followed by a variable
|
||||||
|
length payload.
|
||||||
|
|
||||||
|
```nohighlight
|
||||||
|
+--------------+------------------------------------+
|
||||||
|
| Version Byte | Payload Bytes |
|
||||||
|
+--------------+------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
The version byte is ``"\x03"``.
|
||||||
|
|
||||||
|
The payload uses the same key-value format as for normal messages.
|
||||||
|
|
||||||
|
**Name**|**Tag**|**Type**|**Meaning**
|
||||||
|
:-----:|:-----:|:-----:|:-----:
|
||||||
|
One-Time-Key|0x0A|String|The public part of Bob's single-use key, Eb.
|
||||||
|
Base-Key|0x12|String|The public part of Alice's single-use key, Ea.
|
||||||
|
Identity-Key|0x1A|String|The public part of Alice's identity key, Ia.
|
||||||
|
Message|0x22|String|An embedded Olm message with its own version and MAC.
|
||||||
|
|
||||||
|
## Olm Authenticated Encryption
|
||||||
|
|
||||||
|
### Version 1
|
||||||
|
|
||||||
|
Version 1 of Olm uses [AES-256][] in [CBC][] mode with [PKCS#7][] padding for
|
||||||
|
encryption and [HMAC-SHA-256][] (truncated to 64 bits) for authentication. The
|
||||||
|
256 bit AES key, 256 bit HMAC key, and 128 bit AES IV are derived from the
|
||||||
|
message key using [HKDF-SHA-256][] using the default salt and an info of
|
||||||
|
``"OLM_KEYS"``.
|
||||||
|
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
AES\_KEY_{i,j}\;\parallel\;HMAC\_KEY_{i,j}\;\parallel\;AES\_IV_{i,j}
|
||||||
|
&= \operatorname{HKDF}\left(0,M_{i,j},\text{``OLM\_KEYS"},80\right)
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
|
||||||
|
The plain-text is encrypted with AES-256, using the key \(AES\_KEY_{i,j}\)
|
||||||
|
and the IV \(AES\_IV_{i,j}\) to give the cipher-text, \(X_{i,j}\).
|
||||||
|
|
||||||
|
Then the entire message (including the Version Byte and all Payload Bytes) are
|
||||||
|
passed through [HMAC-SHA-256][]. The first 8 bytes of the MAC are appended to the message.
|
||||||
|
|
||||||
|
## Message authentication concerns
|
||||||
|
|
||||||
|
To avoid unknown key-share attacks, the application must include identifying
|
||||||
|
data for the sending and receiving user in the plain-text of (at least) the
|
||||||
|
pre-key messages. Such data could be a user ID, a telephone number;
|
||||||
|
alternatively it could be the public part of a keypair which the relevant user
|
||||||
|
has proven ownership of.
|
||||||
|
|
||||||
|
### Example attacks
|
||||||
|
|
||||||
|
1. Alice publishes her public [Curve25519][] identity key, \(I_A\). Eve
|
||||||
|
publishes the same identity key, claiming it as her own. Bob downloads
|
||||||
|
Eve's keys, and associates \(I_A\) with Eve. Alice sends a message to
|
||||||
|
Bob; Eve intercepts it before forwarding it to Bob. Bob believes the
|
||||||
|
message came from Eve rather than Alice.
|
||||||
|
|
||||||
|
This is prevented if Alice includes her user ID in the plain-text of the
|
||||||
|
pre-key message, so that Bob can see that the message was sent by Alice
|
||||||
|
originally.
|
||||||
|
|
||||||
|
2. Bob publishes his public [Curve25519][] identity key, \(I_B\). Eve
|
||||||
|
publishes the same identity key, claiming it as her own. Alice downloads
|
||||||
|
Eve's keys, and associates \(I_B\) with Eve. Alice sends a message to
|
||||||
|
Eve; Eve cannot decrypt it, but forwards it to Bob. Bob believes the
|
||||||
|
Alice sent the message to him, whereas Alice intended it to go to Eve.
|
||||||
|
|
||||||
|
This is prevented by Alice including the user ID of the intended recpient
|
||||||
|
(Eve) in the plain-text of the pre-key message. Bob can now tell that the
|
||||||
|
message was meant for Eve rather than him.
|
||||||
|
|
||||||
|
## IPR
|
||||||
|
|
||||||
|
The Olm specification (this document) is hereby placed in the public domain.
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
|
||||||
|
Can be sent to olm at matrix.org.
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
The ratchet that Olm implements was designed by Trevor Perrin and Moxie
|
||||||
|
Marlinspike - details at https://whispersystems.org/docs/specifications/doubleratchet/. Olm is
|
||||||
|
an entirely new implementation written by the Matrix.org team.
|
||||||
|
|
||||||
|
[Curve25519]: http://cr.yp.to/ecdh.html
|
||||||
|
[Triple Diffie-Hellman]: https://whispersystems.org/blog/simplifying-otr-deniability/
|
||||||
|
[HMAC-based key derivation function]: https://tools.ietf.org/html/rfc5869
|
||||||
|
[HKDF-SHA-256]: https://tools.ietf.org/html/rfc5869
|
||||||
|
[HMAC-SHA-256]: https://tools.ietf.org/html/rfc2104
|
||||||
|
[SHA-256]: https://tools.ietf.org/html/rfc6234
|
||||||
|
[AES-256]: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
|
[CBC]: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
[PKCS#7]: https://tools.ietf.org/html/rfc2315
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Spec Change Proposals"
|
title: "Spec Change Proposals"
|
||||||
weight: 60
|
weight: 62
|
||||||
type: docs
|
type: docs
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -185,6 +185,10 @@ is as follows:
|
||||||
- Take care in creating your proposal. Specify your intended
|
- Take care in creating your proposal. Specify your intended
|
||||||
changes, and give reasoning to back them up. Changes without
|
changes, and give reasoning to back them up. Changes without
|
||||||
justification will likely be poorly received by the community.
|
justification will likely be poorly received by the community.
|
||||||
|
- At the time of creating your draft you will not yet know the PR number, so you
|
||||||
|
should use a placeholder number to name your file and edit that
|
||||||
|
after PR submission. The suggested steps are described in
|
||||||
|
detail [in the proposals guide](https://github.com/matrix-org/matrix-spec-proposals#1-writing-the-proposal).
|
||||||
- Fork and make a PR to the
|
- Fork and make a PR to the
|
||||||
[matrix-spec-proposals](https://github.com/matrix-org/matrix-spec-proposals) repository.
|
[matrix-spec-proposals](https://github.com/matrix-org/matrix-spec-proposals) repository.
|
||||||
The ID of your PR will become the MSC ID for the lifetime of your
|
The ID of your PR will become the MSC ID for the lifetime of your
|
||||||
|
|
@ -277,7 +281,7 @@ corresponding labels for each stage on the
|
||||||
[matrix-spec-proposals](https://github.com/matrix-org/matrix-spec-proposals)
|
[matrix-spec-proposals](https://github.com/matrix-org/matrix-spec-proposals)
|
||||||
pull request trackers.
|
pull request trackers.
|
||||||
|
|
||||||
```
|
```nohighlight
|
||||||
+ +
|
+ +
|
||||||
Proposals | Spec PRs | Additional States
|
Proposals | Spec PRs | Additional States
|
||||||
+-------+ | +------+ | +---------------+
|
+-------+ | +------+ | +---------------+
|
||||||
|
|
@ -380,9 +384,18 @@ As part of the proposal process the Spec Core Team will require evidence
|
||||||
of the MSC working in order for it to move into FCP. This can usually be
|
of the MSC working in order for it to move into FCP. This can usually be
|
||||||
a branch/pull request to whichever implementation of choice that proves
|
a branch/pull request to whichever implementation of choice that proves
|
||||||
the MSC works in practice, though in some cases the MSC itself will be
|
the MSC works in practice, though in some cases the MSC itself will be
|
||||||
small enough to be considered proven. Where it's unclear if an MSC will
|
small enough to be considered proven. Implementations do not need to be
|
||||||
require an implementation proof, ask in
|
merged or released, but must be of sufficient quality to show that the
|
||||||
[\#matrix-spec:matrix.org](https://matrix.to/#/#matrix-spec:matrix.org).
|
MSC works. Where it's unclear if an MSC will require an implementation
|
||||||
|
proof, ask in [\#matrix-spec:matrix.org](https://matrix.to/#/#matrix-spec:matrix.org).
|
||||||
|
Proposals may require both server-side and client-side implementations.
|
||||||
|
|
||||||
|
Proposals that have not yet been implemented will have the
|
||||||
|
`needs-implementation` label. After an implementation has been made, add a
|
||||||
|
comment in the GitHub issue indicating so. After an implementation has been
|
||||||
|
made, we will check it to verify that it implements the MSC. Proposals that
|
||||||
|
have implementations that have not yet been checked will have the
|
||||||
|
`implementation-needs-checking` label.
|
||||||
|
|
||||||
### Early release of an MSC/idea
|
### Early release of an MSC/idea
|
||||||
|
|
||||||
|
|
@ -484,6 +497,42 @@ In summary:
|
||||||
a small table at the bottom mapping the various values from stable
|
a small table at the bottom mapping the various values from stable
|
||||||
to unstable.
|
to unstable.
|
||||||
|
|
||||||
|
### Placeholder MSCs
|
||||||
|
|
||||||
|
Some proposals may contain security-sensitive or private context which can't be
|
||||||
|
publicly disclosed until a later stage in the idea or solution process. Typically,
|
||||||
|
the initial idea is validated using some amount of implementation or experimentation
|
||||||
|
and may require an MSC number to make that implementation easier.
|
||||||
|
|
||||||
|
Placeholder MSCs are used to represent proposals in a state where implementation
|
||||||
|
is ongoing, but the MSC details can't yet be disclosed. Authors which feel as
|
||||||
|
though their MSC could be highly sensitive MUST get in contact with the Spec Core
|
||||||
|
Team or [Security Team](https://matrix.org/security-disclosure-policy/) prior to
|
||||||
|
opening their MSC. If either team determines that a placeholder MSC is required,
|
||||||
|
it may be opened as such.
|
||||||
|
|
||||||
|
There are a few expectations attached to placeholder MSCs:
|
||||||
|
|
||||||
|
* They have a title which marks them WIP, and are in the "draft" state.
|
||||||
|
* They have the following labels: `[proposal-placeholder, action-required, needs-implementation]`.
|
||||||
|
* Notably, *not* `proposal`.
|
||||||
|
* They are relatively short-lived (ideally less than 6-12 months in placeholder).
|
||||||
|
* They propose solutions which are reasonably likely to be accepted. If a placeholder
|
||||||
|
needs to be closed because the idea won't work, isn't needed, etc, then the MSC's
|
||||||
|
content MUST be published ahead of that closure.
|
||||||
|
* Note: the MSC's publication (and therefore closure) may be delayed until an
|
||||||
|
appropriate point in the security disclosure cycle. For example, an alternative
|
||||||
|
MSC being published, or a stream of work being completed.
|
||||||
|
* When they are updated to receive real content, the following happens:
|
||||||
|
1. The Spec Core Team or the author leaves a comment to cause a notification
|
||||||
|
that the MSC has been replaced with real content.
|
||||||
|
2. The `proposal` label (or its equivalent) is added to trigger chat notifications
|
||||||
|
in the public Matrix rooms. The `proposal-placeholder` and `action-required`
|
||||||
|
labels should be removed at this stage as well. Other labels are removed/applied
|
||||||
|
per normal process.
|
||||||
|
* The Spec Core Team is aware of the intended MSC's title and purpose. This is
|
||||||
|
especially important if the Security Team approved the use of a placeholder MSC.
|
||||||
|
|
||||||
## Proposal Tracking
|
## Proposal Tracking
|
||||||
|
|
||||||
This is a living document generated from the list of proposals on the
|
This is a living document generated from the list of proposals on the
|
||||||
|
|
@ -506,7 +555,7 @@ resolve to the desired MSC, whether it started as an issue or a PR.
|
||||||
Other metadata:
|
Other metadata:
|
||||||
|
|
||||||
- The MSC number is taken from the GitHub Pull Request ID. This is
|
- The MSC number is taken from the GitHub Pull Request ID. This is
|
||||||
carried for the lifetime of the proposal. These IDs do not necessary
|
carried for the lifetime of the proposal. These IDs do not necessarily
|
||||||
represent a chronological order.
|
represent a chronological order.
|
||||||
- The GitHub PR title will act as the MSC's title.
|
- The GitHub PR title will act as the MSC's title.
|
||||||
- Please link to the spec PR (if any) by adding a "PRs: \#1234" line
|
- Please link to the spec PR (if any) by adding a "PRs: \#1234" line
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue