Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC1957: Integration manager discovery #1957

Merged
merged 13 commits into from
Aug 26, 2019
167 changes: 167 additions & 0 deletions proposals/1957-integrations-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# MSC1957: Integration manager discovery
turt2live marked this conversation as resolved.
Show resolved Hide resolved

**Note**: this proposal is part of a larger "Integrations API" which has not yet been defined.
See [MSC1956](https://github.com/matrix-org/matrix-doc/pull/1956) for details.

Users should have the freedom to choose which integration manager they want to use in their client, while
also accepting suggestions from their homeserver and client. Clients need to know where to find the different
integration managers and how to contact them.


## Proposal

A single logged in user may be influenced by zero or more integration managers at any given time. Managers
are sourced from the client's own configuration, homeserver discovery information, and the user's personal
account data in the form of widgets. Clients should support users using more than one integration manager
at a given time, although the rules for how this can be handled are defined later in this proposal.

#### Client-configured integration managers
turt2live marked this conversation as resolved.
Show resolved Hide resolved

This is left as an implementation detail. In the case of Riot, this is likely to be part of the existing
`config.json` options, although likely modified to support multiple managers instead of one.

#### Homeserver-configured integration managers

The integration managers suggested by a homeserver are done through the existing
[.well-known](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-well-known-matrix-client) discovery
mechanism. The added optional fields, which should not affect a client's ability to log a user in, are:
```json
{
"m.integrations": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, why a managers key within m.integrations, rather than m.integration_managers ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future expansion is really the only answer I have here. The other thing would be vague and not thought out things like possibly decentralized integrations, whatever that means.

"managers": [
{
"api_url": "https://integrations.example.org",
"ui_url": "https://integrations.example.org/ui"
},
{
"api_url": "https://bots.example.org"
}
]
}
}
```

As shown, the homeserver is able to suggest multiple integration managers through this method. Each manager
must have an `api_url` which must be an `http` or `https` URL. The `ui_url` is optional and if not provided
is the same as the `api_url`. Like the `api_url`, the `ui_url` must be `http` or `https` if supplied.

The `ui_url` is ultimately treated the same as a widget, except that the custom `data` is not present and
turt2live marked this conversation as resolved.
Show resolved Hide resolved
must not be templated here. Variables like `$matrix_display_name` are able to function, however. Integration
managers should never use the `$matrix_user_id` as authoritative and instead seek other ways to determine the
user ID. This is covered by other proposals.

The `api_url` is the URL clients will use when *not* embedding the integration manager, and instead showing
its own purpose-built interface.

Clients should query the `.well-known` information for the homeserver periodically to update the integration
manager settings for that homeserver. The client is not expected to validate or use any other information
contained in the response. Current recommendations are to query the configuration when the client starts up
and every 8 hours after that.
turt2live marked this conversation as resolved.
Show resolved Hide resolved

#### User-configured integration managers

Users can specify integration managers in the form of account widgets. The `type` is to be `m.integration_manager`
and the content would look something similar to:
```json
{
"url": "https://integrations.example.org/ui?displayName=$matrix_display_name",
"data": {
"api_url": "https://integrations.example.org"
}
}
```

The `api_url` in the `data` object is required and has the same meaning as the homeserver-defined `api_url`.
The `url` of the widget is analogous to the `ui_url` from the homeserver configuration above, however normal
widget rules apply here.

The user is able to have multiple integration managers through use of multiple widgets.

#### Display order of integration managers

Clients which have support for integration managers should display at least 1 manager, but should
display multiple via something like tabs. Clients must prefer to display the user's configured
integration managers over any defaults, and if only displaying one manager must pick the first
manager after sorting the `state_key`s of the applicable widgets in lexicographical order. Clients
can additionally display default managers if they so wish, and should preserve the order defined in
the various defaults. If the user has no configured integration managers, the client must prefer
to display one or more of the managers suggested by the homeserver over the managers recommended
by the client.

The client can optionally support a way to entirely disable integration manager support, even if the
user and homeserver have managers defined.

The rationale for having the client prefer to use the user's integration managers first is so that
the user can tailor their experience within Matrix if desired. Similarly, a homeserver may wish to
subject all of their users to the same common integration manager as would be common in some organizations.
The client's own preference is a last ditch effort to have an integration manager available to the
user so they don't get left out.

#### Displaying integration managers

Clients simply open the `ui_url` (or equivalent) in an `iframe` or similar. In the current ecosystem,
integration managers would receive a `scalar_token` to idenitify the user - this is no longer the case
turt2live marked this conversation as resolved.
Show resolved Hide resolved
and instead integration managers must seek other avenues for determining the user ID. Other proposals
cover how to do this in the context of the integrations API.

Integration managers shown in this way must be treated like widgets, regardless of source. In practice
this means exposing the Widget API to the manager and applying necessary scoping to keep the manager
as an account widget rather than a room widget.

#### Discovering a manager by only the domain name

Clients may wish to ask users for a single canonical domain name so they can find the manager to add
turt2live marked this conversation as resolved.
Show resolved Hide resolved
to the user's account transparently. Similar to the .well-known discovery done by servers (and clients
during login), clients which have an integrations domain (eg: "example.org") make a regular HTTPS
turt2live marked this conversation as resolved.
Show resolved Hide resolved
request to `https://example.org/.well-known/matrix/integrations` which returns an object which looks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to sanity check that plural integrations is the right term here... For other .well-known URLs, we have client and server, so this adds integrations to that set.

