Change:
When constructing HPKE contexts, we now include both sender and recipient roles, and the application label also includes the PPM version. I used here because we recently submitted draft-01 of and so the next submitted draft, which would include this change, will be . I also backported the definition of struct HpkeCiphertext from the interop PR because it makes everything tidier and should be non-controversial we can get a head-start on bringing those changes into main.
Fixed, thank you! I also rewrote the relevant paragraph to acknowledge that there's two encrypted input shares and that the leader should examine the HPKE config ID of the one intended for itself. Further, I recall NAME pointing out to me that should this draft get adopted by the WG, we'll reset to something like , so is the more appropriate application label.
There's one more instance of that needs to be changed to . Otherwise, LGTM.

Discussion:
leader's, the second share should be for the first helper, and so on). <del> Encrypted input shares are structured as follows: "aggregator_config_id" is equal to "HpkeConfig.id", where "HpkeConfig" is the key config of the aggregator receiving the input share. "enc" is the HPKE encapsulated key, used by the aggregator to decrypt its input share. "payload" is the encrypted input share. </del> To generate the report, the client begins by sharding its measurement into a sequence of input shares as specified by the VDAF in use.  To encrypt an input share, the client first generates an HPKE I-D.irtf- cfrg-hpke context for the aggregator by running <del> where "pk" is the aggregator's public key, "task_id" is "Report.task_id" and "server_role" is a byte whose value is "0x01" if the aggregator is the leader and "0x00" if the aggregator is the helper. "enc" is the HPKE encapsulated key and "context" is the HPKE context used by the client for encryption.  The payload is encrypted as </del> <ins> where "pk" is the aggregator's public key and "server_role" is the Role of the intended recipient ("0x02" for the leader and "0x03" for the helper).  In general, the info string for computing the HPKE context is suffixed by two bytes, the first of which identifies the role of the sender and the second of which identifies the role of the intended recipient. "enc" is the HPKE encapsulated key and "context" is the HPKE context used by the client for encryption.  The payload is encrypted as </ins> where "input_share" is the aggregator's input share and "nonce" and <del> "extensions" are the corresponding fields of "Report". </del> <ins> "extensions" are the corresponding fields of "Report".  Clients MUST NOT use the same "enc" for multiple reports. </ins> The leader responds to well-formed requests to "[leader]/upload" with status 200 and an empty body.  Malformed requests are handled as

value in more than one report if the leader responds with status 200 and an empty body. <del> The leader responds to requests with out-of-date "HpkeConfig.id" values, indicated by "EncryptedInputShare.config_id", with status 400 and an error of type 'outdatedConfig'.  Clients SHOULD invalidate any cached aggregator "HpkeConfig" and retry with a freshly generated Report.  If this retried report does not succeed, clients MUST abort and discontinue retrying. </del> <ins> The leader responds to requests whose leader encrypted input share uses an out-of-date "HpkeConfig.id" value, indicated by "HpkeCiphertext.config_id", with status 400 and an error of type 'outdatedConfig'.  Clients SHOULD invalidate any cached aggregator "HpkeConfig" and retry with a freshly generated Report.  If this retried report does not succeed, clients MUST abort and discontinue retrying. </ins> The leader MUST ignore any report whose nonce contains a timestamp that falls in a batch interval for which it has received at least one

The "nonce" and "extensions" fields have the same value as those in the report uploaded by the client.  Similarly, the "helper_share" <del> field is the "EncryptedInputShare" from the "Report" whose index in </del> <ins> field is the "HpkeCiphertext" from the "Report" whose index in </ins> "Report.encrypted_input_shares" is equal to the index of "[aggregator]" in the task's aggregator endpoints.  [OPEN ISSUE: We usually only need to send this in the first aggregate request.  Shall

where "sk" is the HPKE secret key, "task_id" is "AggregateReq.task_id" and "server_role" is the role of the server <del> ("0x01" for the leader and "0x00" for the helper). "nonce" and "extensions" are obtained from the corresponding fields in "AggregateSubReq".  If decryption fails, then the sub-response consists of a "decryption error" alert.  [See issue#57.]  Otherwise, the helper handles the request for its plaintext input share "input_share" and updates its state as specified by the PPM protocol. </del> <ins> ("0x02" for the leader and "0x03" for the helper; "0x01", the client role, is used as the sender). "nonce" and "extensions" are obtained from the corresponding fields in "AggregateSubReq".  If decryption fails, then the sub-response consists of a "decryption error" alert. [See issue#57.]  Otherwise, the helper handles the request for its plaintext input share "input_share" and updates its state as specified by the PPM protocol. </ins> After processing all of the sub-requests, the helper encrypts its updated state and constructs its response to the aggregate request.

collector's public key as follows: where "pk" is the HPKE public key encoded by the collector's HPKE key <del> configuration, "task_id" is "AggregateShareReq.task_id" and "server_role" is the role of the server ("0x01" for the leader and "0x00" for the helper).  "agg_share" is the serialized "AggregateShare", and "batch_interval" is obtained from the "AggregateShareReq". </del> <ins> configuration and "task_id" is "AggregateShareReq.task_id". "agg_share" is the serialized "AggregateShare", and "batch_interval" is obtained from the "AggregateShareReq". </ins> This encryption prevents the leader from learning the actual result, as it only has its own share and not the helper's share, which is <del> encrypted for the collector.  The helper responds to the collector with HTTP status 200 OK and a body consisting of the following structure: "collector_hpke_config_id" is "collector_config.id" from the task parameters corresponding to "CollectReq.task_id". "enc" is the HPKE encapsulated key, used by the collector to decrypt the aggregate share. "payload" is an encrypted "AggregateShare". </del> <ins> encrypted for the collector.  The helper responds to the leader with HTTP status 200 OK and a body consisting of an "HpkeCiphertext" where "config_id" is set to the collector's HPKE config ID, "enc" is set to the encapsulated HPKE context "enc" and "ciphertext" is "encrypted_agg_share". </ins> The leader uses the helper's aggregate share response to respond to the collector's collect request (see pa-collect).

the helper's encrypted aggregate share for the batch interval by sending an "AggregateShareReq" to the helper as described in aggregate-share-request.  The leader then computes its own aggregate <del> share by aggregating all of the prepared output shares that fall within the batch interval. </del> <ins> share "agg_share" by aggregating all of the prepared output shares that fall within the batch interval.  Finally, it encrypts it under the collector's HPKE public key as follows: where "pk" is the collector's public key. </ins> When both aggregators' shares are successfully obtained, the leader responds to subsequent HTTP GET requests to the collect job's URI with HTTP status 200 OK and a body consisting of a "CollectResp": <del> "shares" is a vector of "EncryptedAggregateShare"s, as described in aggregate-share-request, except that for the leader's share, the "task_id" and "batch_interval" used to encrypt the "AggregateShare" are obtained from the "CollectReq". </del> <ins> The "encrypted_agg_shares" field is the vector of encrypted aggregate shares.  They MUST appear in the same order as the aggregator endpoints list of the task parameters. </ins> If obtaining aggregate shares fails, then the leader responds to subsequent HTTP GET requests to the collect job URI with an HTTP

where "sk" is the HPKE secret key, "task_id" is "AggregateReq.task_id" and "server_role" is the role of the server <del> that send the aggregate share ("0x01" for the leader and "0x00" for </del> <ins> that sent the aggregate share ("0x02" for the leader and "0x03" for </ins> the helper). "batch_interval" is the "Interval" from the "CollectReq".  The collector then unshards the aggregate shares into an aggregate result using the VDAF's "agg_shares_to_result"