Skip to content

Commit

Permalink
Introduce internal report IDs for identity comparisons (#1421)
Browse files Browse the repository at this point in the history
Rather than re-use the external report UUID for this purpose, since there is a small chance that it is not actually unique.

This also provides a foundation for addressing #1405 using integer sequences, as UUIDs cannot be used to provide an ordering of events.
  • Loading branch information
apasel422 authored Sep 11, 2024
1 parent d7f363f commit 4db3b83
Showing 1 changed file with 51 additions and 41 deletions.
92 changes: 51 additions & 41 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ An attribution scopes is a [=struct=] with the following items:
An attribution source is a [=struct=] with the following items:

<dl dfn-for="attribution source">
: <dfn>source identifier</dfn>
: <dfn>internal ID</dfn>
:: A [=string=].
: <dfn>source origin</dfn>
:: A [=suitable origin=].
Expand Down Expand Up @@ -1008,7 +1008,9 @@ An attribution report is a [=struct=] with the following items:
:: A [=suitable origin=].
: <dfn>report time</dfn>
:: A [=moment=].
: <dfn>report ID</dfn>
: <dfn>external ID</dfn>
:: A UUID formatted as a [=string=].
: <dfn>internal ID</dfn>
:: A [=string=].

</dl>
Expand Down Expand Up @@ -1040,8 +1042,8 @@ An event-level report is an [=attribution report=] with the following additional
:: A 64-bit integer.
: <dfn>trigger time</dfn>
:: A [=moment=].
: <dfn>source identifier</dfn>
:: A string.
: <dfn>source ID</dfn>
:: A [=string=].
: <dfn>attribution destinations</dfn>
:: A [=set=] of [=sites=].
: <dfn>attribution debug info</dfn>
Expand Down Expand Up @@ -1090,7 +1092,7 @@ An <dfn>aggregatable attribution report</dfn> is an [=aggregatable report=] with
:: A positive integer.
: <dfn>attribution debug info</dfn>
:: An [=attribution debug info=].
: <dfn>source identifier</dfn>
: <dfn>source ID</dfn>
:: Null or a [=string=].

</dl>
Expand Down Expand Up @@ -1123,9 +1125,9 @@ An <dfn>attribution rate-limit record</dfn> is a [=struct=] with the following i
: <dfn>expiry time</dfn>
:: Null or a [=moment=].
: <dfn>entity ID</dfn>
:: 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=].
:: Null for [=obtain a fake report|fake reports=] or an [=event-level report=]'s [=event-level report/internal ID=] or an
[=aggregatable attribution report=]'s [=aggregatable attribution report/internal ID=] or an
[=attribution source=]'s [=attribution source/internal ID=].
: <dfn>deactivated for unexpired destination limit</dfn> (default false)
:: A [=boolean=].
: <dfn>destination limit priority</dfn> (default null)
Expand Down Expand Up @@ -2268,8 +2270,10 @@ an [=aggregation coordinator=] |aggregationCoordinator|, and a [=moment=] |now|:
:: |effectiveDestination|
: [=aggregatable debug report/report time=]
:: |now|
: [=aggregatable debug report/report ID=]
: [=aggregatable debug report/external ID=]
:: The result of [=generating a random UUID=]
: [=aggregatable debug report/internal ID=]
:: A new unique [=string=]
: [=aggregatable debug report/contributions=]
:: |contributions|
: [=aggregatable debug report/aggregation coordinator=]
Expand Down Expand Up @@ -2799,7 +2803,7 @@ To <dfn noexport>parse source-registration JSON</dfn> given a [=byte sequence=]
1. If [=automation local testing mode=] is true, set |epsilon| to `∞`.
1. Let |source| be a new [=attribution source=] struct whose items are:

: [=attribution source/source identifier=]
: [=attribution source/internal ID=]
:: A new unique [=string=]
: [=attribution source/source origin=]
:: |sourceOrigin|
Expand Down Expand Up @@ -2907,17 +2911,17 @@ given an [=attribution source=] |source|, run the following steps:
1. Return whether |destinations|'s [=set/size=] is greater than [=max destinations per source reporting site per day=].

To <dfn>delete sources for unexpired destination limit</dfn> given a [=set=] of
[=attribution source/source identifiers=] |sourcesToDelete| and a [=moment=] |now|:
[=attribution source/internal IDs=] |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=].
[=set/contains=] |source|'s [=attribution source/internal ID=].
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=]
1. If |sourcesToDelete| [=set/contains=] |report|'s [=event-level report/source ID=]
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/Append=] |report|'s [=event-level report/internal ID=] to |deletedEventLevelReports|.
1. [=set/Remove=] |report| from the [=event-level report cache=].

