@@ -378,6 +378,8 @@ An aggregatable report is a [=struct=] with the following items:
378
378
:: A [=string=] or null
379
379
: <dfn>filtering ID max bytes</dfn>
380
380
:: A positive integer
381
+ : <dfn>max contributions</dfn>
382
+ :: A positive integer
381
383
: <dfn>queued</dfn>
382
384
:: A [=boolean=]
383
385
@@ -410,6 +412,8 @@ items:
410
412
:: A [=string=] or null
411
413
: <dfn>filtering ID max bytes</dfn> (default: [=default filtering ID max bytes=] )
412
414
:: A positive integer
415
+ : <dfn>max contributions</dfn> (default: null)
416
+ :: A positive integer or null
413
417
414
418
</dl>
415
419
@@ -466,10 +470,15 @@ controls which [=origins=] are valid [=aggregation coordinators=]. Every
466
470
<dfn>Default aggregation coordinator</dfn> is an [=aggregation coordinator=]
467
471
that controls which is used for a report if none is explicitly selected.
468
472
469
- <dfn>Maximum report contributions</dfn> is a [=map=] from [=context type=] to
470
- positive integers. Semantically, it defines the maximum number of contributions
471
- that can be present in a single report for every kind of calling context, e.g.
472
- Shared Storage.
473
+ <dfn>Maximum maxContributions</dfn> is a positive integer that defines an upper
474
+ bound on the number of contributions per [=aggregatable report=] .
475
+
476
+ <dfn>Default maxContributions by API</dfn> is a [=map=] from [=context types=]
477
+ to positive integers. Semantically, it defines the default number of
478
+ contributions per report for every kind of calling context, e.g. Shared Storage.
479
+ The values in this map are used when callers do not specifically request another
480
+ value. Each value in this map must be less than or equal to [=maximum
481
+ maxContributions=] .
473
482
474
483
<dfn>Minimum report delay</dfn> is a non-negative [=duration=] that controls the
475
484
minimum delay to deliver an [=aggregatable report=] .
@@ -569,12 +578,19 @@ steps. They return a [=boolean=]:
569
578
not null, return true.
570
579
1. If |preSpecifiedParams|' [=pre-specified report parameters/filtering ID max
571
580
bytes=] is not the [=default filtering ID max bytes=] , return true.
581
+ 1. If |preSpecifiedParams|' [=pre-specified report parameters/max
582
+ contributions=] is not null, return true.
572
583
1. Return false.
573
584
574
- Note: If a context ID or non-default filtering ID max bytes was specified, a
575
- report is sent, even if there are no contributions or there is insufficent
576
- budget for the requested contributions. See [Protecting against leaks via
577
- the number of reports](#protecting-against-leaks-via-the-number-of-reports).
585
+ Note: It is sometimes necessary to send a 'null report' to conceal the fact that
586
+ there were no contributions. For instance, it's possible that budget, which is
587
+ cross-site data in its own right, was insufficient for the requested
588
+ contributions. Alternatively, the caller might have chosen to make no
589
+ contributions after reading cross-site data. In these kinds of scenarios, the
590
+ absence of a report could reveal cross-site data to the reporting endpoint. See
591
+ [Protecting against leaks via the number of
592
+ reports](#protecting-against-leaks-via-the-number-of-reports).
593
+
578
594
</div>
579
595
580
596
<div algorithm>
@@ -683,6 +699,9 @@ scope</dfn> given a [=pre-specified report parameters=] |params| and a
683
699
filtering ID max bytes=] .
684
700
1. [=Assert=] : |filteringIdMaxBytes| is [=set/contained=] in the [=valid
685
701
filtering ID max bytes range=]
702
+ 1. Let |maxContributions| be |params|' [=pre-specified report parameters/max
703
+ contributions=] .
704
+ 1. [=Assert=] : |maxContributions| is null or greater than zero.
686
705
1. [=map/Set=] [=pre-specified report parameters map=] [|batchingScope|] to
687
706
|params|.
688
707
@@ -718,11 +737,13 @@ null |timeout|:
718
737
1. [=iteration/Break=] .
719
738
1. If |hasProcessedContribution| is false, [=list/append=] |contribution| to
720
739
|mergedContributions|.
740
+ 1. Let |effectiveMaxContributions| be the result of [=determining the max
741
+ contributions=] with |preSpecifiedParams| and |api|.
721
742
1. Let |truncatedContributions| be a new [=list=] .
722
- 1. If |mergedContributions| has a [=list/size=] greater than [=maximum report
723
- contributions=] [|api|] :
724
- 1. [=set/For each=] |n| of [=the exclusive range|the range=] 0 to [=maximum
725
- report contributions=] [|api|] , exclusive:
743
+ 1. If |mergedContributions| has a [=list/size=] greater than
744
+ |effectiveMaxContributions| :
745
+ 1. [=set/For each=] |n| of [=the exclusive range|the range=] 0 to
746
+ |effectiveMaxContributions| , exclusive:
726
747
1. [=set/Append=] |mergedContributions|[|n|] to
727
748
|truncatedContributions|.
728
749
1. Otherwise, set |truncatedContributions| to |mergedContributions|.
@@ -771,7 +792,7 @@ To <dfn>obtain an aggregatable report</dfn> given an [=origin=]
771
792
|reportingOrigin|, a [=context type=] |api|, a [=list=] of
772
793
{{PAHistogramContribution}} s |contributions|, a [=debug details=]
773
794
|debugDetails|, an [=aggregation coordinator=] |aggregationCoordinator|, a
774
- [=pre-specified report parameters=] |preSpecifiedParams|, a [=moment] or null
795
+ [=pre-specified report parameters=] |preSpecifiedParams|, a [=moment= ] or null
775
796
|timeout| and a [=moment=] |currentTime|,
776
797
perform the following steps. They return an [=aggregatable report=] .
777
798
1. [=Assert=] : |reportingOrigin| is a [=potentially trustworthy origin=] .
@@ -799,6 +820,9 @@ perform the following steps. They return an [=aggregatable report=].
799
820
: [=aggregatable report/filtering ID max bytes=]
800
821
:: |preSpecifiedParams|' [=pre-specified report parameters/filtering ID max
801
822
bytes=]
823
+ : [=aggregatable report/max contributions=]
824
+ :: The result of [=determining the max contributions=] with
825
+ |preSpecifiedParams| and |api|.
802
826
: [=aggregatable report/queued=]
803
827
:: false
804
828
1. Return |report|.
@@ -821,6 +845,20 @@ They return a [=moment=].
821
845
822
846
</div>
823
847
848
+ <div algorithm>
849
+ To <dfn>determine the max contributions</dfn> given a [=pre-specified report
850
+ parameters=] |preSpecifiedParams| and a [=context type=] |api|, perform the
851
+ following steps. They return a positive integer.
852
+ 1. Let |maxContributions| be |preSpecifiedParams|' [=pre-specified report
853
+ parameters/max contributions=] .
854
+ 1. If |maxContributions| is null, return [=default maxContributions by
855
+ API=] [|api|] .
856
+ 1. If |maxContributions| is greater than [=maximum maxContributions=] , return
857
+ [=maximum maxContributions=] .
858
+ 1. Return |maxContributions|.
859
+
860
+ </div>
861
+
824
862
Sending reports {#sending-reports}
825
863
----------------------------------
826
864
@@ -1044,8 +1082,7 @@ To <dfn>obtain the plaintext payload</dfn> given an [=aggregatable report=]
1044
1082
|report|, perform the following steps. They return a [=byte sequence=] .
1045
1083
1. Let |payloadData| be a new [=list=] .
1046
1084
1. Let |contributions| be |report|'s [=aggregatable report/contributions=] .
1047
- 1. Let |maxContributions| be
1048
- [=maximum report contributions=] [[=aggregatable report/api=]] .
1085
+ 1. Let |maxContributions| be |report|'s [=aggregatable report/max contributions=] .
1049
1086
1. [=Assert=] : |contributions|' [=list/size=] is not greater than
1050
1087
|maxContributions|.
1051
1088
1. [=iteration/While=] |contributions|' [=list/size=] is less than
@@ -1258,18 +1295,20 @@ However, the number of reports with the given metadata could expose some
1258
1295
cross-site information. To protect against this, the API delays sending reports
1259
1296
by a randomized amount of time to make it difficult to determine whether a
1260
1297
report was sent or not from any particular event. In the case that a
1261
- [=aggregatable report/context ID=] is supplied or a non-default [=aggregatable
1262
- report/filtering ID max bytes=] is specified, the API makes the number of
1263
- reports sent deterministic (sending 'null reports' if necessary -- each
1264
- containing only a contribution with a value of 0 in the payload). Additional
1265
- mitigations may also be possible in the future, e.g. adding noise to the report
1266
- count.
1298
+ [=pre-specified report parameters/context ID=] is supplied, a non-default
1299
+ [=pre-specified report parameters/filtering ID max bytes=] is specified, or a
1300
+ [=pre-specified report parameters/max contributions=] is specified, the API
1301
+ makes the number of reports sent deterministic (sending 'null reports' if
1302
+ necessary — each containing only a contribution with a value of 0 in the
1303
+ payload). Additional mitigations may also be possible in the future, e.g. adding
1304
+ noise to the report count.
1267
1305
1268
1306
### Protecting against leaks via payload size ### {#protecting-against-leaks-via-payload-size}
1269
1307
1270
1308
The length of the payload could additionally expose some cross-site information,
1271
1309
namely how many contributions are included. To protect against this, the payload
1272
1310
is padded to a fixed number of contributions.
1311
+
1273
1312
### Temporary debugging mechanism ### {#temporary-debugging-mechanism}
1274
1313
1275
1314
The {{PrivateAggregation/enableDebugMode()}} method allows for many of the
0 commit comments