Change:
"AggregateShareReq" is done as follows: where "pk" is the HPKE public key encoded by the collector's HPKE <del> key, "server_role" is "0x02" for the leader and "0x03" for a helper. </del> <ins> key, "server_role" is "0x02" for the leader and "0x03" for a helper, and "agg_share_aad" is a value of type "AggregateShareAad" with its values set from the corresponding fields of the "AggregateShareReq". </ins> The "SealBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration. The collector decrypts these aggregate shares using the opposite process.  Specifically, given an encrypted input share, denoted <del> "enc_share", for a given batch selector, denoted "batch_selector", decryption works as follows: where "sk" is the HPKE secret key, "task_id" is the task ID for the collect request, and "server_role" is the role of the server that sent the aggregate share ("0x02" for the leader and "0x03" for the helper).  The value of "batch_selector" is computed by the Collector from its query and the response to its query: </del> <ins> "enc_share", for a given batch selector, decryption works as follows: where "sk" is the HPKE secret key, "server_role" is the role of the server that sent the aggregate share ("0x02" for the leader and "0x03" for the helper), and "agg_share_aad" is an "AggregateShareAad" message constructed from the task ID in the collect request and a batch selector.  The value of the batch selector used in "agg_share_aad" is computed by the Collector from its query and the response to its query as follows: </ins> For time_interval tasks, the batch selector is the batch interval specified in the query.

Discussion:
This revises the sections dealing with encryption and decryption of input shares and aggregate shares, rewriting the construction of each AAD input to be in terms of RFC 8446-style structs instead of byte string concatenation. This
I squashed this back into two commits and then rebased to fix some conflicts.
NAME would you mind taking a quick look?
Currently, the AAD for input shares is defined as . The variable is narratively introduced in 4.4.1.3 as "the public share sent to each aggregator", referring to a part of the report share. Two implementations interpreted the construction of the AAD differently, as either or a 32-bit length suffix preceding the public share. While it would likely be okay to have a single variable-length byte array in the AAD without a length prefix, as the resulting AAD would still be unambiguous, I think it would be prudent to change this to explicitly include a length prefix, to simplify future changes. We should define new structs for both kinds of AAD strings, and specify that the AAD is the result of encoding the corresponding struct. For example:
Places in DAP-02 is used without a length prefix: Section 4.3.2, in the AAD to . Section 4.4.1.3, in the AAD to . I think all of the places where we might unexpectedly not have a length prefix will live in the info or AAD parameters to or , since I think all other encoding is specified via RFC8446 struct notation. I like the idea of specifying info/AAD values as encodings of an RFC8446 struct, as suggested in the OP: this would be unambiguous, and would lower the odds of regressions if we introduced additional variable-length fields.
I interpreted these sections as including the length prefix. The only section where we definitely can't pass the length prefix is URL, where the VDAF is invoked.
I also support this approach in OP, I think all AAD string should be defined in structs and make it explicit that OpenBase and SealBase takes the encoding of such struct for AAD, that means AAD used in Aggregate share encrypt/decrypt in URL should also have a struct definition.
Regarding the VDAF call, am I right TLS is not specified for the procedure calls with VDAF?

so publicshare can be any type/encoding that VDAF implementation understands, therefore how length of publicshare is passed in the below call doesn't have to be constrained by how AAD is used.
As input to VDAF, is the opaque byte string carried by the , excluding the prefix. Just as , it is decoded as specified by the VDAF in use.
LGTMSolid implementation, and a clear win