From 0ed14c92a67589ab859c4ab7992457f6a9ca1a95 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 14 Nov 2021 20:56:48 +0000 Subject: [PATCH 01/14] MSC3489: Sharing streams of location data --- proposals/3489-location-streaming.md | 128 +++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 proposals/3489-location-streaming.md diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md new file mode 100644 index 0000000000..e6976b17af --- /dev/null +++ b/proposals/3489-location-streaming.md @@ -0,0 +1,128 @@ +# MSC3489 - m.beacon: Sharing streams of location data + +## Problem + +A common communication feature is sharing live location data with other users. +Use cases include helping users find each other and asset tracking. Matrix +doesn't currently provide a way of doing this. + +Therefore, we'd like to provide a way for users to efficiently advertise the +time-limited real-time location of themselves or arbitrary assets to other +users in a room. + +## Proposal + +This MSC adds the ability to publish real-time location beacons to Matrix by +building on MSC3488 (m.location: Extending events with location data). + +We introduce two types of state events to describe beacons: the first contains +the metadata about the beacons advertised by a given user: `m.beacon_info.*`. +As Matrix doesn't yet have a way to stop other users overwriting an event +other than setting its state_key to be the owner's mxid, we work around this +by letting the final part of the event type be a unique ID for the beacon. +(Ideally we would put the unique ID as its `state_key` and flip a bit on the +event to indicate that it can only ever be written by its owner - we may get +this via MSC3414 encrypted state events). + +This lets us track an arbitrary number of beacons per user, and avoids becaon +metadata being duplicated as location data is shared. + +An example `m.beacon_info.*` event is: + +```json +{ + "type": "m.beacon_info.self", + "state_key": "@matthew:matrix.org", + "content": { + "m.beacon_info": { + "description": "The Matthew Tracker", // same as an `m.location` description + "created": 1436829458432, // creation timestamp of the beacon on the client. + "lifetime": 86400000, // how long the beacon will publish for in milliseconds + } + } +} +``` + +Separately, we have the actual location data from the beacon in question +stored in `m.beacon.*` state events. Storing the data as state events +ensures that the current location of a given beacon is trivial to determine +(rather than the client having to back-paginate history). It also gives us +location history where desirable. If history is not wanted, then one can use +data retention policies(e.g. exploding messages) to ensure it does not +accumulate unnecessarily. + +`m.beacon.*` events should be sent every 2 seconds while the location of +the asset is moving. If the asset is not moving, it should be refreshed +every 30 seconds. + +An example `m.beacon.*` event is: + +```json +{ + "type": "m.beacon.self", + "state_key": "@matthew:matrix.org", + "content": { + "m.location": { + "uri": "geo:51.5008,0.1247;u=35", + }, + "m.ts": 1636829458432, + } +} +``` + +The special ID `self` is used to indicate that the beacon describes the +primary asset associated with that mxid (e.g. the whereabouts of its human +user). + +## Encryption + +Location data should be stored end-to-end encrypted for obvious data privacy +reasons - given the beacon data is stored in state events, this should be +achieved by MSC3414. + +## Problems + +By storing a state event for every location datapoint, we put significant +load on servers' state management implementations. Current implementations +may not handle this well. However, semantically, state events provide the +behaviour we need (easy access to current value; persistent state within +a room), hence adopting them for this. + +## Alternatives + +We could behave like MSC3401 and broadcast and announce users' beacons in +`m.beacon_info.*` (similar to MSC3401's `m.calls`), and then send location +data via to-device messages to interested devices. + * Pros: + * Doesn't thrash state resolution by storing new location points every time they change + * Gets you easy E2EE automatically + * Cons: + * designs out historical geo-data use cases + * means you are reinventing the pubsub fan-out routing you get for free with Matrix events + * means you have to reinvent decentralised ACLs to check that the subscribing users are valid + * means new joiners to a room won't even be able to see the most recent location for someone + * MSC1763 data retention lets us control the historical data anyway. + +Alternatively, we could sell location data as normal E2EE messages. However, +clients would have to back-paginate in an unbounded fashion to confidently +say what the various beacons are doing rather than simply fishing it out of +room state. + +Alternatively, we could negotiate a WebRTC data channel using MSC3401 and +stream low-latency geospatial data over the participating devices in the room. +This doesn't give us historical data, however, and requiring a WebRTC stack +is prohibitively complicated for simple clients (e.g. basic IOT devices +reporting spatial telemetry). + +## Security considerations + +Location data is high risk for real-world abuse, especially if stored +unencrypted or persisted. The same security considerations apply as for +`m.location` data in general. + +## Unstable prefix + +`m.beacon_info.*` should be referred to as `org.matrix.msc3489.beacon_info.*` until this MSC lands. +`m.beacon.*` should be referred to as `org.matrix.msc3489.beacon.*` until this MSC lands. +`m.location` should be referred to as `org.matrix.msc3488.location.*` until MSC3488 lands. +`m.ts` should be referred to as `org.matrix.msc3488.ts.*` until MSC3488 lands. From 3d60c962caa249f77b11538d2472205deca982b6 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 14 Nov 2021 21:01:54 +0000 Subject: [PATCH 02/14] clarify description param --- proposals/3489-location-streaming.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index e6976b17af..ee727713ab 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -74,6 +74,10 @@ The special ID `self` is used to indicate that the beacon describes the primary asset associated with that mxid (e.g. the whereabouts of its human user). +The `m.location` section of the `m.beacon.*` event should not include a +`description` field, as this instead resides on the matching +`m.beacon_info.*` state event. + ## Encryption Location data should be stored end-to-end encrypted for obvious data privacy From fde61c18d14cb0a7eb1f7f8425c0c4264a6a2270 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 14 Nov 2021 21:03:44 +0000 Subject: [PATCH 03/14] json5 --- proposals/3489-location-streaming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index ee727713ab..13b7d0c371 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -29,7 +29,7 @@ metadata being duplicated as location data is shared. An example `m.beacon_info.*` event is: -```json +```json5 { "type": "m.beacon_info.self", "state_key": "@matthew:matrix.org", From 9ac2c43e49bad35e99bfba707dfacf96bccc0723 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 14 Nov 2021 21:05:54 +0000 Subject: [PATCH 04/14] bullets --- proposals/3489-location-streaming.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 13b7d0c371..dfb7a7ba2c 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -126,7 +126,7 @@ unencrypted or persisted. The same security considerations apply as for ## Unstable prefix -`m.beacon_info.*` should be referred to as `org.matrix.msc3489.beacon_info.*` until this MSC lands. -`m.beacon.*` should be referred to as `org.matrix.msc3489.beacon.*` until this MSC lands. -`m.location` should be referred to as `org.matrix.msc3488.location.*` until MSC3488 lands. -`m.ts` should be referred to as `org.matrix.msc3488.ts.*` until MSC3488 lands. + * `m.beacon_info.*` should be referred to as `org.matrix.msc3489.beacon_info.*` until this MSC lands. + * `m.beacon.*` should be referred to as `org.matrix.msc3489.beacon.*` until this MSC lands. + * `m.location` should be referred to as `org.matrix.msc3488.location.*` until MSC3488 lands. + * `m.ts` should be referred to as `org.matrix.msc3488.ts.*` until MSC3488 lands. From de4ad14e956dcf881b50f7e8cb9adfd43194f64f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 14 Nov 2021 23:15:10 +0000 Subject: [PATCH 05/14] typos --- proposals/3489-location-streaming.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index dfb7a7ba2c..5f8a124bce 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -94,8 +94,8 @@ a room), hence adopting them for this. ## Alternatives -We could behave like MSC3401 and broadcast and announce users' beacons in -`m.beacon_info.*` (similar to MSC3401's `m.calls`), and then send location +We could behave like MSC3401 and announce users' beacons in +`m.beacon_info.*` (similar to MSC3401's `m.call`), and then send location data via to-device messages to interested devices. * Pros: * Doesn't thrash state resolution by storing new location points every time they change @@ -107,7 +107,7 @@ data via to-device messages to interested devices. * means new joiners to a room won't even be able to see the most recent location for someone * MSC1763 data retention lets us control the historical data anyway. -Alternatively, we could sell location data as normal E2EE messages. However, +Alternatively, we could send location data as normal E2EE messages. However, clients would have to back-paginate in an unbounded fashion to confidently say what the various beacons are doing rather than simply fishing it out of room state. From 834954a1c4831cc9431d06f662dcf6bfc6a9de7c Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 21 Nov 2021 16:46:20 +0100 Subject: [PATCH 06/14] incorporate feedback relax rate requirements spell out that we're ignoring velocity for now --- proposals/3489-location-streaming.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 5f8a124bce..58fd7ba921 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -51,9 +51,11 @@ location history where desirable. If history is not wanted, then one can use data retention policies(e.g. exploding messages) to ensure it does not accumulate unnecessarily. -`m.beacon.*` events should be sent every 2 seconds while the location of -the asset is moving. If the asset is not moving, it should be refreshed -every 30 seconds. +`m.beacon.*` events should be sent at a variable rate which is meaningful for +the use case for the asset being tracked. This rate should not be more +frequent than sending an event every 2 seconds. If the asset is not moving, +the state event should still be refreshed on a regular basis to convey that +information - e.g. every 30 seconds. An example `m.beacon.*` event is: @@ -118,6 +120,10 @@ This doesn't give us historical data, however, and requiring a WebRTC stack is prohibitively complicated for simple clients (e.g. basic IOT devices reporting spatial telemetry). +We could include velocity data as well as displacement data here(especially as +the W3C geolocation API provides it); this has been left for a future MSC in +the interests of avoiding scope creep. + ## Security considerations Location data is high risk for real-world abuse, especially if stored From c0a2f7b7a2fdee4cb94649099da7da324b305004 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 12 Jan 2022 12:57:00 +0200 Subject: [PATCH 07/14] Location streaming tweaks (#3622) * Various tweaks following initial implementation: - switched from `m.beacon.*` state event to `m.becon` reference relationship to original `m.beacon_info.*` - changed `beacon_info` created to `m.ts` - renamed `lifetime` to `timeout` - added `m.asset` `type` --- proposals/3489-location-streaming.md | 81 ++++++++++++++++------------ 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 58fd7ba921..058f1f7b73 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -15,7 +15,7 @@ users in a room. This MSC adds the ability to publish real-time location beacons to Matrix by building on MSC3488 (m.location: Extending events with location data). -We introduce two types of state events to describe beacons: the first contains +We introduce two types of events to describe beacons: the first, a state event, contains the metadata about the beacons advertised by a given user: `m.beacon_info.*`. As Matrix doesn't yet have a way to stop other users overwriting an event other than setting its state_key to be the owner's mxid, we work around this @@ -24,79 +24,91 @@ by letting the final part of the event type be a unique ID for the beacon. event to indicate that it can only ever be written by its owner - we may get this via MSC3414 encrypted state events). -This lets us track an arbitrary number of beacons per user, and avoids becaon +This lets us track an arbitrary number of beacons per user, and avoids beacon metadata being duplicated as location data is shared. An example `m.beacon_info.*` event is: ```json5 { - "type": "m.beacon_info.self", + "type": "m.beacon_info.@matthew:matrix.org", "state_key": "@matthew:matrix.org", "content": { "m.beacon_info": { "description": "The Matthew Tracker", // same as an `m.location` description - "created": 1436829458432, // creation timestamp of the beacon on the client. - "lifetime": 86400000, // how long the beacon will publish for in milliseconds + "timeout": 86400000, // how long from the last event until we consider the beacon inactive in milliseconds + }, + "m.ts": 1436829458432, // creation timestamp of the beacon on the client + "m.asset": { + "type": "m.self" // the type of asset being tracked as per MSC3488 } } } ``` Separately, we have the actual location data from the beacon in question -stored in `m.beacon.*` state events. Storing the data as state events -ensures that the current location of a given beacon is trivial to determine -(rather than the client having to back-paginate history). It also gives us -location history where desirable. If history is not wanted, then one can use +as `m.beacon` events forming a reference relationship to the original `m.beacon_info` event. + +Storing the location data as references as opposed to in a state event has multiple advantages: +* Location data is easily encrypted (no dependency on MSC3414) +* Doesn't thrash state resolution by storing new location points every time they change +* Paginated history easily accessible through the `relations` endpoint. If history is not wanted, then one can use data retention policies(e.g. exploding messages) to ensure it does not accumulate unnecessarily. +* Allows other users to request data from a beacon + -`m.beacon.*` events should be sent at a variable rate which is meaningful for +`m.beacon` events should be sent at a variable rate which is meaningful for the use case for the asset being tracked. This rate should not be more frequent than sending an event every 2 seconds. If the asset is not moving, -the state event should still be refreshed on a regular basis to convey that +the location should still be refreshed on a regular basis to convey that information - e.g. every 30 seconds. -An example `m.beacon.*` event is: +An example `m.beacon` event is: -```json +```json5 { - "type": "m.beacon.self", - "state_key": "@matthew:matrix.org", + "type": "m.beacon", + "sender": "@matthew:matrix.org", "content": { + "m.relates_to": { // from MSC2674: https://github.com/matrix-org/matrix-doc/pull/2674 + "rel_type": "m.reference", // from MSC3267: https://github.com/matrix-org/matrix-doc/pull/3267 + "event_id": "$beacon_info" + }, "m.location": { "uri": "geo:51.5008,0.1247;u=35", + "description": "Arbitrary beacon information" }, "m.ts": 1636829458432, } } ``` -The special ID `self` is used to indicate that the beacon describes the -primary asset associated with that mxid (e.g. the whereabouts of its human -user). - -The `m.location` section of the `m.beacon.*` event should not include a -`description` field, as this instead resides on the matching -`m.beacon_info.*` state event. +The `m.location` section of the `m.beacon` event can include an optional +`description` field to provide user facing updates e.g. current address ## Encryption Location data should be stored end-to-end encrypted for obvious data privacy -reasons - given the beacon data is stored in state events, this should be -achieved by MSC3414. - -## Problems - -By storing a state event for every location datapoint, we put significant -load on servers' state management implementations. Current implementations -may not handle this well. However, semantically, state events provide the -behaviour we need (easy access to current value; persistent state within -a room), hence adopting them for this. +reasons - given the beacon data is stored as simple events that will be automatic. ## Alternatives -We could behave like MSC3401 and announce users' beacons in +Initially this MSC considered storing location data in a separate state event but +that had multiple downsides: +* No encryption without MSC3414 +* Difficult access to historical data, timeline pagination required +* State resolution thrasing on every location update. By storing a state event for every location datapoint, +we put significant load on servers' state management implementations. Current implementations +may not handle this well. + +Another option would be using ephemeral data units to broadcast location updates but they +do come with downsides of their own: +* they are not persisted and cannot provide historical data +* there's no per-room API for them +* they are not end to end encrypted + +Alternatively, we could behave like MSC3401 and announce users' beacons in `m.beacon_info.*` (similar to MSC3401's `m.call`), and then send location data via to-device messages to interested devices. * Pros: @@ -133,6 +145,7 @@ unencrypted or persisted. The same security considerations apply as for ## Unstable prefix * `m.beacon_info.*` should be referred to as `org.matrix.msc3489.beacon_info.*` until this MSC lands. - * `m.beacon.*` should be referred to as `org.matrix.msc3489.beacon.*` until this MSC lands. + * `m.beacon` should be referred to as `org.matrix.msc3489.beacon` until this MSC lands. * `m.location` should be referred to as `org.matrix.msc3488.location.*` until MSC3488 lands. * `m.ts` should be referred to as `org.matrix.msc3488.ts.*` until MSC3488 lands. + * `m.asset` should be referred to as `org.matrix.msc3488.asset.*` until MSC3488 lands. From 8eb830c09a225805ee6a545603a96968c569d742 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 25 Jan 2022 14:56:48 +0000 Subject: [PATCH 08/14] split out ephemeral location share to MSC3672 --- proposals/3489-location-streaming.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 058f1f7b73..cb6418ff3d 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -1,4 +1,4 @@ -# MSC3489 - m.beacon: Sharing streams of location data +# MSC3489 - m.beacon: Sharing streams of location data with history ## Problem @@ -8,7 +8,11 @@ doesn't currently provide a way of doing this. Therefore, we'd like to provide a way for users to efficiently advertise the time-limited real-time location of themselves or arbitrary assets to other -users in a room. +users in a room - while by default preserving the history of the location +data in the room by storing it as relational timeline events. + +For purely ephemeral location sharing, see +[MSC3672](https://github.com/matrix-org/matrix-doc/pull/3672) ## Proposal @@ -106,7 +110,8 @@ Another option would be using ephemeral data units to broadcast location updates do come with downsides of their own: * they are not persisted and cannot provide historical data * there's no per-room API for them -* they are not end to end encrypted +* they are not end to end encrypted +However, a privacy-preserving "never store these" approach is still desirable, hence [MSC3672](https://github.com/matrix-org/matrix-doc/pull/3672) Alternatively, we could behave like MSC3401 and announce users' beacons in `m.beacon_info.*` (similar to MSC3401's `m.call`), and then send location From cfd6208616c3694ce897d3c82ed9b576e347ccd8 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 26 Jan 2022 10:02:12 +0200 Subject: [PATCH 09/14] Add persitent location data use cases. --- proposals/3489-location-streaming.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index cb6418ff3d..0f95dc725a 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -11,13 +11,24 @@ time-limited real-time location of themselves or arbitrary assets to other users in a room - while by default preserving the history of the location data in the room by storing it as relational timeline events. +The rationale for persisting location data is to support the use cases of: + +* Publishing things like Strava-style exercise data +* Bridging to things like ADS-B sources for sharing plane flight path data. +* Logistics use cases where you want to track where your fleet of vehicles/ships +has been, or the packages within them +* Supporting scenarios where you're trying to rendezvous with someone/something +which will be aided by seeing their historical whereabouts (e.g. search-and-rescue +operations; enhanced Find-my-iPhone style use cases). + For purely ephemeral location sharing, see [MSC3672](https://github.com/matrix-org/matrix-doc/pull/3672) ## Proposal This MSC adds the ability to publish real-time location beacons to Matrix by -building on MSC3488 (m.location: Extending events with location data). +building on [MSC3488](https://github.com/matrix-org/matrix-doc/pull/3488) +(m.location: Extending events with location data). We introduce two types of events to describe beacons: the first, a state event, contains the metadata about the beacons advertised by a given user: `m.beacon_info.*`. From b402c8404c19ba7e6abb236685e4c36107713be0 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 3 May 2022 10:48:10 +0100 Subject: [PATCH 10/14] Remove variable event types; clarifications * Clarify that this proposal includes history - see MSC3672 for EDUs * Note dependency on MSC3267 for reference relationships * Remove variable event_type - instead use state_key * Propose state_key prefixes inspired by MSC3757 and MSC3779 * Update links to matrix-spec-proposals * Clarify how to stop sharing, and when a share is stopped * Mention the need for redactions to work * Clarify the use of milliseconds for all timing * Mention implementations --- proposals/3489-location-streaming.md | 476 ++++++++++++++++++++++----- 1 file changed, 385 insertions(+), 91 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 0f95dc725a..3bfdcfc84b 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -15,63 +15,109 @@ The rationale for persisting location data is to support the use cases of: * Publishing things like Strava-style exercise data * Bridging to things like ADS-B sources for sharing plane flight path data. -* Logistics use cases where you want to track where your fleet of vehicles/ships -has been, or the packages within them -* Supporting scenarios where you're trying to rendezvous with someone/something -which will be aided by seeing their historical whereabouts (e.g. search-and-rescue -operations; enhanced Find-my-iPhone style use cases). +* Logistics use cases where you want to track where your fleet of + vehicles/ships has been, or the packages within them +* Supporting scenarios where you're trying to rendezvous with someone/something + which will be aided by seeing their historical whereabouts (e.g. + search-and-rescue operations; enhanced Find-my-iPhone style use cases). For purely ephemeral location sharing, see -[MSC3672](https://github.com/matrix-org/matrix-doc/pull/3672) +[MSC3672](https://github.com/matrix-org/matrix-spec-proposals/pull/3672). ## Proposal This MSC adds the ability to publish real-time location beacons to Matrix by -building on [MSC3488](https://github.com/matrix-org/matrix-doc/pull/3488) -(m.location: Extending events with location data). +building on +[MSC3488](https://github.com/matrix-org/matrix-spec-proposals/pull/3488), +which allows sharing of single static locations via the `m.location` event +type. -We introduce two types of events to describe beacons: the first, a state event, contains -the metadata about the beacons advertised by a given user: `m.beacon_info.*`. -As Matrix doesn't yet have a way to stop other users overwriting an event -other than setting its state_key to be the owner's mxid, we work around this -by letting the final part of the event type be a unique ID for the beacon. -(Ideally we would put the unique ID as its `state_key` and flip a bit on the -event to indicate that it can only ever be written by its owner - we may get -this via MSC3414 encrypted state events). +We introduce two types of event to describe beacons: -This lets us track an arbitrary number of beacons per user, and avoids beacon -metadata being duplicated as location data is shared. +* **`m.beacon_info`**: a single state event containing metadata about this + beacon (e.g. how long it will remain live). -An example `m.beacon_info.*` event is: +* **`m.beacon`**: multiple message events containing the actual locations at + various times. All of the `m.beacon` events refer to the original + `m.beacon_info`. + +### `m.beacon_info` - "I am going to share live location" + +An example `m.beacon_info` event is: ```json5 { - "type": "m.beacon_info.@matthew:matrix.org", - "state_key": "@matthew:matrix.org", - "content": { - "m.beacon_info": { - "description": "The Matthew Tracker", // same as an `m.location` description - "timeout": 86400000, // how long from the last event until we consider the beacon inactive in milliseconds - }, - "m.ts": 1436829458432, // creation timestamp of the beacon on the client - "m.asset": { - "type": "m.self" // the type of asset being tracked as per MSC3488 - } - } + "type": "m.beacon_info", + "state_key": "@matthew:matrix.org", + "content": { + "description": "The Matthew Tracker", + "live": true, + "m.ts": 1436829458432, + "timeout": 86400000, + "m.asset": { "type": "m.self" } + } } ``` -Separately, we have the actual location data from the beacon in question -as `m.beacon` events forming a reference relationship to the original `m.beacon_info` event. +`description` is the same as an `m.location` description +([MSC3488](https://github.com/matrix-org/matrix-spec-proposals/pull/3488)). + +`live` should be true when a user starts sharing location. + +`m.ts` is the time when location sharing started, in milliseconds since the +epoch. + +`timeout` is the length of time in milliseconds that the location will be live. +So the location will stop being shared at `m.ts` + `timeout` milliseconds since +the epoch. + +`m.asset` identifies the type of asset being tracked as per +[MSC3488](https://github.com/matrix-org/matrix-spec-proposals/pull/3488). + +#### `state_key` of `m.beacon_info` -Storing the location data as references as opposed to in a state event has multiple advantages: -* Location data is easily encrypted (no dependency on MSC3414) -* Doesn't thrash state resolution by storing new location points every time they change -* Paginated history easily accessible through the `relations` endpoint. If history is not wanted, then one can use -data retention policies(e.g. exploding messages) to ensure it does not -accumulate unnecessarily. -* Allows other users to request data from a beacon +The `state_key` of the `m.beacon_info` identifies the beacon. It must start +with the mxid of the sender, and if it contains more characters, the first +character after the mxid must be underscore, to match +[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) and +[MSC3779](https://github.com/matrix-org/matrix-spec-proposals/pull/3779). +If `state_key` exactly equals the sender's mxid, then the current Matrix spec +prevents anyone else from overwriting the state from this event. If `state_key` +contains further characters, that protection will not apply until +[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) (or +some equivalent mechanism) is available. + +Obviously, if the `state_key` always equals the sender's mxid, each user can +only share a single beacon in each room at any time. We recommend that clients +work in this mode until +[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) is +available. + +To allow multiple beacons per user (e.g. one per device), we use a `state_key` +of mxid plus underscore, and an identifier. For example: + +```json5 +{ + "type": "m.beacon_info", + "state_key": "@matthew:matrix.org_46583241", // inspired by MSC3757 + "content": { + "description": "Matthew's other phone", + "live": true, + "m.ts": 1436829458432, + "timeout": 86400000, + "m.asset": { "type": "m.self" } + } +} +``` + +We recommend clients do not use this style of `state_key` until +[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) is available. + +### `m.beacon` - "I am here" + +The actual location data is sent in `m.beacon` events, which have a reference +relationship to the original `m.beacon_info` event. `m.beacon` events should be sent at a variable rate which is meaningful for the use case for the asset being tracked. This rate should not be more @@ -83,72 +129,226 @@ An example `m.beacon` event is: ```json5 { - "type": "m.beacon", - "sender": "@matthew:matrix.org", - "content": { - "m.relates_to": { // from MSC2674: https://github.com/matrix-org/matrix-doc/pull/2674 - "rel_type": "m.reference", // from MSC3267: https://github.com/matrix-org/matrix-doc/pull/3267 - "event_id": "$beacon_info" - }, - "m.location": { - "uri": "geo:51.5008,0.1247;u=35", - "description": "Arbitrary beacon information" - }, - "m.ts": 1636829458432, - } + "type": "m.beacon", + "sender": "@matthew:matrix.org", + "content": { + "m.relates_to": { + "rel_type": "m.reference", + "event_id": "$beacon_info_event_id" + }, + "m.location": { + "uri": "geo:51.5008,0.1247;u=35", + "description": "Arbitrary beacon information" + }, + "m.ts": 1636829458432, + } } ``` -The `m.location` section of the `m.beacon` event can include an optional -`description` field to provide user facing updates e.g. current address +`m.relates_to` is a reference relationship +([MSC3267](https://github.com/matrix-org/matrix-spec-proposals/pull/3267)). +The `event_id` is the ID of the `m.beacon_info` event emitted when the user +started this live share. + +`m.location` is identical to the `m.location` section of the `m.location` event +type in [MSC3488](https://github.com/matrix-org/matrix-spec-proposals/pull/3488). As such, +it must contain a `uri` field with an RFC5870 `geo:` URI. It can contain an +optional `description` field to provide user-facing updates e.g. the current +address of this location. + +`m.ts` is the time in milliseconds since the epoch when the location was +measured. + +### Stopping sharing + +To stop sharing, the client should emit an additional `m.beacon_info` +event that is identical to the first, except with `live: false`. + +The client that initiated a share should stop sharing if: + +* the timeout on a live share has expired, or +* the user requested to stop sharing, or +* the user revoked permissions on their device to share location. + +For example: + +```json5 +{ + "type": "m.beacon_info", + "state_key": "@matthew:matrix.org_46583241", + "content": { + "description": "Matthew's other phone", + "live": false, // Stop sharing + "m.ts": 1436829458432, + "timeout": 86400000, + "m.asset": { "type": "m.self" } + } +} +``` + +### Deciding which shared locations are live + +A location share is "live" if the sender is currently sharing their location. + +Client apps will often want to determine two related but different pieces of +information about the shares in a room: + +1. Which location shares are live +2. How to display a single location share event (e.g. in a timeline) + +#### Which locations shares are live + +To determine who is currently sharing their location in a room, clients should +examine the room state for events of type `m.beacon_info`. + +For each `m.beacon_info` event in the room state, it is live if: + +* `live` is `true`, and +* `m.ts + timeout < now_ts` where `now_ts` is the current time in milliseconds + since the epoch. + +Otherwise it is not live. + +#### How to display a single location share event + +For clients with timelines, we expect that a map or similar will appear in the +timeline whenever a `m.beacon_info` event with `live: true` is sent, and +related `m.beacon` events will cause that map to update. Stopping sharing +(sending a `m.beacon_info` event with `live: false`) might not create any new +visible item in the timeline. + +For a map on a timeline associated with an initial `m.beacon_info`, to +determine whether that map is "live", clients should: + +* look in the room state for an `m.beacon_info` event with the same + `state_key`, and +* follow the rules in the previous section ("Which location shares are live"). + +### Redacting shared locations + +Because location information is private, it is vital that people are able to +delete information that they no longer want to reveal, or that was +inadvertantly posted to the wrong room. + +We expect that clients will provide a single UI element that redacts all events +for a live sharing session. This includes the original `m.beacon_info` event, +all `m.beacon` events related to it, and any additional `m.beacon_info` event +sent to stop sharing. + +Redaction should be done in the normal way, using the `redact` API as specified +in section +[7.9 Redactions](https://spec.matrix.org/v1.2/client-server-api/#redactions) of +the Client-Server API. + +## Permission to share location + +Since the `m.beacon_info` event is a state event, users who wish to share their +live location will need permission to send state events. By default, users with +power level 50 are able to send state events. + +To allow all users to send `m.beacon_info` events, the room's power levels +should be set to something like this: -## Encryption +```json5 +{ + "state_key": "", + "type": "m.room.power_levels", + "content": { + "events": { + "m.beacon_info": 0, + ... + }, + ... + }, + ... +} +``` -Location data should be stored end-to-end encrypted for obvious data privacy -reasons - given the beacon data is stored as simple events that will be automatic. +This can be done during room creation, or later by sending a new +`m.room.power_levels` state event. + +[MSC3779](https://github.com/matrix-org/matrix-spec-proposals/pull/3779) is intended to +make it easier to send this kind of state event, and the `state_key`s in this +proposal are deliberately designed to take advantage of MSC3779 if it is +standardised. If MSC3779 is available, users with permission to send message +events will automatically have permission to share their live location, because +the `state_key` matches the pattern required to be an "owned" state event. ## Alternatives -Initially this MSC considered storing location data in a separate state event but -that had multiple downsides: -* No encryption without MSC3414 -* Difficult access to historical data, timeline pagination required -* State resolution thrasing on every location update. By storing a state event for every location datapoint, -we put significant load on servers' state management implementations. Current implementations -may not handle this well. - -Another option would be using ephemeral data units to broadcast location updates but they -do come with downsides of their own: -* they are not persisted and cannot provide historical data -* there's no per-room API for them -* they are not end to end encrypted -However, a privacy-preserving "never store these" approach is still desirable, hence [MSC3672](https://github.com/matrix-org/matrix-doc/pull/3672) - -Alternatively, we could behave like MSC3401 and announce users' beacons in -`m.beacon_info.*` (similar to MSC3401's `m.call`), and then send location -data via to-device messages to interested devices. +### Storing location in room state + +Initially this MSC considered storing location data in a separate state event +but that had multiple downsides: + +* No encryption without + [MSC3414](https://github.com/matrix-org/matrix-spec-proposals/pull/3414). +* Difficult access to historical data, timeline pagination required. +* State resolution thrashing on every location update. By storing a state event + for every location datapoint, we put significant load on servers' state + management implementations. Current implementations may not handle this + well. + +Storing the location data as references as opposed to in a state event has +multiple advantages: + +* Location data is easily encrypted (no dependency on + [MSC3414](https://github.com/matrix-org/matrix-spec-proposals/pull/3414)). +* Doesn't thrash state resolution by storing new location points every time + they change. +* Paginated history easily accessible through the `relations` endpoint. If + history is not wanted, then one can use data retention policies (e.g. + exploding messages) to ensure it does not accumulate unnecessarily. +* Allows other users to request data from a beacon. + +### Sending location data using ephemeral data units (EDUs) + +This proposal covers use cases where location data needs to be preserved +in the room timeline. In cases where this is not required, better privacy +may be obtained by sending the `m.beacon` events as EDUs. + +See [MSC3672](https://github.com/matrix-org/matrix-spec-proposals/pull/3672) +for this approach. Note that it depends on user-defined EDUs +([MSC2477](https://github.com/matrix-org/matrix-spec-proposals/pull/2477/)) +and encrypted EDUs +([MSC3673](https://github.com/matrix-org/matrix-spec-proposals/pull/3673)). + +### To-device messages + +We could behave like +[MSC3401](https://github.com/matrix-org/matrix-spec-proposals/pull/3401) and +send location data via to-device messages to interested devices. + * Pros: - * Doesn't thrash state resolution by storing new location points every time they change + * Doesn't thrash state resolution by storing new location points every time + they change * Gets you easy E2EE automatically * Cons: * designs out historical geo-data use cases - * means you are reinventing the pubsub fan-out routing you get for free with Matrix events - * means you have to reinvent decentralised ACLs to check that the subscribing users are valid - * means new joiners to a room won't even be able to see the most recent location for someone + * means you are reinventing the pubsub fan-out routing you get for free with + Matrix events + * means you have to reinvent decentralised ACLs to check that the + subscribing users are valid + * means new joiners to a room won't even be able to see the most recent + location for someone * MSC1763 data retention lets us control the historical data anyway. -Alternatively, we could send location data as normal E2EE messages. However, -clients would have to back-paginate in an unbounded fashion to confidently -say what the various beacons are doing rather than simply fishing it out of -room state. - Alternatively, we could negotiate a WebRTC data channel using MSC3401 and stream low-latency geospatial data over the participating devices in the room. This doesn't give us historical data, however, and requiring a WebRTC stack is prohibitively complicated for simple clients (e.g. basic IOT devices reporting spatial telemetry). -We could include velocity data as well as displacement data here(especially as +### No state events + +We could send location data as normal E2EE messages, with no state events +involved. However, clients would have to back-paginate in an unbounded fashion +to confidently say what the various beacons are doing rather than simply +fishing it out of room state. + +### Including velocity + +We could include velocity data as well as displacement data here (especially as the W3C geolocation API provides it); this has been left for a future MSC in the interests of avoiding scope creep. @@ -158,10 +358,104 @@ Location data is high risk for real-world abuse, especially if stored unencrypted or persisted. The same security considerations apply as for `m.location` data in general. +Normally, locations should only be shared in encrypted rooms, meaning that they +are transferred and stored end-to-end encrypted automatically. + +Clients will probably want to warn users when they request to share location in +an unencrypted room. + +See "Redacting shared locations" above for information about deleting shared +location data. + ## Unstable prefix - * `m.beacon_info.*` should be referred to as `org.matrix.msc3489.beacon_info.*` until this MSC lands. - * `m.beacon` should be referred to as `org.matrix.msc3489.beacon` until this MSC lands. - * `m.location` should be referred to as `org.matrix.msc3488.location.*` until MSC3488 lands. - * `m.ts` should be referred to as `org.matrix.msc3488.ts.*` until MSC3488 lands. - * `m.asset` should be referred to as `org.matrix.msc3488.asset.*` until MSC3488 lands. +Until this MSC lands, the following unstable prefixes should be used: + + * `m.beacon_info` -> `org.matrix.msc3672.beacon_info` + * `m.beacon` -> `org.matrix.msc3672.beacon` + +(Note: these prefixes are shared with MSC3672. If this MSC lands first, MSC3672 +can be updated to use stable prefixes.) + +Until MSC3488 lands, the following unstable prefixes should be used: + + * `m.location` -> `org.matrix.msc3488.location` + * `m.ts` -> `org.matrix.msc3488.ts` + * `m.asset` -> `org.matrix.msc3488.asset` + +Examples of the events with unstable prefixes: + +```json5 +{ + "content": { + "description": "Kylie's live location", + "live": true, + "org.matrix.msc3488.asset": { "type": "m.self" }, + "org.matrix.msc3488.ts": 651066205621, + "timeout": 3600000 + }, + "room_id": "!dypRwVXIkJkTAACHPd:element.io", + "sender": "@kylie:example.com", + "state_key": "@kylie:example.com", + "type": "org.matrix.msc3672.beacon_info", + "event_id": "$TlS7h0NHzBdZIccsSspF5CMpQE8YMT0stRern0nXscI" +} + +``` + +```json5 +{ + "content": { + "m.relates_to": { + "event_id": "$TlS7h0NHzBdZIccsSspF5CMpQE8YMT0stRern0nXscI", + "rel_type": "m.reference" + }, + "org.matrix.msc3488.location": { + "uri": "geo:8.95752746197222,12.494122581370175;u=10" + }, + "org.matrix.msc3488.ts": 651066206460 + }, + "room_id": "!dypRwVXIkJkTAACHPd:element.io", + "sender": "@kylie:example.com", + "type": "org.matrix.msc3672.beacon", + "event_id": "$75FtAIdg9wRTdACcgq4yetaInKlKQKhExYAwMc-qW3Q" +} +``` + +## Related MSCs + +### Dependencies + +* [MSC3267](https://github.com/matrix-org/matrix-spec-proposals/pull/3267): + *Reference relations*. This MSC uses `rel_type: m.reference` from MSC3267, + which in turn builds on + [MSC2674](https://github.com/matrix-org/matrix-spec-proposals/pull/2674): + Event Relationships (which has landed). + +* [MSC3488](https://github.com/matrix-org/matrix-spec-proposals/pull/3488): + *Extending events with location data*. This MSC re-uses the `m.location` + object from MSC3488. + +### MSCs that will enhance this one + +* [MSC3779](https://github.com/matrix-org/matrix-spec-proposals/pull/3779): + *"Owned" State Events*. If MSC3779 lands, normal users will be able to share + their live location without special room permissions. + +* [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757): + *Restricting who can overwrite a state event*. If MSC3757 lands, it will be + safe for users to share multiple live locations with variable `state_keys` + without fear that other users can overwrite their `m.beacon_info`. + +### Related + +* [MSC3672](https://github.com/matrix-org/matrix-spec-proposals/pull/3672): + *Sharing ephemeral streams of location data*. Equivalent of this MSC, but + using ephemeral events, for greater privacy but reduced historical + functionality. + +## Implementations + +Element (Web, Android and iOS) implementations based on this MSC are underway +in April 2022, and feedback from those implementations has been incorporated +into updates of this document. From b98765dc481c7c7bb5a84d1e954f9ff401d6066d Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 3 May 2022 11:47:50 +0100 Subject: [PATCH 11/14] Fix spelling error --- proposals/3489-location-streaming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 3bfdcfc84b..5e1374cd54 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -228,7 +228,7 @@ determine whether that map is "live", clients should: Because location information is private, it is vital that people are able to delete information that they no longer want to reveal, or that was -inadvertantly posted to the wrong room. +inadvertently posted to the wrong room. We expect that clients will provide a single UI element that redacts all events for a live sharing session. This includes the original `m.beacon_info` event, From 09b7793827a3c52d41bfc37f7a77320144b54242 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Wed, 4 May 2022 10:51:26 +0100 Subject: [PATCH 12/14] Add a reference to MSC2244: Mass redactions --- proposals/3489-location-streaming.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 5e1374cd54..4bcfb4ce4d 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -238,7 +238,8 @@ sent to stop sharing. Redaction should be done in the normal way, using the `redact` API as specified in section [7.9 Redactions](https://spec.matrix.org/v1.2/client-server-api/#redactions) of -the Client-Server API. +the Client-Server API. (See also +[MSC2244: Mass redactions](https://github.com/matrix-org/matrix-spec-proposals/pull/2244).) ## Permission to share location From 7ab68f571f51d90fd02f649128b7e0e51198c00f Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Mon, 9 May 2022 10:26:40 +0100 Subject: [PATCH 13/14] Re-word to reflect that mxid_blah is not allowed as a state_key --- proposals/3489-location-streaming.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 4bcfb4ce4d..91f7cfbc72 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -83,10 +83,12 @@ character after the mxid must be underscore, to match [MSC3779](https://github.com/matrix-org/matrix-spec-proposals/pull/3779). If `state_key` exactly equals the sender's mxid, then the current Matrix spec -prevents anyone else from overwriting the state from this event. If `state_key` -contains further characters, that protection will not apply until +prevents anyone else from overwriting the state from this event. Until +`state_key` [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) (or -some equivalent mechanism) is available. +some equivalent mechanism) lands, `state_key` will not be allowed to contain +further characters. After it lands, adding underscore and further characters +will allow one user to create multiple beacons. Obviously, if the `state_key` always equals the sender's mxid, each user can only share a single beacon in each room at any time. We recommend that clients @@ -111,8 +113,9 @@ of mxid plus underscore, and an identifier. For example: } ``` -We recommend clients do not use this style of `state_key` until -[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) is available. +This style of `state_key` will not work (is not allowed) until +[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) is +available. ### `m.beacon` - "I am here" @@ -445,7 +448,7 @@ Examples of the events with unstable prefixes: * [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757): *Restricting who can overwrite a state event*. If MSC3757 lands, it will be - safe for users to share multiple live locations with variable `state_keys` + possible for users to share multiple live locations with variable `state_keys` without fear that other users can overwrite their `m.beacon_info`. ### Related From 99861a90607cb9d9065a06d6d252c777101cc096 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Thu, 19 May 2022 16:06:13 +0100 Subject: [PATCH 14/14] Write up state-event-per-user idea --- proposals/3489-location-streaming.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/proposals/3489-location-streaming.md b/proposals/3489-location-streaming.md index 91f7cfbc72..2858dfae7f 100644 --- a/proposals/3489-location-streaming.md +++ b/proposals/3489-location-streaming.md @@ -343,6 +343,24 @@ This doesn't give us historical data, however, and requiring a WebRTC stack is prohibitively complicated for simple clients (e.g. basic IOT devices reporting spatial telemetry). +### One state event per user + +(As suggested by @deepbluev7) + +To reduce the problem of state bloat (too many state events with different keys) and avoid the need for permission changes on state events, we could post a single state event per user, which contained a list of all the currently-shared location events, and the location events could be normal timeline events, which are updated using message edits (with `m.replace`). + +Advantages: + +* Backwards compatible with static location sharing ([MSC3488](https://github.com/matrix-org/matrix-spec-proposals/pull/3488)) - clients that did not understand live location sharing but did understand static would see the location changing over time due to the edits. +* Only one state event per user - less state bloat. +* No need for changes to the rules about who can modify state events (but still requires the ability for unprivileged users to create a state event with `state_key` equal to their mxid). + +Disadvantages + +* Potential race where multiple clients update the same state event at the same time, and one overwrites the other. +* Location events need to be fetched from the timeline before they can be used. +* Potential confusion - a live location is semantically different from a static location that has been edited. + ### No state events We could send location data as normal E2EE messages, with no state events