| exclusive | **Required** A true or false value stating whether this application service has exclusive access to events within this namespace. |
<colstyle="width: 87%"/>
| regex | **Required** A regular expression defining which values this namespace includes. |
</colgroup>
<thead>
<trclass="header">
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td>exclusive</td>
<td><strong>Required</strong> A true or false value stating whether this application service has exclusive access to events within this namespace.</td>
</tr>
<trclass="even">
<td>regex</td>
<td><strong>Required</strong> A regular expression defining which values this namespace includes.</td>
</tr>
</tbody>
</table>
Exclusive user and alias namespaces should begin with an underscore
Exclusive user and alias namespaces should begin with an underscore
after the sigil to avoid collisions with other users on the homeserver.
after the sigil to avoid collisions with other users on the homeserver.
@ -149,52 +110,17 @@ The registration is represented by a series of key-value pairs, which
this specification will present as YAML. See below for the possible
this specification will present as YAML. See below for the possible
| id | **Required** A unique, user-defined ID of the application service which will never change. |
</colgroup>
| url | **Required** The URL for the application service. May include a path after the domain name. Optionally set to null if no traffic is required. |
<thead>
| as_token | **Required** A unique token for application services to use to authenticate requests to Homeservers. |
<trclass="header">
| hs_token | **Required** A unique token for Homeservers to use to authenticate requests to application services. |
<th>Name</th>
| sender_localpart | **Required** The localpart of the user associated with the application service. |
<th>Description</th>
| namespaces | **Required** A list of `users`, `aliases` and `rooms` namespaces that the application service controls. |
</tr>
| rate_limited | Whether requests from masqueraded users are rate-limited. The sender is excluded. |
</thead>
| protocols | The external protocols which the application service provides (e.g. IRC). |
<tbody>
<trclass="odd">
<td>id</td>
<td><strong>Required.</strong> A unique, user-defined ID of the application service which will never change.</td>
</tr>
<trclass="even">
<td>url</td>
<td><strong>Required.</strong> The URL for the application service. May include a path after the domain name. Optionally set to <code>null</code> if no traffic is required.</td>
</tr>
<trclass="odd">
<td>as_token</td>
<td><strong>Required.</strong> A unique token for application services to use to authenticate requests to Homeservers.</td>
</tr>
<trclass="even">
<td>hs_token</td>
<td><strong>Required.</strong> A unique token for Homeservers to use to authenticate requests to application services.</td>
</tr>
<trclass="odd">
<td>sender_localpart</td>
<td><strong>Required.</strong> The localpart of the user associated with the application service.</td>
</tr>
<trclass="even">
<td>namespaces</td>
<td><strong>Required.</strong> A list of <code>users</code>, <code>aliases</code> and <code>rooms</code> namespaces that the application service controls.</td>
</tr>
<trclass="odd">
<td>rate_limited</td>
<td>Whether requests from masqueraded users are rate-limited. The sender is excluded.</td>
</tr>
<trclass="even">
<td>protocols</td>
<td>The external protocols which the application service provides (e.g. IRC).</td>
</tr>
</tbody>
</table>
An example registration file for an IRC-bridging application service is
An example registration file for an IRC-bridging application service is
| state_key | string | **Required.** A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. State keys starting with an `@` are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user's ID as the state key MUST only be set by that user. |
<colstyle="width: 67%"/>
| prev_content | EventContent | Optional. The previous `content` for this event. If there is no previous content, this key will be missing. |
</colgroup>
<thead>
<trclass="header">
<th>Key</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td>state_key</td>
<td>string</td>
<td><strong>Required.</strong> A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. State keys starting with an <code>@</code> are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user's ID as the state key MUST only be set by that user.</td>
</tr>
<trclass="even">
<td>prev_content</td>
<td>EventContent</td>
<td>Optional. The previous <code>content</code> for this event. If there is no previous content, this key will be missing.</td>
| key | string | **Required.** The unpadded Base64-encoded 32-byte Curve25519 public key. |
<th>Parameter</th>
| signatures | Signatures | **Required.** Signatures of the key object. The signature is calculated using the process described at [Signing JSON](/appendices/#signing-json). |
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>key</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The unpadded Base64-encoded 32-byte Curve25519 public key.</p></td>
</tr>
<trclass="even">
<td><p>signatures</p></td>
<td><p>Signatures</p></td>
<td><p><strong>Required.</strong> Signatures of the key object.</p>
<p>The signature is calculated using the process described at <ahref="/appendices/#signing-json">Signing JSON</a>.</p></td>
| url | string | **Required.** The URL to the file. |
<th>Parameter</th>
| key | JWK | **Required.** A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. |
<th>Type</th>
| iv | string | **Required.** The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64. |
<th>Description</th>
| 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`. |
</tr>
| v | string | **Required.** Version of the encrypted attachments protocol. Must be `v2`. |
</thead>
<tbody>
<trclass="odd">
<td>url</td>
<td>string</td>
<td><strong>Required.</strong> The URL to the file.</td>
</tr>
<trclass="even">
<td>key</td>
<td>JWK</td>
<td><strong>Required.</strong> A <ahref="https://tools.ietf.org/html/rfc7517#appendix-A.3">JSON Web Key</a> object.</td>
</tr>
<trclass="odd">
<td><p>iv</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64.</p></td>
</tr>
<trclass="even">
<td><p>hashes</p></td>
<td><p>{string: string}</p></td>
<td><p><strong>Required.</strong> 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 <code>sha256</code>.</p></td>
</tr>
<trclass="odd">
<td><p>v</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> Version of the encrypted attachments protocol. Must be <code>v2</code>.</p></td>
| kty | string | **Required.** Key type. Must be `oct`. |
<th>Parameter</th>
| key_ops | [string] | **Required.** Key operations. Must at least contain `encrypt` and `decrypt`. |
<th>Type</th>
| alg | string | **Required.** Algorithm. Must be `A256CTR`. |
<th>Description</th>
| k | string | **Required.** The key, encoded as urlsafe unpadded base64. |
</tr>
| ext | boolean | **Required.** Extractable. Must be `true`. This is a [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk). |
</thead>
<tbody>
<trclass="odd">
<td>kty</td>
<td>string</td>
<td><strong>Required.</strong> Key type. Must be <code>oct</code>.</td>
</tr>
<trclass="even">
<td><p>key_ops</p></td>
<td><p>[string]</p></td>
<td><p><strong>Required.</strong> Key operations. Must at least contain <code>encrypt</code> and <code>decrypt</code>.</p></td>
</tr>
<trclass="odd">
<td>alg</td>
<td>string</td>
<td><strong>Required.</strong> Algorithm. Must be <code>A256CTR</code>.</td>
</tr>
<trclass="even">
<td>k</td>
<td>string</td>
<td><strong>Required.</strong> The key, encoded as urlsafe unpadded base64.</td>
</tr>
<trclass="odd">
<td><p>ext</p></td>
<td><p>boolean</p></td>
<td><p><strong>Required.</strong> Extractable. Must be <code>true</code>. This is a <ahref="https://w3c.github.io/webcrypto/#iana-section-jwk">W3C extension</a>.</p></td>
| algorithm | string | **Required.** The end-to-end message encryption algorithm that the key is for. Must be `m.megolm.v1.aes-sha2`. |
<th>Parameter</th>
| forwarding_curve25519_key_chain | [string] | **Required.** Chain of Curve25519 keys through which this session was forwarded, via [m.forwarded_room_key](#mforwarded_room_key) events. |
<td><p><strong>Required.</strong> The end-to-end message encryption algorithm that the key is for. Must be <code>m.megolm.v1.aes-sha2</code>.</p></td>
</tr>
<trclass="even">
<td><p>forwarding_curve25519_key_chain</p></td>
<td><p>[string]</p></td>
<td><p><strong>Required.</strong> Chain of Curve25519 keys through which this session was forwarded, via <ahref="#mforwarded_room_key">m.forwarded_room_key</a> events.</p></td>
| algorithm | string | Required. The encryption algorithm that the session uses. Must be `m.megolm.v1.aes-sha2`. |
<th>Parameter</th>
| forwarding_curve25519_key_chain | [string] | Required. Chain of Curve25519 keys through which this session was forwarded, via [m.forwarded_room_key](#mforwarded_room_key) events. |
<th>Type</th>
| room_id | string | Required. The room where the session is used. |
<th>Description</th>
| sender_key | string | Required. The Curve25519 key of the device which initiated the session originally. |
</tr>
| sender_claimed_keys | {string: string} | Required. The Ed25519 key of the device which initiated the session originally. |
</thead>
| session_id | string | Required. The ID of the session. |
<tbody>
| session_key | string | Required. The key for the session. |
<trclass="odd">
<td><p>algorithm</p></td>
<td><p>string</p></td>
<td><p>Required. The encryption algorithm that the session uses. Must be <code>m.megolm.v1.aes-sha2</code>.</p></td>
</tr>
<trclass="even">
<td><p>forwarding_curve25519_key_chain</p></td>
<td><p>[string]</p></td>
<td><p>Required. Chain of Curve25519 keys through which this session was forwarded, via <ahref="#mforwarded_room_key">m.forwarded_room_key</a> events.</p></td>
</tr>
<trclass="odd">
<td><p>room_id</p></td>
<td><p>string</p></td>
<td><p>Required. The room where the session is used.</p></td>
</tr>
<trclass="even">
<td><p>sender_key</p></td>
<td><p>string</p></td>
<td><p>Required. The Curve25519 key of the device which initiated the session originally.</p></td>
</tr>
<trclass="odd">
<td><p>sender_claimed_keys</p></td>
<td><p>{string: string}</p></td>
<td><p>Required. The Ed25519 key of the device which initiated the session originally.</p></td>
</tr>
<trclass="even">
<td>session_id</td>
<td>string</td>
<td>Required. The ID of the session.</td>
</tr>
<trclass="odd">
<td>session_key</td>
<td>string</td>
<td>Required. The key for the session.</td>
</tr>
</tbody>
</table>
This is similar to the format before encryption used for the session
This is similar to the format before encryption used for the session
keys in [Server-side key backups](#server-side-key-backups) but adds the
keys in [Server-side key backups](#server-side-key-backups) but adds the
@ -1509,51 +1324,17 @@ It also adds a `one_time_keys_count` property. Note the spelling
difference with the `one_time_key_counts` property in the
difference with the `one_time_key_counts` property in the
| device_lists | DeviceLists | Optional. Information on e2e device updates. Note: only present on an incremental sync. |
<th>Parameter</th>
| 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. |
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>device_lists</p></td>
<td><p>DeviceLists</p></td>
<td><p>Optional. Information on e2e device updates. Note: only present on an incremental sync.</p></td>
</tr>
<trclass="even">
<td><p>device_one_time_keys_count</p></td>
<td><p>{string: integer}</p></td>
<td><p>Optional. For each key algorithm, the number of unclaimed one-time keys currently held on the server for this device.</p></td>
| 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. |
<th>Parameter</th>
| left | [string] | List of users with whom we do not share any encrypted rooms anymore since the previous sync response. |
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>changed</p></td>
<td><p>[string]</p></td>
<td><p>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.</p></td>
</tr>
<trclass="even">
<td><p>left</p></td>
<td><p>[string]</p></td>
<td><p>List of users with whom we do not share any encrypted rooms anymore since the previous sync response.</p></td>
</tr>
</tbody>
</table>
{{% 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
| name | string | **Required.** The name of the key. |
<th>Parameter</th>
| algorithm | string | **Required.** The encryption algorithm to be used for this key. Currently, only `m.secret_storage.v1.aes-hmac-sha2` is supported. |
<th>Type</th>
| passphrase | string | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td>name</td>
<td>string</td>
<td><strong>Required.</strong> The name of the key.</td>
</tr>
<trclass="even">
<td><p>algorithm</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The encryption algorithm to be used for this key. Currently, only <code>m.secret_storage.v1.aes-hmac-sha2</code> is supported.</p></td>
</tr>
<trclass="odd">
<td><p>passphrase</p></td>
<td><p>string</p></td>
<td><p>See <ahref="#deriving-keys-from-passphrases">deriving keys from passphrases</a> section for a description of this property.</p></td>
</tr>
</tbody>
</table>
Other properties depend on the encryption algorithm, and are described
Other properties depend on the encryption algorithm, and are described
below.
below.
@ -91,22 +70,9 @@ of the data.
`Secret`
`Secret`
<table>
| Parameter | Type | Description |
<thead>
|-----------|------------------|-------------|
<trclass="header">
| 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. |
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>encrypted</p></td>
<td><p>{string: object}</p></td>
<td><p><strong>Required.</strong> Map from key ID the encrypted data. The exact format for the encrypted data is dependent on the key algorithm. See the definition of <code>AesHmacSha2EncryptedData</code> in the <ahref="#msecret_storagev1aes-hmac-sha2">m.secret_storage.v1.aes-hmac-sha2</a> section.</p></td>
</tr>
</tbody>
</table>
Example:
Example:
@ -175,32 +141,11 @@ HMAC-SHA-256. The secret is encrypted as follows:
| name | string | **Required.** The name of the key. |
<th>Parameter</th>
| algorithm | string | **Required.** The encryption algorithm to be used for this key. Currently, only `m.secret_storage.v1.aes-hmac-sha2` is supported. |
<th>Type</th>
| passphrase | object | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
<th>Description</th>
| iv | string | The 16-byte initialization vector, encoded as base64. |
</tr>
| mac | string | The MAC of the result of encrypting 32 bytes of 0, encoded as base64. |
</thead>
<tbody>
<trclass="odd">
<td>name</td>
<td>string</td>
<td><strong>Required.</strong> The name of the key.</td>
</tr>
<trclass="even">
<td><p>algorithm</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The encryption algorithm to be used for this key. Currently, only <code>m.secret_storage.v1.aes-hmac-sha2</code> is supported.</p></td>
</tr>
<trclass="odd">
<td><p>passphrase</p></td>
<td><p>object</p></td>
<td><p>See <ahref="#deriving-keys-from-passphrases">deriving keys from passphrases</a> section for a description of this property.</p></td>
</tr>
<trclass="even">
<td>iv</td>
<td>string</td>
<td>The 16-byte initialization vector, encoded as base64.</td>
</tr>
<trclass="odd">
<td><p>mac</p></td>
<td><p>string</p></td>
<td><p>The MAC of the result of encrypting 32 bytes of 0, encoded as base64.</p></td>
</tr>
</tbody>
</table>
For example, the `m.secret_storage.key.key_id` for a key using this
For example, the `m.secret_storage.key.key_id` for a key using this
algorithm could look like:
algorithm could look like:
@ -311,37 +227,12 @@ defined by the `algorithm` specified.
For the `m.pbkdf2` algorithm, the `passphrase` property has the
For the `m.pbkdf2` algorithm, the `passphrase` property has the
| name | string | Required if ``action`` is ``request``. The name of the secret that is being requested. |
<th>Parameter</th>
| action | enum | **Required.** One of ["request", "request_cancellation"]. |
<th>Type</th>
| requesting_device_id | string | **Required.** The ID of the device requesting the secret. |
<th>Description</th>
| request_id | string | **Required.** A random string uniquely identifying (with respect to the requester and the target) the target for a secret. If the secret is requested from multiple devices at the same time, the same ID may be used for every target. The same ID is also used in order to cancel a previous request. |
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>name</p></td>
<td><p>string</p></td>
<td><p>Required if <code>action</code> is <code>request</code>. The name of the secret that is being requested.</p></td>
</tr>
<trclass="even">
<td>action</td>
<td>enum</td>
<td><strong>Required.</strong> One of ["request", "request_cancellation"].</td>
</tr>
<trclass="odd">
<td>requesting_device_id</td>
<td>string</td>
<td><strong>Required.</strong> The ID of the device requesting the secret.</td>
</tr>
<trclass="even">
<td><p>request_id</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> A random string uniquely identifying (with respect to the requester and the target) the target for a secret. If the secret is requested from multiple devices at the same time, the same ID may be used for every target. The same ID is also used in order to cancel a previous request.</p></td>
</tr>
</tbody>
</table>
Example:
Example:
@ -434,27 +300,10 @@ Sent by a client to share a secret with another device, in response to
an `m.secret.request` event. It must be encrypted as an
an `m.secret.request` event. It must be encrypted as an
`m.room.encrypted` event, then sent as a to-device event.
`m.room.encrypted` event, then sent as a to-device event.
| Proposal Drafting and Feedback | N/A | A proposal document which is still work-in-progress but is being shared to incorporate feedback. Please prefix your proposal's title with `[WIP]` to make it easier for reviewers to skim their notifications list. |
<th>Name</th>
| Proposal In Review | proposal-in-review | A proposal document which is now ready and waiting for review by the Spec Core Team and community |
<th>GitHub Label</th>
| Proposed Final Comment Period | proposed-final-comment-period | Currently awaiting signoff of a 75% majority of team members in order to enter the final comment period |
<th>Description</th>
| Final Comment Period | final-comment-period | A proposal document which has reached final comment period either for merge, closure or postponement |
</tr>
| Final Comment Period Complete | finished-final-comment-period | The final comment period has been completed. Waiting for a demonstration implementation |
</thead>
| Spec PR Missing | spec-pr-missing | The proposal has been agreed, and proven with a demonstration implementation. Waiting for a PR against the Spec |
<tbody>
| Spec PR In Review | spec-pr-in-review | The spec PR has been written, and is currently under review |
<trclass="odd">
| Spec PR Merged | merged | A proposal with a sufficient working implementation and whose Spec PR has been merged! |
<td>Proposal Drafting and Feedback</td>
| Postponed | proposal-postponed | A proposal that is temporarily blocked or a feature that may not be useful currently but perhaps sometime in the future |
<td>N/A</td>
| Closed | proposal-closed | A proposal which has been reviewed and deemed unsuitable for acceptance |
<td>A proposal document which is still work-in-progress but is being shared to incorporate feedback. Please prefix your proposal's title with <code>[WIP]</code> to make it easier for reviewers to skim their notifications list.</td>
| Obsolete | obsolete | A proposal which has been made obsolete by another proposal or decision elsewhere. |
</tr>
<trclass="even">
<td>Proposal In Review</td>
<td>proposal-in-review</td>
<td>A proposal document which is now ready and waiting for review by the Spec Core Team and community</td>
</tr>
<trclass="odd">
<td>Proposed Final Comment Period</td>
<td>proposed-final-comment-period</td>
<td>Currently awaiting signoff of a 75% majority of team members in order to enter the final comment period</td>
</tr>
<trclass="even">
<td>Final Comment Period</td>
<td>final-comment-period</td>
<td>A proposal document which has reached final comment period either for merge, closure or postponement</td>
</tr>
<trclass="odd">
<td>Final Comment Period Complete</td>
<td>finished-final-comment-period</td>
<td>The final comment period has been completed. Waiting for a demonstration implementation</td>
</tr>
<trclass="even">
<td>Spec PR Missing</td>
<td>spec-pr-missing</td>
<td>The proposal has been agreed, and proven with a demonstration implementation. Waiting for a PR against the Spec</td>
</tr>
<trclass="odd">
<td>Spec PR In Review</td>
<td>spec-pr-in-review</td>
<td>The spec PR has been written, and is currently under review</td>
</tr>
<trclass="even">
<td>Spec PR Merged</td>
<td>merged</td>
<td>A proposal with a sufficient working implementation and whose Spec PR has been merged!</td>
</tr>
<trclass="odd">
<td><p>Postponed</p></td>
<td><p>proposal-postponed</p></td>
<td><p>A proposal that is temporarily blocked or a feature that may not be useful currently but perhaps sometime in the future</p></td>
</tr>
<trclass="even">
<td>Closed</td>
<td>proposal-closed</td>
<td>A proposal which has been reviewed and deemed unsuitable for acceptance</td>
</tr>
<trclass="odd">
<td>Obsolete</td>
<td>obsolete</td>
<td>A proposal which has been made obsolete by another proposal or decision elsewhere.</td>