Subject: [Webpush] Per-client subscription resource - 'aggregated subscriptions'

From: Brian Raymor <[email-masked]>
Date: Fri, 7 Aug 2015 00:09:41 +0000

As tracked in https://github.com/webpush-wg/webpush-protocol/issues/41, subscription aggregation has been
requested multiple times on the mailing list. Further details and scenarios are in the issue, which I'll not reiterate here.

Following the webpush meeting at IETF93, a few of us (Costin, Darshak, Elio, Martin, Peter, and I) had conversations
about the shape of such a feature.

I've outlined the basic changes (see bullet points below) to webpush-protocol-00. Note that the list of changes is not intended
to be exhaustive. It's the minimal set of information to start the discussion in the WG. If we reach consensus in the future,
then I'll create a more complete pull request for review.

This feature is optional for a push service to implement.

2.1.  HTTP Resources

* Add push message subscription set

   push message subscription set:  This resource provides read and delete
      access for a set of message subscriptions.  A link relation
      of type "urn:ietf:params:push:subscriptions" identifies a push
      message subscription set.

3.  Subscribing for Push Messages

   A user agent sends a POST request to its configured push service
   resource to create a new subscription.

   POST /subscribe/ HTTP/1.1
   Host: push.example.net

* Each subscription response MAY include a urn:ietf:params:push:subscriptions link relation. If included, the push service supports subscription aggregation. 
* The push service MAY return new subscription sets in response to different subscription requests from the same UA. This allows the push service to control the grouping.

   HTTP/1.1 201 Created
   Date: Thu, 11 Dec 2014 23:56:52 GMT
   Link: </p/JzLQ3raZJfFBR0aqvOMsLrt54w4rJUsV>;
           rel="urn:ietf:params:push"
   Link: </receipts/xjTG79I3VuptNWS0DsFu4ihT97aE6UQJ>;
           rel="urn:ietf:params:push:receipt"

* The new subscription set link relation is returned.
   Link: </subscriptions/hard-to-guess>;
           rel="urn:ietf:params:push:subscriptions"

   Location: https://push.example.net/s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx
   Cache-Control: max-age:864000, private

6.  Receiving Push Messages

* The user agent MAY use either the subscription set or individual subscriptions when retrieving messages.
* The user agent MAY poll (Prefer: wait=0) the subscription set or an individual subscription.
* Add an example for subscription sets - GET /subscriptions/hard-to-guess

   HEADERS      [stream 7] +END_STREAM +END_HEADERS
     :method        = GET
     :path          = /subscriptions/hard-to-guess
     :authority     = push.example.net

   PUSH_PROMISE [stream 7; promised stream 4] +END_HEADERS
     :method        = GET
     :path          = /d/qDIYHNcfAIPP_5ITvURr-d6BGtYnTRnk
     :authority     = push.example.net

   HEADERS      [stream 4] +END_HEADERS
     :status        = 200
     date           = Thu, 11 Dec 2014 23:56:56 GMT
     last-modified  = Thu, 11 Dec 2014 23:56:55 GMT
     cache-control  = private
     content-type   = text/plain;charset=utf8
     content-length = 36

* The urn:ietf:params:push link relation is included in the HEADERS to differentiate the source of pushed messages.

     link           = </p/JzLQ3raZJfFBR0aqvOMsLrt54w4rJUsV>;
                        rel="urn:ietf:params:push"

   DATA         [stream 4] +END_STREAM
     iChYuI3jMzt3ir20P8r_jgRR-dSuN182x7iB

7.3.  Subscription Expiration

* A subscription set MAY be assigned a fixed expiration time by the push service similar to individual subscriptions. 
* A push service MAY terminate a subscription set which MUST also result in the termination of its entire set of individual subscriptions.
* A user agent MAY delete a subscription set which MUST result in the deletion of its entire set of individual subscriptions.
* An individual subscription MAY be deleted or terminated. It MUST be removed from its subscription set. 
* Question: Is it desirable to allow empty subscription sets or should the deletion of the last individual subscription also delete the set?
* Question: Is the expiration time for the subscription set specific to the set or related in some way to the individual subscriptions in the set?

8.  Security Considerations

* Update to include considerations for subscription sets

---

From: Martin Thomson <[email-masked]>
Date: Fri, 7 Aug 2015 14:40:30 -0700

> 3.  Subscribing for Push Messages

You didn't mention how the push service knows to correlate two
different subscriptions.  It needs that in order to put the two
subscriptions in the same set.

---

From: Brian Raymor <[email-masked]>
Date: Fri, 7 Aug 2015 23:31:49 +0000

On 7 August 2015 at 2:41, Martin Thomson <[email-masked]> wrote:

> You didn't mention how the push service knows to correlate two different subscriptions.  It needs that in order to put the two subscriptions in the same set.

Good point. In earlier discussions, one proposal was to pass the first subscription resource that was created (as parent) with subsequent subscription requests (children) to provide that common link between the user agent and push service. This allowed the user agent to make the decision to aggregate or not. If it did not pass a parent subscription, then the push service could not aggregate the separate subscriptions. 

My thought was to avoid 'special' properties on the first subscription. The subscription set ensures a clean separation between operations on aggregated and individual subscriptions. For example, the user agent can continue to GET (or poll) and DELETE individual subscriptions - including the first one. 

To enable the current proposal where the push service makes the decision to aggregate, there must be some form of client authentication/identification included with the subscription request in order for a push service to correlate the subscriptions.

Darshak noted this in a previous message:
	I’m not sure how a PS can force a UA to aggregate (unless the PS somehow identifies the client based on authentication/cookie/something-else).

I may be taking it out of context as "something-else", but Benjamin also commented:
	I'm associating one h2 connection as being one UA

---

From: Martin Thomson <[email-masked]>
Date: Fri, 7 Aug 2015 17:44:04 -0700

>         I’m not sure how a PS can force a UA to aggregate (unless the PS somehow identifies the client based on authentication/cookie/something-else).

I think that I would prefer something more explicit.  Having something
explicit would allow the UA to opt out of aggregating.

>         I'm associating one h2 connection as being one UA

That's generally considered a bad idea.  As the basis for an
optimization, maybe, but I wouldn't want to rely on that.

---

From: Benjamin Bangert <[email-masked]>
Date: Sat, 8 Aug 2015 10:32:05 -0700

On Fri, Aug 7, 2015 at 5:44 PM, Martin Thomson <[email-masked]>
wrote:

> >         I’m not sure how a PS can force a UA to aggregate (unless the PS
> somehow identifies the client based on
> authentication/cookie/something-else).
>

I'm not in favor of anything allowing a UA to opt out of aggregating.
Aggregating is a necessary server resource issue, the client should not be
able to choose additional ways to impair the server or substantially
increase the cost of running a Push Service.

> optimization, maybe, but I wouldn't want to rely on that.

In what case would a single h2 connection not be a single UA?