I suppose .well-known data should answer questions like "For domain [example.com], what do I need to know about the [client|server] API?" Since we refer to this new API surface as the "integrations API" (which is implemented by an "integration manager"), it seems like integrations does indeed follow the existing structure.

It would be wonderful to record these naming style choices alongside the other bits of spec style.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is supposed to be plural here because it's referencing the integrations themselves rather than the manager - the content mentions the manager directly. Theory is that we can have future capability with this endpoint if we ever get around to decentralized bridges/integrations.

like the following:
```json
{
"m.integrations_widget": {
"url": "https://integrations.example.org/ui?displayName=$matrix_display_name",
turt2live marked this conversation as resolved.
Show resolved Hide resolved
"data": {
turt2live marked this conversation as resolved.
Show resolved Hide resolved
"api_url": "https://integrations.example.org"
}
}
}
```

The response should be parsed as JSON. If the endpoint returns an error or is missing the `m.integrations_widget`
property, the client should assume there is no integrations manager running on that domain. The
`m.integrations_widget` is an object which has the exact same format as the account widget for
an integration manager, described above. The client should wrap the object verbatim into the appropriate
account data location.


## Tradeoffs

We could limit the user (and by extension, the homeserver and client) to exactly 1 integration manager
and not worry about tabs or other concepts, however this restricts a user's access to integrations.
In a scenario where the user wants to use widgets from Service A and bots from Service B, they'd
end up switching accounts or clients to gain access to either service, or potentially just give up
and walk away from the problem. Instead of having the user switch between clients, we might as well
support this use case, even if it is moderately rare.

We could also define the integration managers in a custom account data event rather than defining them
as a widget. Doing so just adds clutter to the account data and risks duplicating code in clients as
using widgets gets us URL templating for free (see the section later on in this proposal about account
turt2live marked this conversation as resolved.
Show resolved Hide resolved
widgets for more information).


## Future extensions

Some things which may be desirable in the future are:
* Avatars for the different managers
* Human-readable names for the different managers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it would be very desirable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, but has bikeshed potential I want to avoid here.

* Supporting `ui_url`s targeting specific clients for a more consistent design


## Security considerations

When displaying integration managers, clients should not trust that the input is sanitary. Per the
proposal above, an intergration manager is only permitted to be served from HTTP(S) URIs. A given
turt2live marked this conversation as resolved.
Show resolved Hide resolved
integration manager can still have malicious intent however, and clients should ensure any sandboxing
on the manager is appropriate such that it can communicate with the client, but cannot perform
unauthorized actions. Other URI schemes are just as dangerous and could potentially be allowed by
this proposal - use cases are less defined and desirable for schemes like `file://` and are excluded
by this proposal. They can be added in a future proposal if a use case arises.