@@ -131,6 +131,7 @@ interface PrivateAggregation {
131
131
dictionary PAHistogramContribution {
132
132
required bigint bucket;
133
133
required long value;
134
+ bigint filteringId = 0;
134
135
};
135
136
136
137
dictionary PADebugModeOptions {
@@ -168,12 +169,22 @@ are:
168
169
1. If |contribution|["{{PAHistogramContribution/value}}"] is negative,
169
170
[=exception/throw=] a {{RangeError}} .
170
171
1. Let |scopingDetails| be [=this=] 's [=PrivateAggregation/scoping details=] .
172
+ 1. Let |batchingScope| be the result of running |scopingDetails|' [=scoping
173
+ details/get batching scope steps=] .
174
+ 1. Let |filteringIdMaxBytes| be the [=default filtering ID max bytes=] .
175
+ 1. If [=pre-specified report parameters map=] [|batchingScope|] [=map/exists=] :
176
+ 1. Set |filteringIdMaxBytes| to [=pre-specified report parameters
177
+ map=] [|batchingScope|] 's [=pre-specified report parameters/filtering ID
178
+ max bytes=] .
179
+ 1. If |contribution|["{{PAHistogramContribution/filteringId}}"] is not [=set/
180
+ contained=] in [=the exclusive range|the range=] 0 to
181
+ 256<sup> |filteringIdMaxBytes|</sup> , exclusive, [=exception/throw=] a
182
+ {{RangeError}} .
171
183
1. Let |entry| be a new [=contribution cache entry=] with the items:
172
184
: [=contribution cache entry/contribution=]
173
185
:: |contribution|
174
186
: [=contribution cache entry/batching scope=]
175
- :: The result of running |scopingDetails|' [=scoping details/get batching
176
- scope steps=] .
187
+ :: |batchingScope|
177
188
: [=contribution cache entry/debug scope=]
178
189
:: The result of running |scopingDetails|' [=scoping details/get debug scope
179
190
steps=] .
@@ -349,6 +360,8 @@ An aggregatable report is a [=struct=] with the following items:
349
360
:: An [=aggregation coordinator=]
350
361
: <dfn>context ID</dfn>
351
362
:: A [=string=] or null
363
+ : <dfn>filtering ID max bytes</dfn>
364
+ :: A positive integer
352
365
: <dfn>queued</dfn>
353
366
:: A [=boolean=]
354
367
@@ -379,6 +392,8 @@ items:
379
392
<dl dfn-for="pre-specified report parameters">
380
393
: <dfn>context ID</dfn> (default: null)
381
394
:: A [=string=] or null
395
+ : <dfn>filtering ID max bytes</dfn> (default: [=default filtering ID max bytes=] )
396
+ :: A positive integer
382
397
383
398
</dl>
384
399
@@ -413,6 +428,18 @@ The user agent may expose controls that allow the user to delete data from the
413
428
[=contribution cache=] , the [=debug scope map=] and the [=pre-specified report
414
429
parameters map=] .
415
430
431
+ Constants {#constants}
432
+ ======================
433
+
434
+ <dfn>Default filtering ID max bytes</dfn> is a positive integer controlling the
435
+ max bytes used if none is explicitly chosen. Its value is 1.
436
+
437
+ <dfn>Valid filtering ID max bytes range</dfn> is a [=set=] of positive integers
438
+ controlling the allowable values of max bytes. Its value is [=the inclusive
439
+ range|the range=] 1 to 8, inclusive.
440
+
441
+ Issue: Consider adding more constants.
442
+
416
443
[=Implementation-defined=] values {#implementation-defined-values}
417
444
==================================================================
418
445
@@ -510,12 +537,14 @@ To <dfn>determine if a report should be sent deterministically</dfn> given a
510
537
steps. They return a [=boolean=] :
511
538
1. If |preSpecifiedParams|' [=pre-specified report parameters/context ID=] is
512
539
not null, return true.
540
+ 1. If |preSpecifiedParams|' [=pre-specified report parameters/filtering ID max
541
+ bytes=] is not the [=default filtering ID max bytes=] , return true.
513
542
1. Return false.
514
543
515
- Note: If a context ID was specified, a report is sent, even if there are no
516
- contributions or there is insufficent budget for the requested
517
- contributions. See [Protecting against leaks via the number of
518
- reports](#protecting-against-leaks-via-the-number-of-reports).
544
+ Note: If a context ID or non-default filtering ID max bytes was specified, a
545
+ report is sent, even if there are no contributions or there is insufficent
546
+ budget for the requested contributions. See [Protecting against leaks via
547
+ the number of reports](#protecting-against-leaks-via-the-number-of-reports).
519
548
520
549
To <dfn algorithm export>process contributions for a batching scope</dfn> given
521
550
a [=batching scope=] |batchingScope|, an [=origin=] |reportingOrigin|, a
@@ -598,6 +627,10 @@ scope</dfn> given a [=pre-specified report parameters=] |params| and a
598
627
1. Let |contextId| be |params|' [=pre-specified report parameters/context ID=] .
599
628
1. [=Assert=] : |contextId| is null or |contextId|'s [=string/length=] is not
600
629
larger than 64.
630
+ 1. Let |filteringIdMaxBytes| be |params|' [=pre-specified report parameters/
631
+ filtering ID max bytes=] .
632
+ 1. [=Assert=] : |filteringIdMaxBytes| is [=set/contained=] in the [=valid
633
+ filtering ID max bytes range=]
601
634
1. [=map/Set=] [=pre-specified report parameters map=] [|batchingScope|] to
602
635
|params|.
603
636
@@ -681,6 +714,9 @@ perform the following steps. They return an [=aggregatable report=].
681
714
:: |aggregationCoordinator|
682
715
: [=aggregatable report/context ID=]
683
716
:: |preSpecifiedParams|' [=pre-specified report parameters/context ID=]
717
+ : [=aggregatable report/filtering ID max bytes=]
718
+ :: |preSpecifiedParams|' [=pre-specified report parameters/filtering ID max
719
+ bytes=]
684
720
: [=aggregatable report/queued=]
685
721
:: false
686
722
1. Return |report|.
@@ -909,21 +945,32 @@ To <dfn>obtain the plaintext payload</dfn> given an [=aggregatable report=]
909
945
:: 0
910
946
: {{PAHistogramContribution/value}}
911
947
:: 0
948
+ : {{PAHistogramContribution/filteringId}}
949
+ :: 0
912
950
1. [=list/Append=] |nullContribution| to |contributions|.
913
951
914
952
Note: This padding protects against the number of contributions being leaked
915
953
through the encrypted payload size, see discussion
916
954
[below] (#protecting-against-leaks-via-payload-size).
917
955
1. [=list/iterate|For each=] |contribution| of |report|'s [=aggregatable report/
918
956
contributions=] :
957
+ 1. Let |filteringIdMaxBytes| be |report|'s [=aggregatable report/filtering
958
+ id max bytes=] .
959
+ 1. [=Assert=] : |contribution|["{{PAHistogramContribution/filteringId}}"]
960
+ is [=set/contained=] in [=the exclusive range|the range=] 0 to
961
+ 256<sup> |filteringIdMaxBytes|</sup> , exclusive.
919
962
1. Let |contributionData| be an [=ordered map=] of the following key/value
920
963
pairs:
921
964
: "`bucket`"
922
965
:: The result of [=encoding an integer for the payload=] given
923
- |contribution|["{{PAHistogramContribution/bucket}}"] and 128 .
966
+ |contribution|["{{PAHistogramContribution/bucket}}"] and 16 .
924
967
: "`value`"
925
968
:: The result of [=encoding an integer for the payload=] given
926
- |contribution|["{{PAHistogramContribution/value}}"] and 32.
969
+ |contribution|["{{PAHistogramContribution/value}}"] and 4.
970
+ : "`id`"
971
+ :: The result of [=encoding an integer for the payload=] given
972
+ |contribution|[="{{PAHistogramContribution/filteringId}}"] and
973
+ |filteringIdMaxBytes|.
927
974
1. [=list/Append=] |contributionData| to |payloadData|.
928
975
1. Let |payload| be an [=ordered map=] of the following key/value pairs:
929
976
: "`data`"
@@ -953,9 +1000,9 @@ They return a [=byte sequence=] or an error.
953
1000
with |hpkeContext| and |aad|.
954
1001
955
1002
To <dfn>encode an integer for the payload</dfn> given an integer |intToEncode|
956
- and an integer |bitLength |, return the representation of |intToEncode| as a
957
- big-endian [=byte sequence=] of length |bitLength| / 8 , left padding with zeroes
958
- as necessary.
1003
+ and an integer |byteLength |, return the representation of |intToEncode| as a
1004
+ big-endian [=byte sequence=] of length |byteLength| , left padding with zeroes as
1005
+ necessary.
959
1006
960
1007
To <dfn>obtain a report's shared info</dfn> given an [=aggregatable report=]
961
1008
|report|, perform the following steps. They return a [=string=] .
@@ -973,7 +1020,7 @@ To <dfn>obtain a report's shared info</dfn> given an [=aggregatable report=]
973
1020
:: The number of seconds in |scheduledReportTime|, rounded down to the
974
1021
nearest number of whole seconds and [=serialize an integer|serialized=]
975
1022
: "`version`"
976
- :: "`0.1 `"
1023
+ :: "`1.0 `"
977
1024
1. Return the result of [=serializing an infra value to a json string=] given
978
1025
|sharedInfo|.
979
1026
@@ -1038,6 +1085,7 @@ partial interface SharedStorageWorkletGlobalScope {
1038
1085
dictionary SharedStoragePrivateAggregationConfig {
1039
1086
USVString aggregationCoordinatorOrigin;
1040
1087
USVString contextId;
1088
+ [EnforceRange] unsigned long long filteringIdMaxBytes;
1041
1089
};
1042
1090
1043
1091
partial dictionary SharedStorageRunOperationMethodOptions {
@@ -1078,15 +1126,25 @@ steps. They return a [=pre-specified report parameters=], null, or a
1078
1126
{{DOMException}} :
1079
1127
1. If |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"]
1080
1128
does not [=map/exist=] , return null.
1129
+ 1. Let |privateAggregationConfig| be
1130
+ |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"] .
1081
1131
1. Let |contextId| be null.
1082
- 1. If |options| ["{{SharedStorageRunOperationMethodOptions/ privateAggregationConfig}}"] ["{{SharedStoragePrivateAggregationConfig/contextId}}"]
1132
+ 1. If |privateAggregationConfig| ["{{SharedStoragePrivateAggregationConfig/contextId}}"]
1083
1133
[=map/exists=] , set |contextId| to
1084
- |options| ["{{SharedStorageRunOperationMethodOptions/ privateAggregationConfig}}"] ["{{SharedStoragePrivateAggregationConfig/contextId}}"] .
1134
+ |privateAggregationConfig| ["{{SharedStoragePrivateAggregationConfig/contextId}}"] .
1085
1135
1. If |contextId|'s [=string/length=] is greater than 64, return a new
1086
1136
{{DOMException}} with name "`DataError`".
1137
+ 1. Let |filteringIdMaxBytes| be the [=default filtering ID max bytes=] .
1138
+ 1. If |privateAggregationConfig|["{{SharedStoragePrivateAggregationConfig/filteringIdMaxBytes}}"]
1139
+ [=map/exists=] , set |filteringIdMaxBytes| to
1140
+ |privateAggregationConfig|["{{SharedStoragePrivateAggregationConfig/filteringIdMaxBytes}}"] .
1141
+ 1. If |filteringIdMaxBytes| is not [=set/contained=] in the [=valid filtering ID
1142
+ max bytes range=] , return a new {{DOMException}} with name "`DataError`".
1087
1143
1. Return a new [=pre-specified report parameters=] with the items:
1088
1144
: [=pre-specified report parameters/context ID=]
1089
1145
:: |contextId|
1146
+ : [=pre-specified report parameters/filtering ID max bytes=]
1147
+ :: |filteringIdMaxBytes|
1090
1148
1091
1149
The {{WindowSharedStorage}} 's {{WindowSharedStorage/run()}} method steps are
1092
1150
modified in four ways. First, add the following steps just after step 2 ("If
@@ -1282,6 +1340,7 @@ dictionary PASignalValue {
1282
1340
dictionary PAExtendedHistogramContribution {
1283
1341
required (PASignalValue or bigint) bucket;
1284
1342
required (PASignalValue or long) value;
1343
+ bigint filteringId = 0;
1285
1344
};
1286
1345
1287
1346
[Exposed=InterestGroupScriptRunnerGlobalScope, SecureContext]
@@ -1349,9 +1408,16 @@ event, PAExtendedHistogramContribution contribution)</dfn> method steps are:
1349
1408
throw=] a {{TypeError}} .
1350
1409
1. Otherwise, if |contribution|["{{PAHistogramContribution/value}}"] is
1351
1410
negative, [=exception/throw=] a {{TypeError}} .
1411
+ 1. If |contribution|["{{PAExtendedHistogramContribution/filteringId}}"] is
1412
+ not [=set/contained=] in [=the exclusive range|the range=] 0 to
1413
+ 256<sup> [=default filtering ID max bytes=] </sup> , exclusive, [=exception/
1414
+ throw=] a {{TypeError}} .
1352
1415
1353
1416
Issue: Make the error types on validation issues here and above consistent
1354
1417
with {{PrivateAggregation/contributeToHistogram(contribution)}} .
1418
+
1419
+ Note: It is not currently possible to set a non-default filtering ID max
1420
+ bytes for Protected Audience.
1355
1421
1. Let |batchingScope| be null.
1356
1422
1. If |event| [=string/starts with=] "`reserved.`", set |batchingScope| to the
1357
1423
result of running |scopingDetails|' [=scoping details/get batching scope
@@ -1974,7 +2040,10 @@ an <a spec="turtledove">auction config</a> |auctionConfig| and a
1974
2040
:: |bucket|
1975
2041
: {{PAHistogramContribution/value}}
1976
2042
:: |value|
2043
+ : {{PAHistogramContribution/filteringId}}
2044
+ :: 0
1977
2045
2046
+ Issue: Consider allowing the filtering ID to be set here.
1978
2047
1. [=map/For each=] |ig| of the [=user agent=] 's <a spec="turtledove">
1979
2048
interest group set</a> whose
1980
2049
<a spec="turtledove" for="interest group">owner</a> is
@@ -2029,11 +2098,15 @@ following steps. They return a {{PAHistogramContribution}}.
2029
2098
1. Let |value| be |contribution|["{{PAExtendedHistogramContribution/value}}"] .
2030
2099
1. If |value| is a {{PASignalValue}} , set |value| to the result of [=filling in
2031
2100
the signal value=] given |value|, 2<sup> 31</sup> −1 and |leadingBidInfo|.
2032
- 1. Return a new {{PAHistogramContribution}} with the items:
2101
+ 1. Let |filledInContribution| be a new {{PAHistogramContribution}} with the
2102
+ items:
2033
2103
: {{PAHistogramContribution/bucket}}
2034
2104
:: |bucket|
2035
2105
: {{PAHistogramContribution/value}}
2036
2106
:: |value|
2107
+ : {{PAHistogramContribution/filteringId}}
2108
+ :: |contribution|["{{PAExtendedHistogramContribution/filteringId}}"]
2109
+ 1. Return |filledInContribution|.
2037
2110
2038
2111
To <dfn>fill in the signal value</dfn> given a {{PASignalValue}} |value|, an
2039
2112
integer |maxAllowed| and a <a spec="turtledove">leading bid info</a>
@@ -2218,7 +2291,8 @@ However, the number of reports with the given metadata could expose some
2218
2291
cross-site information. To protect against this, the API delays sending reports
2219
2292
by a randomized amount of time to make it difficult to determine whether a
2220
2293
report was sent or not from any particular event. In the case that a
2221
- [=aggregatable report/context ID=] is supplied, the API makes the number of
2294
+ [=aggregatable report/context ID=] is supplied or a non-default [=aggregatable
2295
+ report/filtering ID max bytes=] is specified, the API makes the number of
2222
2296
reports sent deterministic (sending 'null reports' if necessary -- each
2223
2297
containing only a contribution with a value of 0 in the payload). Additional
2224
2298
mitigations may also be possible in the future, e.g. adding noise to the report
0 commit comments