Note: Leaking browsing history of destinations deactivated for unexpired
Expand All @@ -2929,8 +2933,8 @@ To <dfn>delete sources for unexpired destination limit</dfn> given a [=set=] of

1. Let |deletedAggregatableReports| be a new [=set=].
1. [=set/iterate|For each=] [=aggregatable attribution report=] |report| of the [=aggregatable attribution report cache=]:
1. If |report|'s [=aggregatable attribution report/source identifier=] is not null and |sourcesToDelete| [=set/contains=] |report|'s [=aggregatable attribution report/source identifier=]:
1. [=set/Append=] |report|'s [=aggregatable attribution report/report ID=] to |deletedAggregatableReports|.
1. If |report|'s [=aggregatable attribution report/source ID=] is not null and |sourcesToDelete| [=set/contains=] |report|'s [=aggregatable attribution report/source ID=]:
1. [=set/Append=] |report|'s [=aggregatable attribution report/internal 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:
Expand All @@ -2956,7 +2960,7 @@ A <dfn>destination limit record</dfn> is a [=struct=] with the following items:
:: A 64-bit integer.
: <dfn>time</dfn>
:: A [=moment=]
: <dfn>source identifier</dfn>
: <dfn>source ID</dfn>
:: A [=string=].

</dl>
Expand All @@ -2980,7 +2984,7 @@ To <dfn>get sources to delete for the unexpired destination limit</dfn> given an
:: |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=]
: [=destination limit record/source ID=]
:: |record|'s [=attribution rate-limit record/entity ID=]

1. [=list/Append=] |destinationRecord| to |destinationRecords|.
Expand All @@ -2993,8 +2997,8 @@ To <dfn>get sources to delete for the unexpired destination limit</dfn> given an
:: |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=]
: [=destination limit record/source ID=]
:: |record|'s [=attribution source/internal ID=]

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:
Expand All @@ -3014,7 +3018,7 @@ To <dfn>get sources to delete for the unexpired destination limit</dfn> given an
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. [=set/Append=] |record|'s [=destination limit record/source ID=] to |sourcesToDelete|.
1. Return |sourcesToDelete|.

To <dfn>check if an [=attribution source=] should be blocked by reporting-origin per site limit</dfn> given an [=attribution source=] |source|:
Expand Down Expand Up @@ -3177,12 +3181,12 @@ To <dfn>find sources with common destinations and reporting origin</dfn> given a
1. [=list/Append=] |source| to |matchingSources|.
1. Return |matchingSources|.

To <dfn>remove associated event-level reports and rate-limit records</dfn> given an [=attribution source/source identifier=] |sourceId| and a [=moment=] |minTriggerTime|:
To <dfn>remove associated event-level reports and rate-limit records</dfn> given an [=attribution source/internal ID=] |sourceId| and a [=moment=] |minTriggerTime|:
1. [=set/iterate|For each=] [=event-level report=] |report| of the [=event-level report cache=]:
1. If |report|'s [=event-level report/source identifier=] is not equal to |sourceId|, [=iteration/continue=].
1. If |report|'s [=event-level report/source ID=] is not equal to |sourceId|, [=iteration/continue=].
1. If |report|'s [=event-level report/trigger time=] is less than |minTriggerTime|, [=iteration/continue=].
1. [=set/Remove=] |report| from the [=event-level report cache=].
1. [=list/Remove=] all [=attribution rate-limit records=] |entry| from the [=attribution rate-limit cache=] where |entry|'s [=attribution rate-limit record/entity ID=] is equal to |report|'s [=event-level report/report ID=].
1. [=list/Remove=] all [=attribution rate-limit records=] |entry| from the [=attribution rate-limit cache=] where |entry|'s [=attribution rate-limit record/entity ID=] is equal to |report|'s [=event-level report/internal ID=].

