diff --git a/EVENT.md b/EVENT.md index d67a96d103..f49668987c 100644 --- a/EVENT.md +++ b/EVENT.md @@ -1114,9 +1114,27 @@ trying to measure user visits on, the browser can limit the number `destination` sites represented by unexpired sources for a source-site. The browser can place a limit on the number of a source site's unexpired source's -unique `destination` sites. When an attribution source is registered for a site -that is not already in the unexpired sources and a source site is at its limit, -the browser will drop the new source. +unique `destination` sites. Source registrations will accept an optional field +`destination_limit_priority` to allow developers to prioritize the destinations +registered with this source with respect to other destinations for the purpose +of source deactivation. + +```jsonc +{ + ..., // existing fields + "destination_limit_priority": "[64-bit signed integer]" // defaults to 0 if not present +} +``` + +When an attribution source is registered for a site that is not already in the +unexpired sources and a source site is at its limit, the browser will sort the +`destination` sites registered by unexpired sources, including the new source, +by `destination_limit_priority` in descending order and by the registration +time in descending order. The browser will then select the first few +`destination` sites within this limit, and delete pending sources and +aggregatable reports associated with the unselected `destination` sites. Any +event-level reports are not deleted, as the leak of user's browsing history is +mitigated by fake reports within differential privacy. The lower this value, the harder it is for a reporting origin to use the API to try and measure user browsing activity not associated with ads being shown. @@ -1129,6 +1147,9 @@ the [denial of service](#denial-of-service) for more details. To prevent this attack, the browser should maintain these limits per reporting site. This effectively limits the number of unique sites covered per {source site, reporting site} applied to all unexpired sources regardless of type at source time. +The browser can also limit the number of `destination` sites per {source site, reporting site, 1 day} +to mitigate the history reconstruction attack. + #### Limiting the number of unique destinations per source site To further reduce the possibility of a history reconstruction attack, the browser can also limit the number of `destination` sites registered per {source-site, 1 minute}. diff --git a/index.bs b/index.bs index 4a008aecc7..9d3d3676fc 100644 --- a/index.bs +++ b/index.bs @@ -843,6 +843,8 @@ An attribution source is a [=struct=] with the following items: :: Number of [=aggregatable debug reports=] created for this [=attribution source=]. : aggregatable debug reporting config :: An [=aggregatable debug reporting config=]. +: destination limit priority +:: A 64-bit integer. @@ -1064,6 +1066,8 @@ An aggregatable attribution report is an [=aggregatable report=] with :: Null or a [=string=]. : attribution debug info :: An [=attribution debug info=]. +: source identifier +:: A [=string=]. @@ -1094,8 +1098,14 @@ An attribution rate-limit record is a [=struct=] with the following i :: A [=moment=]. : expiry time :: Null or a [=moment=]. -: event-level report ID -:: Null or an [=event-level report=]'s [=event-level report/report ID=]. +: entity ID +:: Null for [=obtain a fake report|fake reports=] or an [=event-level report=]'s [=event-level report/report ID=] or an + [=aggregatable attribution report=]'s [=aggregatable attribution report/report ID=] or an + [=attribution source=]'s [=attribution source/source identifier=]. +: deactivated for unexpired destination limit (default false) +:: A [=boolean=]. +: destination limit priority (default null) +:: Null or a 64-bit integer. @@ -1127,6 +1137,8 @@ Possible values are:
source-channel-capacity-limit
"
source-destination-global-rate-limit
"
source-destination-limit
"
+source-destination-limit-replaced
"
+source-destination-per-day-rate-limit
"
source-destination-rate-limit
"
source-noised
"
source-reporting-origin-limit
"
@@ -1434,6 +1446,11 @@ The second controls the maximum number of distinct [=sites=] across all [=attrib
for [=attribution sources=] with a given ([=attribution source/source site=], [=attribution source/reporting origin=] [=site=])
per [=destination rate-limit window=].
+Max destinations per source reporting site per day is an integer that controls
+the maximum number of distinct [=sites=] across all [=attribution source/attribution destinations=]
+for [=attribution sources=] with a given ([=attribution source/source site=], [=attribution source/reporting origin=] [=site=])
+per day.
+
Max source reporting origins per rate-limit window is a positive
integer that controls the maximum number of distinct
[=attribution source/reporting origin|reporting origins=] for a
@@ -2361,6 +2378,7 @@ A source-registration JSON key is one of the following:
debug_key
"
debug_reporting
"
destination
"
+destination_limit_priority
"
end_times
"
event_level_epsilon
"
event_report_window
"
@@ -2666,6 +2684,10 @@ To parse source-registration JSON given a [=byte sequence=]
[=parse an optional 64-bit signed integer=] with |value|, "[=source-registration JSON key/priority=]
", and
0.
1. If |priority| is an error, return null.
+1. Let |destinationLimitPriority| be the result of running
+ [=parse an optional 64-bit signed integer=] with |value|,
+ "[=source-registration JSON key/destination_limit_priority=]
", and 0.
+1. If |destinationLimitPriority| is an error, return null.
1. Let |filterData| be a new [=filter map=].
1. If |value|["[=source-registration JSON key/filter_data=]
"] [=map/exists=]:
1. Set |filterData| to the result of running [=parse filter data=] with
@@ -2772,6 +2794,8 @@ To parse source-registration JSON given a [=byte sequence=]
:: |aggregatableDebugBudget|
: [=attribution source/aggregatable debug reporting config=]
:: |aggregatableDebugReportingConfig|
+ : [=attribution source/destination limit priority=]
+ :: |destinationLimitPriority|
1. Return |source|.
Issue: Determine proper charset-handling for the JSON header value.
@@ -2812,19 +2836,123 @@ To check if an [=attribution source=] exceeds the time-based destination li
Note: When both limits are hit, we interpret it as "[=destination rate-limit result/hit reporting limit=]
"
for debug reporting.
-To check if an [=attribution source=] exceeds the unexpired destination limit given an
-[=attribution source=] |source|, run the following steps:
+To check if an [=attribution source=] exceeds the per day destination limits
+given an [=attribution source=] |source|, run the following steps:
-1. Let |unexpiredSources| be all [=attribution rate-limit records=] |record| in the [=attribution rate-limit cache=] where all of the following are true:
+1. Let |matchingSources| be all [=attribution rate-limit records=] |record| in the [=attribution rate-limit cache=] where all of the following are true:
* |record|'s [=attribution rate-limit record/scope=] is "[=rate-limit scope/source=]
"
* |record|'s [=attribution rate-limit record/source site=] and |source|'s [=attribution source/source site=] are equal
- * |record|'s [=attribution rate-limit record/reporting origin=] and |source|'s [=attribution source/reporting origin=] are [=same site=]
+ * |record|'s [=attribution rate-limit record/reporting origin=] is [=same site=] with
+ |source|'s [=attribution source/reporting origin=]
* |record|'s [=attribution rate-limit record/expiry time=] is greater than |source|'s [=attribution source/source time=]
-1. Let |unexpiredDestinations| be a new [=set=].
-1. For each [=attribution rate-limit record=] |unexpiredRecord| of |unexpiredSources|:
- 1. [=set/Append=] |unexpiredRecord|'s [=attribution rate-limit record/attribution destination=] to |unexpiredDestinations|.
-1. Let |newDestinations| be the result of taking the [=set/union=] of |unexpiredDestinations| and |source|'s [=attribution source/attribution destinations=].
-1. Return whether |newDestinations|'s [=set/size=] is greater than the user agent's [=max destinations covered by unexpired sources=].
+ * The [=duration from=] |record|'s [=attribution rate-limit record/time=] and |source|'s [=attribution source/source time=]
+ is less than 1 day
+1. Let |destinations| be the [=set=] of all [=attribution rate-limit record/attribution destination=] in |matchingSources|,
+ [=set/union|unioned=] with |source|'s [=attribution source/attribution destinations=].
+1. Return whether |destinations|'s [=set/size=] is greater than [=max destinations per source reporting site per day=].
+
+To delete sources for unexpired destination limit given a [=set=] of
+[=attribution source/source identifiers=] |sourcesToDelete| and a [=moment=] |now|:
+
+1. If |sourcesToDelete| [=set/is empty=], return.
+1. [=set/iterate|For each=] [=attribution source=] |source| of the [=attribution source cache=]:
+ 1. [=set/Remove=] |source| from the [=attribution source cache=] if |sourcesToDelete|
+ [=set/contains=] |source|'s [=attribution source/source identifier=].
+1. Let |deletedEventLevelReports| be a new [=set=].
+1. [=set/iterate|For each=] [=event-level report=] |report| of the [=event-level report cache=]:
+ 1. If |sourcesToDelete| [=set/contains=] |report|'s [=event-level report/source identifier=]
+ and |report|'s [=event-level report/trigger time=] is greater than or equal to |now|:
+ 1. [=set/Append=] |report|'s [=event-level report/report ID=] to |deletedEventLevelReports|.
+ 1. [=set/Remove=] |report| from the [=event-level report cache=].
+1. Let |deletedAggregatableReports| be a new [=set=].
+1. [=set/iterate|For each=] [=aggregatable attribution report=] |report| of the [=aggregatable attribution report cache=]:
+ 1. If |sourcesToDelete| [=set/contains=] |report|'s [=aggregatable attribution report/source identifier=]:
+ 1. [=set/Append=] |report|'s [=aggregatable attribution report/report ID=] to |deletedAggregatableReports|.
+ 1. [=set/Remove=] |report| from the [=aggregatable attribution report cache=].
+1. [=set/iterate|For each=] [=attribution rate-limit record=] |record| of the [=attribution rate-limit cache=]:
+ 1. If |record|'s [=attribution rate-limit record/scope=] is:
+ [=rate-limit scope/source=]
"
+ :: Set |record|'s [=attribution rate-limit record/deactivated for unexpired destination limit=] to
+ true if |sourcesToDelete| [=set/contains=] |record|'s [=attribution rate-limit record/entity ID=].
+ : "[=rate-limit scope/event-attribution=]
"
+ :: [=set/Remove=] |record| from the [=attribution rate-limit cache=] if
+ |deletedEventLevelReports| [=set/contains=] |record|'s [=attribution rate-limit record/entity ID=].
+ : "[=rate-limit scope/aggregatable-attribution=]
"
+ :: [=set/Remove=] |record| from the [=attribution rate-limit cache=] if
+ |deletedAggregatableReports| [=set/contains=] |record|'s [=attribution rate-limit record/entity ID=].
+
+ [=rate-limit scope/source=]
", [=iteration/continue=].
+ 1. If |record|'s [=attribution rate-limit record/deactivated for unexpired destination limit=] is true, [=iteration/continue=].
+ 1. If |record|'s [=attribution rate-limit record/source site=] and |source|'s [=attribution source/source site=] are not equal, [=iteration/continue=].
+ 1. If |record|'s [=attribution rate-limit record/reporting origin=] and |source|'s [=attribution source/reporting origin=] are not [=same site=], [=iteration/continue=].
+ 1. If |record|'s [=attribution rate-limit record/expiry time=] is less than or equal to |source|'s [=attribution source/source time=], [=iteration/continue=].
+ 1. [=Assert=]: |record|'s [=attribution rate-limit record/destination limit priority=] is not null.
+ 1. [=Assert=]: |record|'s [=attribution rate-limit record/entity ID=] is not null.
+ 1. Let |destinationRecord| be a new [=destination limit record=] struct whose items are:
+
+ : [=destination limit record/attribution destination=]
+ :: |record|'s [=attribution rate-limit record/attribution destination=]
+ : [=destination limit record/priority=]
+ :: |record|'s [=attribution rate-limit record/destination limit priority=]
+ : [=destination limit record/time=]
+ :: |record|'s [=attribution rate-limit record/time=]
+ : [=destination limit record/source identifier=]
+ :: |record|'s [=attribution rate-limit record/entity ID=]
+
+ 1. [=list/Append=] |destinationRecord| to |destinationRecords|.
+1. [=set/iterate|For each=] [=site=] |destination| of |source|'s [=attribution source/attribution destinations=]:
+ 1. Let |destinationRecord| be a new [=destination limit record=] struct whose items are:
+
+ : [=destination limit record/attribution destination=]
+ :: |destination|
+ : [=destination limit record/priority=]
+ :: |source|'s [=attribution source/destination limit priority=]
+ : [=destination limit record/time=]
+ :: |source|'s [=attribution source/source time=]
+ : [=destination limit record/source identifier=]
+ :: |record|'s [=attribution source/source identifier=]
+
+ 1. [=list/Append=] |destinationRecord| to |destinationRecords|.
+1. [=list/sort in descending order|Sort=] |destinationRecords| in descending order, with |a| less than |b| if the following steps return true:
+ 1. If |a|'s [=destination limit record/priority=] is less than |b|'s [=destination limit record/priority=], return true.
+ 1. If |a|'s [=destination limit record/priority=] is greater than |b|'s [=destination limit record/priority=], return false.
+ 1. If |a|'s [=destination limit record/time=] is less than |b|'s [=destination limit record/time=], return true.
+ 1. If |a|'s [=destination limit record/time=] is greater than |b|'s [=destination limit record/time=], return false.
+ 1. If |a|'s serialized
+ [=destination limit record/attribution destination=]
+ is less than |b|'s serialized
+ [=destination limit record/attribution destination=], return true.
+ 1. Return false.
+1. Let |sourcesToDelete| be a new [=set=].
+1. Let |newDestinations| be a new [=set=].
+1. [=set/iterate|For each=] [=destination limit record=] |record| of |destinationRecords|:
+ 1. Let |destination| be |record|'s [=destination limit record/attribution destination=].
+ 1. If |newDestinations|'s [=set/size=] is less than the user agent's [=max destinations covered by unexpired sources=],
+ [=set/append=] |destination| to |newDestinations|.
+ 1. Otherwise, if |newDestinations| does not [=set/contain=] |destination|:
+ 1. [=set/Append=] |record|'s [=destination limit record/source identifier=] to |sourcesToDelete|.
+1. Return |sourcesToDelete|.
To check if an [=attribution source=] should be blocked by reporting-origin per site limit given an [=attribution source=] |source|:
@@ -2842,8 +2970,7 @@ a [=trigger state=] |triggerState|:
1. Let |specEntry| be the [=map/entry=] for
|source|'s [=attribution source/trigger specs=][|triggerState|'s [=trigger state/trigger data=]].
-1. Let |triggerTime| be the greatest [=moment=] that is strictly less than
- |triggerState|'s [=trigger state/report window=]'s [=report window/end=].
+1. Let |triggerTime| be |triggerState|'s [=trigger state/report window=]'s [=report window/start=].
1. Let |priority| be 0.
1. Let |fakeReport| be the result of running [=obtain an event-level report=] with |source|,
|triggerTime|, [=obtain an event-level report/triggerDebugKey=] set to null,
@@ -2852,9 +2979,22 @@ a [=trigger state=] |triggerState|:
|triggerState|'s [=trigger state/report window=]'s [=report window/end=].
1. Return |fakeReport|.
+To check if a source debug data type is a verbose debug data type
+given a [=source debug data type=] |dataType|:
+
+1. If |dataType| is:
+ [=source debug data type/source-destination-global-rate-limit=]
"
+ : "[=source debug data type/source-destination-limit-replaced=]
"
+ : "[=source debug data type/source-reporting-origin-limit=]
"
+ :: Return false.
+
+ [=source debug data type/source-destination-global-rate-limit=]
"
- : "[=source debug data type/source-reporting-origin-limit=]
"
- :: Set |dataTypeToReport| to "[=source debug data type/source-success=]
".
+1. Let |dataTypeToReport| be null.
+1. [=set/iterate|For each=] |dataType| of |dataTypes|:
+ 1. Let |effectiveDataType| be |dataType|.
+ 1. If |dataType| is:
+ [=source debug data type/source-destination-global-rate-limit=]
"
+ : "[=source debug data type/source-reporting-origin-limit=]
"
+ :: Set |effectiveDataType| to "[=source debug data type/source-success=]
".
- [=source debug data type/source-success=]
"
- and |isNoised| is true, set |dataTypeToReport| to "[=source debug data type/source-noised=]
".
-1. If |dataTypeToReport| is:
- [=source debug data type/source-destination-limit=]
"
- :: [=map/Set=] |body|["`limit`"] to the user agent's [=max destinations covered by unexpired sources=],
- [=serialize an integer|serialized=].
- : "[=source debug data type/source-destination-rate-limit=]
"
- :: [=map/Set=] |body|["`limit`"] to the user agent's [=max destinations per rate-limit window=][1],
- [=serialize an integer|serialized=].
- : "[=source debug data type/source-storage-limit=]
"
- :: [=map/Set=] |body|["`limit`"] to the user agent's [=max pending sources per source origin=],
- [=serialize an integer|serialized=].
- : "[=source debug data type/source-channel-capacity-limit=]
"
- ::
- 1. Let |sourceType| be |source|'s [=attribution source/source type=].
- 1. [=map/Set=] |body|["`limit`"] to the user agent's [=max event-level channel capacity per source=][|sourceType|].
- : "[=source debug data type/source-trigger-state-cardinality-limit=]
"
- :: [=map/Set=] |body|["`limit`"] to the user agent's [=max trigger-state cardinality=],
- [=serialize an integer|serialized=].
- : "[=source debug data type/source-reporting-origin-per-site-limit=]
"
- :: [=map/Set=] |body|["`limit`"] to the user agent's [=max source reporting origins per source reporting site=],
- [=serialize an integer|serialized=].
+ [=source debug data type/source-success=]
"
+ and |isNoised| is true, set |effectiveDataType| to "[=source debug data type/source-noised=]
".
+ 1. If the result of [=checking if a source debug data type is a verbose debug data type=]
+ is true:
+ 1. [=Assert=]: |dataTypeToReport| is null.
+ 1. Set |dataTypeToReport| to |effectiveDataType|.
+ 1. If |effectiveDataType| is:
+ [=source debug data type/source-destination-limit=]
"
+ :: [=map/Set=] |body|["`limit`"] to the user agent's [=max destinations covered by unexpired sources=],
+ [=serialize an integer|serialized=].
+ : "[=source debug data type/source-destination-limit-replaced=]
"
+ :: [=map/Set=] |body|["`source_destination_limit`"] to the user agent's
+ [=max destinations covered by unexpired sources=], [=serialize an integer|serialized=].
+
+ Note: The "`source_destination_limit`" field may be included to indicate that
+ [=max destinations covered by unexpired sources=] was hit, which is not
+ reported as "[=source debug data type/source-destination-limit=]
" to prevent side-channel
+ leakage of cross-origin data.
+
+ : "[=source debug data type/source-destination-rate-limit=]
"
+ :: [=map/Set=] |body|["`limit`"] to the user agent's [=max destinations per rate-limit window=][1],
+ [=serialize an integer|serialized=].
+ : "[=source debug data type/source-destination-per-day-rate-limit=]
"
+ :: [=map/Set=] |body|["`limit`"] to the user agent's [=max destinations per source reporting site per day=],
+ [=serialize an integer|serialized=].
+ : "[=source debug data type/source-storage-limit=]
"
+ :: [=map/Set=] |body|["`limit`"] to the user agent's [=max pending sources per source origin=],
+ [=serialize an integer|serialized=].
+ : "[=source debug data type/source-channel-capacity-limit=]
"
+ ::
+ 1. Let |sourceType| be |source|'s [=attribution source/source type=].
+ 1. [=map/Set=] |body|["`limit`"] to the user agent's [=max event-level channel capacity per source=][|sourceType|].
+ : "[=source debug data type/source-trigger-state-cardinality-limit=]
"
+ :: [=map/Set=] |body|["`limit`"] to the user agent's [=max trigger-state cardinality=],
+ [=serialize an integer|serialized=].
+ : "[=source debug data type/source-reporting-origin-per-site-limit=]
"
+ :: [=map/Set=] |body|["`limit`"] to the user agent's [=max source reporting origins per source reporting site=],
+ [=serialize an integer|serialized=].
- [=source debug data type/source-success=]
"
- and |isNoised| is true, set |dataTypeToReport| to "[=source debug data type/source-noised=]
".
-1. If |debugDataMap|[|dataTypeToReport|] [=map/exists=]:
- 1. Let |contribution| be a new [=aggregatable contribution=] with items:
- : [=aggregatable contribution/key=]
- :: |debugDataMap|[|dataTypeToReport|]'s [=aggregatable contribution/key=] bitwise-OR
- |config|'s [=aggregatable debug reporting config/key piece=]
- : [=aggregatable contribution/value=]
- :: |debugDataMap|[|dataTypeToReport|]'s [=aggregatable contribution/value=]
- 1. [=list/Append=] |contribution| to |contributions|.
+1. [=set/iterate|For each=] |dataType| of |dataTypes|:
+ 1. Let |dataTypeToReport| be |dataType|.
+ 1. If |dataType| is "[=source debug data type/source-success=]
"
+ and |isNoised| is true, set |dataTypeToReport| to "[=source debug data type/source-noised=]
".
+ 1. If |debugDataMap|[|dataTypeToReport|] [=map/exists=]:
+ 1. Let |contribution| be a new [=aggregatable contribution=] with items:
+ : [=aggregatable contribution/key=]
+ :: |debugDataMap|[|dataTypeToReport|]'s [=aggregatable contribution/key=] bitwise-OR
+ |config|'s [=aggregatable debug reporting config/key piece=]
+ : [=aggregatable contribution/value=]
+ :: |debugDataMap|[|dataTypeToReport|]'s [=aggregatable contribution/value=]
+ 1. [=list/Append=] |contribution| to |contributions|.
1. Run [=obtain and deliver an aggregatable debug report on registration=] with |contributions|,
|source|'s [=attribution source/source site=], |source|'s [=attribution source/reporting origin=],
|source|, |source|'s [=attribution source/attribution destinations=][0],
@@ -2935,13 +3095,13 @@ and a [=boolean=] |isNoised|:
and |source|'s [=attribution source/source time=].
To obtain and deliver debug reports on source registration
-given a [=source debug data type=] |dataType|, an [=attribution source=] |source|,
+given a [=set=] of [=source debug data types=] |dataTypes|, an [=attribution source=] |source|,
and an optional [=boolean=] |isNoised| (default false):
1. Run [=obtain and deliver a verbose debug report on source registration=]
- with |dataType|, |source|, and |isNoised|.
+ with |dataTypes|, |source|, and |isNoised|.
1. Run [=obtain and deliver an aggregatable debug report on source registration=]
- with |dataType|, |source|, and |isNoised|.
+ with |dataTypes|, |source|, and |isNoised|.
To process an attribution source given an [=attribution source=] |source|:
@@ -2957,11 +3117,13 @@ To process an attribution source given an [=attribution source=] |sou
1. Let |epsilon| be |source|'s [=attribution source/event-level epsilon=].
1. Let |channelCapacity| be the result of [=computing the channel capacity of a source=] with |randomizedResponseConfig| and |epsilon|.
1. If |channelCapacity| is an error:
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-trigger-state-cardinality-limit=]
" and |source|.
+ 1. Run [=obtain and deliver debug reports on source registration=] with
+ « "[=source debug data type/source-trigger-state-cardinality-limit=]
" » and |source|.
1. Return.
1. Let |sourceType| be |source|'s [=attribution source/source type=].
1. If |channelCapacity| is greater than [=max event-level channel capacity per source=][|sourceType|]:
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-channel-capacity-limit=]
" and |source|.
+ 1. Run [=obtain and deliver debug reports on source registration=] with
+ « "[=source debug data type/source-channel-capacity-limit=]
" » and |source|.
1. Return.
1. Set |source|'s [=attribution source/randomized response=] to the result of
[=obtaining a randomized source response=] with |randomizedResponseConfig| and |epsilon|.
@@ -2976,24 +3138,37 @@ To process an attribution source given an [=attribution source=] |sou
[=attribution source/source origin=] are [=same origin=].
1. If |pendingSourcesForSourceOrigin|'s [=list/size=] is greater than or equal
to the user agent's [=max pending sources per source origin=]:
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-storage-limit=]
" and |source|.
- 1. Return.
-1. If the result of running [=check if an attribution source exceeds the unexpired destination limit=]
- with |source| is true:
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-destination-limit=]" and |source|.
- 1. Return.
-1. If the result of running [=check if an attribution source should be blocked by reporting-origin per site limit=]
- with |source| is blocked:
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-reporting-origin-per-site-limit=]
" and |source|.
+ 1. Run [=obtain and deliver debug reports on source registration=] with
+ « "[=source debug data type/source-storage-limit=]
" » and |source|.
1. Return.
1. Let |destinationRateLimitResult| be the result of running [=check if an attribution source exceeds the time-based destination limit=] with |source|.
1. If |destinationRateLimitResult| is "[=destination rate-limit result/hit reporting limit=]
":
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-destination-rate-limit=]
" and |source|.
+ 1. Run [=obtain and deliver debug reports on source registration=] with
+ « "[=source debug data type/source-destination-rate-limit=]
" » and |source|.
1. Return.
+1. If the result of running [=check if an attribution source exceeds the per day destination limit=]
+ with |source| is true:
+ 1. Run [=obtain and deliver debug reports on source registration=] with
+ « "[=source debug data type/source-destination-per-day-rate-limit=]
" » and |source|.
+ 1. Return.
+1. Let |sourcesToDeleteForDestinationLimit| be the result of running [=get sources to delete for the unexpired destination limit=]
+ with |source|.
+1. If |sourcesToDeleteForDestinationLimit| [=set/contains=] |source|'s [=attribution source/source identifier=]:
+ 1. Run [=obtain and deliver debug reports on source registration=] with
+ "[=source debug data type/source-destination-limit=]
" and |source|.
+ 1. Return.
+1. Let |debugDataTypes| be a new [=set=].
+1. If |sourcesToDeleteForDestinationLimit| is not [=set/is empty|empty=],
+ [=set/append=] "[=source debug data type/source-destination-limit-replaced=]
"
+ to |debugDataTypes|.
+1. Run [=delete sources for unexpired destination limit=] with |sourcesToDeleteForDestinationLimit| and |source|'s [=attribution source/source time=].
1. Let |isNoised| be true if |source|'s [=attribution source/randomized response=]
is not null, otherwise false.
1. If |destinationRateLimitResult| is "[=destination rate-limit result/hit global limit=]
":
- 1. Run [=obtain and deliver debug reports on source registration=] with "[=source debug data type/source-destination-global-rate-limit=]
", |source|, and |isNoised|.
+ 1. [=set/Append=] "[=source debug data type/source-destination-global-rate-limit=]
"
+ to |debugDataTypes|.
+ 1. Run [=obtain and deliver debug reports on source registration=]
+ with |debugDataTypes|, |source|, and |isNoised|.
1. Return.
1. Let |newRateLimitRecords| be a new [=set=].
1. [=set/iterate|For each=] |destination| in |source|'s [=attribution source/attribution destinations=]:
@@ -3010,13 +3185,16 @@ To process an attribution source given an [=attribution source=] |sou
:: |source|'s [=attribution source/source time=]
: [=attribution rate-limit record/expiry time=]
:: |source|'s [=attribution source/expiry time=]
- : [=attribution rate-limit record/event-level report ID=]
- :: null
+ : [=attribution rate-limit record/entity ID=]
+ :: |source|'s [=attribution source/source identifier=]
+ : [=attribution rate-limit record/destination limit priority=]
+ :: |source|'s [=attribution source/destination limit priority=]
1. If the result of running [=should processing be blocked by reporting-origin limit=] with
|rateLimitRecord| is blocked:
- 1. Run [=obtain and deliver debug reports on source registration=] with
- "[=source debug data type/source-reporting-origin-limit=]
", |source|,
- and |isNoised|.
+ 1. [=set/Append=] "[=source debug data type/source-reporting-origin-limit=]
"
+ to |debugDataTypes|.
+ 1. Run [=obtain and deliver debug reports on source registration=]
+ with |debugDataTypes|, |source|, and |isNoised|.
1. Return.
1. [=set/Append=] |rateLimitRecord| to |newRateLimitRecords|.
1. [=set/iterate|For each=] |record| of |newRateLimitRecords|, [=set/append=] |record| to
@@ -3045,12 +3223,13 @@ To process an attribution source given an [=attribution source=] |sou
:: |source|'s [=attribution source/source time=]
: [=attribution rate-limit record/expiry time=]
:: null
- : [=attribution rate-limit record/event-level report ID=]
+ : [=attribution rate-limit record/entity ID=]
:: null
1. [=set/Append=] |rateLimitRecord| to the [=attribution rate-limit cache=].
+1. [=set/Append=] "[=source debug data type/source-success=]
" to
+ |debugDataTypes|.
1. Run [=obtain and deliver debug reports on source registration=] with
- "[=source debug data type/source-success=]
", |source|,
- and |isNoised|.
+ |debugDataTypes|, |source|, and |isNoised|.
1. [=set/Append=] |source| to |cache|.
Note: Because a fake report does not have a "real" effective destination, we need to subtract from the
@@ -3603,7 +3782,7 @@ To maybe replace event-level report given an [=attribution source=]
1. [=set/Remove=] |lowestPriorityReport| from the [=event-level report cache=].
1. Decrement |sourceToAttribute|'s [=attribution source/number of event-level reports=] value by 1.
1. Let |rateLimitRecord| be the element from [=attribution rate-limit cache=] whose
- [=attribution rate-limit record/event-level report ID=] is equal to |lowestPriorityReport|'s [=event-level report/report ID=]
+ [=attribution rate-limit record/entity ID=] is equal to |lowestPriorityReport|'s [=event-level report/report ID=]
and [=attribution rate-limit record/scope=] is equal to "[=rate-limit scope/event-attribution=]
".
1. [=Assert=]: |rateLimitRecord| is not null.
@@ -3678,7 +3857,7 @@ To trigger event-level attribution given an [=attribution trigger=] |
:: |sourceToAttribute|'s [=attribution source/source time=]
: [=attribution rate-limit record/expiry time=]
:: null
- : [=attribution rate-limit record/event-level report ID=]
+ : [=attribution rate-limit record/entity ID=]
:: |report|'s [=event-level report/report ID=]
1. If the result of running [=check if attribution should be blocked by rate limits=]
with |trigger|, |sourceToAttribute|, and |rateLimitRecord| is not null, return it.
@@ -3777,7 +3956,7 @@ To trigger aggregatable attribution given an [=attribution trigger=]
:: |sourceToAttribute|'s [=attribution source/source time=]
: [=attribution rate-limit record/expiry time=]
:: null
- : [=attribution rate-limit record/event-level report ID=]
+ : [=attribution rate-limit record/entity ID=]
:: null
1. If the result of running [=check if attribution should be blocked by rate limits=]
with |trigger|, |sourceToAttribute|, and |rateLimitRecord| is not null,
@@ -4032,6 +4211,8 @@ an [=attribution trigger=] |trigger|:
:: |trigger|'s [=attribution trigger/aggregatable source registration time configuration=].
: [=aggregatable attribution report/trigger context ID=]
:: |trigger|'s [=attribution trigger/trigger context ID=]
+ : [=aggregatable attribution report/source identifier=]
+ :: |source|'s [=attribution source/source identifier=].
1. Return |report|.