matrix-doc/proposals/2974-widgets-re-exchange-ca...

123 lines
7.5 KiB
Markdown

# MSC2974: Widgets: Re-exchange capabilities
Currently [widgets](https://github.com/matrix-org/matrix-doc/pull/2764) are only able to exchange
capabilities during [their initialization](https://github.com/matrix-org/matrix-doc/pull/2764/files#diff-30e79df7a74998ad207dd3894a975fed94daea20a3a955fd11ade7cf7c96b9f0R366-R371).
This can be limiting to some widgets which don't generally require a given capability until much
later in the widget's lifecycle.
This proposal attempts to support these sorts of long-lived widgets by still requiring the early
exchange of capabilities and by altering the specification to allow mid-session capabilities.
For reference, the capabilities exchange is one of the first request/response pairs sent over the
widget API during the widget's initialization. Once the widget has loaded, the client asks the
widget which capabilities it wants - the widget is then expected to reply with said capabilities
request. Normally a widget would not be aware of what capabilities it was approved for (upon
receipt of the widget's request for capabilities the client is meant to prompt the user for
confirmation), however under [MSC2871](https://github.com/matrix-org/matrix-doc/pull/2871) the
widget is more aware of what capabilities it ended up being approved for. After the capabilities
exchange happens, the widget is generally ready to be communicated with normally - this is the
start of a successful "session".
## Proposal
The line "Clients MUST NOT re-negotiate capabilities after the session has been established." is
removed from the specification and instead replaced by the mechanism defined by this proposal.
After a session has been established, a widget can request additional capabilities with a newly
proposed `request_capabilities` `fromWidget` action over the widget API. The shape of this request
looks very much like what the widget would have already sent back to request the initial set of
capabilities:
```json5
{
"api": "fromWidget",
"requestId": "AAABBB",
"widgetId": "CCCDDD",
"action": "request_capabilities",
"data": {
"capabilities": ["m.always_on_screen", "com.example.cap"]
}
}
```
The client should only prompt the user to approve any additional capabilities that have not been
approved already. The client should only respond with the standardized error response if the widget
is being rate limited or some other programming error has occurred. The client responds to the
widget's request with an acknowledgement (empty `response` object) to avoid the standardized timeout
causing problems with communication.
After the client has prompted the user to approve/deny the additional capabilities, it uses the same
communication structure established by [MSC2871](https://github.com/matrix-org/matrix-doc/pull/2871)
to send over the total list of requested and approved capabilities throughout the session. For example,
if the widget started the session by requesting `com.example.cap.1` and was approved, then when the
widget was later approved for `com.example.cap.2` the client would inform the widget that it was
approved for both 1 and 2.
This MSC does not currently allow clients to decline capabilities which were already approved. There
does not appear to be a use case for this at the moment, and the client retains control over ending
the session if it believes the widget is abusive/malicious (widgets cannot end a session, but a client
can under the current spec).
As a result, clients should not reconfirm already-approved capabilities with the user. The client
might still show the already-approved capabilities to give additional context to the user.
If the widget has made a mistake and requested no new capabilities then the user should not be prompted
and the widget should be reminded of it's capabilities using [MSC2871](https://github.com/matrix-org/matrix-doc/pull/2871).
This implies that the original `request_capabilities` request is also successful and does not result in
an error response. The widget can still be rate limited for making repeated mistakes.
Much like the initial capabilities exchange, the client is permitted to approve capabilities which
"make sense" for the widget without informing the user. Such examples include conference call widgets
which ask to remain on screen: the client can (and probably should) auto-approve this capability.
Widgets which expect their capabilities to be automatically approved are generally encouraged to make
the request while the session is being established rather than with a secondary capabilities request,
however. Typically widgets which would have their capabilities auto-approved will not need to add
extra traffic to the session and can instead get the request out of the way early.
For the purposes of MSCs and functionality which require behaviour if the capabilities were approved
(such as sending events from client to widget), this MSC implies that the defined behaviour starts
once the widget is approved for the relevant capabilities. For example, if the widget starts by asking
for all message events sent to it and later requests room name state events to be sent too, both
would be sent to the widget (assuming the user approved both requests).
## Potential issues
This could result in excessive popups to users as widgets request the bare minimum as they need it.
Widgets are encouraged to avoid being rate limited by requesting capabilities in bulk where possible.
Widgets should note that clients might be more strict on rate limits when user interaction is involved
to ensure that the user experience is not damaged by a widget.
Repeated permissions prompts may help promote a user experience where end users do not read the
capabilities being requested and automatically approve them, such as is common with presenting terms of
service to typical users. Generally speaking, the first permissions prompt will be read by users as
a sort of "wait a minute, what is going on" response however secondary prompts may result in the user
clicking the 'Approve All' button. Clients are encouraged to perform user testing and alter their
design as needed to avoid this scenario.
## Alternatives
The widget could request a whole other session to be established, however this is overly disruptive
to the communications channel that the client and widget will have established. Similarly, widgets
could present dialogs to the user to request that the user reload the widget to establish a new
session. It is believed that these are overly disruptive to the user experience.
## Security considerations
As already mentioned, typical rate limit issues arise when arbitrary widgets can request information
from the user, particularly in popup form.
Also as already mentioned, users may be inclined to approve secondary requests without reviewing the
actual request. This could lead to a widget appearing innocent by requesting very few capabilities and
following that up later with many more capabilities. Clients are encouraged to try and avoid this.
A third risk is that the widget might repeatedly request declined capabilities until it annoys the
user into accepting them. This sort of behaviour should result in a rate limit response or the client
continually denying the widget's capabilities request on behalf of the widget.
## Unstable prefix
Until this MSC is in a release version of the specification, implementations should use `org.matrix.msc2974`
in the `supported_versions` request/response to detect support. The `action` becomes
`org.matrix.msc2974.request_capabilities` under this convention - the capabilities return defined by MSC2871
is unchanged.