To <dfn>remove sources with unselected attribution scopes for destination</dfn> given a [=site=] |destination| and an [=attribution source=] |pendingSource|:
1. Let |scopeRecords| be a new [=list=].
Expand All @@ -3202,7 +3206,7 @@ To <dfn>remove sources with unselected attribution scopes for destination</dfn>
1. If |selectedScopes|'s [=set/size=] is less than |pendingSource|'s [=attribution source/attribution scopes=]'s [=attribution scopes/limit=], [=set/append=] |record|[0] to |selectedScopes|.
1. Otherwise, if |selectedScopes| does not [=set/contain=] |record|[0], [=set/append=] |record|[1] to |sourcesToRemove|.
1. [=set/iterate|For each=] |source| of the |sourcesToRemove|:
1. [=Remove associated event-level reports and rate-limit records=] with |source|'s [=attribution source/source identifier=] and |pendingSource|'s [=attribution source/source time=].
1. [=Remove associated event-level reports and rate-limit records=] with |source|'s [=attribution source/internal ID=] and |pendingSource|'s [=attribution source/source time=].
1. [=set/Remove=] |source| from the [=attribution source cache=].

To <dfn>remove sources with unselected attribution scopes</dfn> given an [=attribution source=] |pendingSource|:
Expand All @@ -3226,7 +3230,7 @@ To <dfn>remove or update sources for attribution scopes</dfn> given an [=attribu
1. If |existingScopes| is null or |existingScopes|'s [=attribution scopes/max event states=]
is not equal to |pendingScopes|'s [=attribution scopes/max event states=] or
|existingScopes|'s [=attribution scopes/limit=] is less than |pendingScopes|'s [=attribution scopes/limit=]:
1. [=Remove associated event-level reports and rate-limit records=] with |source|'s [=attribution source/source identifier=] and |pendingSource|'s [=attribution source/source time=].
1. [=Remove associated event-level reports and rate-limit records=] with |source|'s [=attribution source/internal ID=] and |pendingSource|'s [=attribution source/source time=].
1. [=set/Remove=] |source| from the [=attribution source cache=].
1. [=Remove sources with unselected attribution scopes=] with |pendingSource|.

Expand Down Expand Up @@ -3291,7 +3295,7 @@ To <dfn>process an attribution source</dfn> given an [=attribution source=] |sou
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. If |sourcesToDeleteForDestinationLimit| [=set/contains=] |source|'s [=attribution source/internal ID=]:
1. Run [=obtain and deliver debug reports on source registration=] with
"<code>[=source debug data type/source-destination-limit=]</code>" and |source|.
1. Return.
Expand Down Expand Up @@ -3322,7 +3326,7 @@ To <dfn>process an attribution source</dfn> given an [=attribution source=] |sou
: [=attribution rate-limit record/expiry time=]
:: |source|'s [=attribution source/expiry time=]
: [=attribution rate-limit record/entity ID=]
:: |source|'s [=attribution source/source identifier=]
:: |source|'s [=attribution source/internal ID=]
: [=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
Expand Down Expand Up @@ -3972,7 +3976,7 @@ To <dfn>maybe replace event-level report</dfn> given an [=attribution source=]
|sourceToAttribute|'s [=attribution source/max number of event-level reports=].
1. If |sourceToAttribute|'s [=attribution source/number of event-level reports=] is less than
|sourceToAttribute|'s [=attribution source/max number of event-level reports=], return "<code>[=event-level-report-replacement result/add-new-report=]</code>".
1. Let |matchingReports| be a new [=list=] whose elements are all the elements in the [=event-level report cache=] whose [=event-level report/report time=] and [=event-level report/source identifier=] are equal to |report|'s, [=list/sorted in ascending order=] using [=event-level report/is lower-priority than=].
1. Let |matchingReports| be a new [=list=] whose elements are all the elements in the [=event-level report cache=] whose [=event-level report/report time=] and [=event-level report/source ID=] are equal to |report|'s, [=list/sorted in ascending order=] using [=event-level report/is lower-priority than=].
1. If |matchingReports| [=list/is empty=]:
1. Set |sourceToAttribute|'s [=attribution source/event-level attributable=] value to false.
1. Return "<code>[=event-level-report-replacement result/drop-new-report-none-to-replace=]</code>".
Expand All @@ -3984,7 +3988,7 @@ To <dfn>maybe replace event-level report</dfn> 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/entity 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/internal ID=]
and [=attribution rate-limit record/scope=] is equal to "<code>[=rate-limit scope/event-attribution=]</code>".
1. [=Assert=]: |rateLimitRecord| is not null.

Expand Down Expand Up @@ -4079,7 +4083,7 @@ To <dfn>trigger event-level attribution</dfn> given an [=attribution trigger=] |
: [=attribution rate-limit record/expiry time=]
:: null
: [=attribution rate-limit record/entity ID=]
:: |report|'s [=event-level report/report ID=]
:: |report|'s [=event-level report/internal 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.
1. Let |numMatchingReports| be the number of entries in the [=event-level report cache=] whose
Expand Down Expand Up @@ -4391,10 +4395,12 @@ a 64-bit integer priority |priority|, and a [=trigger spec map=] [=map/entry=]
:: |priority|.
: [=event-level report/trigger time=]
:: |triggerTime|.
: [=event-level report/source identifier=]
:: |source|'s [=attribution source/source identifier=].
: [=event-level report/report ID=]
: [=event-level report/source ID=]
:: |source|'s [=attribution source/internal ID=].
: [=event-level report/external ID=]
:: The result of [=generating a random UUID=].
: [=event-level report/internal ID=]
:: A new unique [=string=]
: [=event-level report/attribution debug info=]
:: (|source|'s [=attribution source/debug key=], |triggerDebugKey|).
1. Return |report|.
Expand All @@ -4421,8 +4427,10 @@ an [=attribution trigger=] |trigger|:
:: |source|'s [=attribution source/source time=].
: [=aggregatable attribution report/report time=]
:: |reportTime|.
: [=aggregatable attribution report/report ID=]
: [=aggregatable attribution report/external ID=]
:: The result of [=generating a random UUID=].
: [=aggregatable attribution report/internal ID=]
: A new unique [=string=]
: [=aggregatable attribution report/attribution debug info=]
:: (|source|'s [=attribution source/debug key=], |trigger|'s [=attribution trigger/debug key=]).
: [=aggregatable attribution report/contributions=]
Expand All @@ -4435,8 +4443,8 @@ an [=attribution trigger=] |trigger|:
:: |trigger|'s [=attribution trigger/trigger context ID=]
: [=aggregatable attribution report/filtering ID max bytes=]
:: |trigger|'s [=attribution trigger/aggregatable filtering ID max bytes=]
: [=aggregatable attribution report/source identifier=]
:: |source|'s [=attribution source/source identifier=].
: [=aggregatable attribution report/source ID=]
:: |source|'s [=attribution source/internal ID=].
1. Return |report|.

<h3 id="generating-randomized-null-attribution-reports">Generating randomized null attribution reports</h3>
Expand All @@ -4454,8 +4462,10 @@ To <dfn>obtain a null attribution report</dfn> given an [=attribution trigger=]
:: |sourceTime|
: [=aggregatable attribution report/report time=]
:: |reportTime|
: [=aggregatable attribution report/report ID=]
: [=aggregatable attribution report/external ID=]
:: The result of [=generating a random UUID=]
: [=aggregatable attribution report/internal ID=]
: A new unique [=string=]
: [=aggregatable attribution report/attribution debug info=]
:: (null, |trigger|'s [=attribution trigger/debug key=])
: [=aggregatable attribution report/contributions=]
Expand All @@ -4470,7 +4480,7 @@ To <dfn>obtain a null attribution report</dfn> given an [=attribution trigger=]
:: |trigger|'s [=attribution trigger/trigger context ID=]
: [=aggregatable attribution report/filtering ID max bytes=]
:: |trigger|'s [=attribution trigger/aggregatable filtering ID max bytes=]
: [=aggregatable attribution report/source identifier=]
: [=aggregatable attribution report/source ID=]
:: Null
1. Return |report|.

Expand Down Expand Up @@ -4613,7 +4623,7 @@ of running the following steps:
: "`attribution_destination`"
:: |report|'s [=aggregatable report/effective attribution destination=], <a href="https://html.spec.whatwg.org/multipage/origin.html#serialization-of-a-site">serialized</a>
: "`report_id`"
:: |report|'s [=aggregatable report/report ID=]
:: |report|'s [=aggregatable report/external ID=]

Note: The inclusion of "`report_id`" in the shared info is intended to allow the report recipient
to perform deduplication and prevent double counting, in the event that the user agent retries
Expand Down Expand Up @@ -4755,7 +4765,7 @@ To <dfn>obtain an event-level report body</dfn> given an [=attribution report=]
: "`trigger_data`"
:: |report|'s [=event-level report/trigger data=], [=serialize an integer|serialized=]
: "`report_id`"
:: |report|'s [=event-level report/report ID=]
:: |report|'s [=event-level report/external ID=]

Note: The inclusion of "`report_id`" in the report body is intended to allow the report recipient
to perform deduplication and prevent double counting, in the event that the user agent retries
Expand Down

0 comments on commit 4db3b83

Please sign in to comment.