Skip to content

Commit

Permalink
Spec: macro reporting support (WICG#762)
Browse files Browse the repository at this point in the history
* Spec out 3pat macro reporting.

Added allowedReportingOrigins field to IG.
Added a new registerAdMacro() API that can be called in reportWin().

* Finish specing 3pat macro reporting.

Protected audience side. Added a todo to pass macro map to fenced frame
reporting function defined in fenced frame spec.

* cleanup.

* Pass allowed reporting origins through.

* Address comments. Link to definitions.

---------

Co-authored-by: Qingxin Wu <qingxinwu@google.com>
  • Loading branch information
qingxinwu and Qingxin Wu authored Sep 12, 2023
1 parent 2ab18b9 commit 6a827bd
Showing 1 changed file with 88 additions and 28 deletions.
116 changes: 88 additions & 28 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ partial interface Navigator {
dictionary AuctionAd {
required USVString renderURL;
any metadata;

USVString buyerReportingId;
USVString buyerAndSellerReportingId;
sequence<USVString> allowedReportingOrigins;
};

dictionary GenerateBidInterestGroup {
Expand Down Expand Up @@ -279,6 +281,16 @@ This is detectable because it can change the set of fields that are read from th
|igAd|'s [=interest group ad/buyer reporting ID=] to it.
1. If |ad|["{{AuctionAd/buyerAndSellerReportingId}}"] [=map/exists=],
then set |igAd|'s [=interest group ad/buyer and seller reporting ID=] to it.
1. If |ad|["{{AuctionAd/allowedReportingOrigins}}"] [=map/exists=]:
1. Let |allowedReportingOrigins| be a new [=list=] of [=origins=].
1. [=list/For each=] |originStr| in |ad|["{{AuctionAd/allowedReportingOrigins}}"]:
1. Let |origin| be the result of [=parsing an origin=] on |originStr|.
1. If |origin| is failure, or its [=url/scheme=] is not "`https`", [=exception/throw=] a
{{TypeError}}.
1. [=list/Append=] |origin| to |allowedReportingOrigins|.
1. If [=list/size=] of |allowedReportingOrigins| is greater than 10, [=exception/throw=]
a {{TypeError}}.
1. Set |igAd|'s [=interest group ad/allowed reporting origins=] to |allowedReportingOrigins|.
1. [=list/Append=] |igAd| to |interestGroup|'s |interestGroupField|.
1. If |interestGroup|'s [=interest group/estimated size=] is greater than 50 KB, then
[=exception/throw=] a {{TypeError}}.
Expand Down Expand Up @@ -323,7 +335,6 @@ The <dfn for="interest group">estimated size</dfn> of an [=interest group=] |ig|
[=interest group/priority signals overrides=]:
1. The [=string/length=] of |key|.
1. 8 bytes, which is the size of |value|.
1. The size of [=interest group/execution mode=].
1. The [=string/length=] of the [=URL serializer|serialization=] of |ig|'s
[=interest group/bidding url=], if the field is not null.
1. The [=string/length=] of the [=URL serializer|serialization=] of |ig|'s
Expand All @@ -340,7 +351,11 @@ The <dfn for="interest group">estimated size</dfn> of an [=interest group=] |ig|
[=interest group ad/render url=].
1. The [=string/length=] of |ad|'s [=interest group ad/metadata=] if the field is not null.
1. The [=string/length=] of |ad|'s [=interest group ad/buyer reporting ID=] if the field is not null.
1. The [=string/length=] of |ad|'s [=interest group ad/buyer and seller reporting ID=] if the field is not null.
1. The [=string/length=] of |ad|'s [=interest group ad/buyer and seller reporting ID=] if the
field is not null.
1. If |ad|'s [=interest group ad/allowed reporting origins=] is not null, [=list/for each=]
|origin| of it:
1. The [=string/length=] of the [=serialization of an origin|serialization=] of |origin|.
1. If |ig|'s [=interest group/ad components=] is not null, [=list/for each=] |ad| of it:
1. The [=string/length=] of the [=URL serializer|serialization=] of |ad|'s
[=interest group ad/render url=].
Expand Down Expand Up @@ -724,14 +739,22 @@ To <dfn>asynchronously finish reporting</dfn> given a
1. [=iteration/While=]:
1. If |buyerDone|, |sellerDone|, and |componentSellerDone| are all true, then
[=iteration/break=].
1. Wait until |leadingBidInfo|'s [=leading bid info/buyer reporting result=] is not null,
or |leadingBidInfo|'s [=leading bid info/seller reporting result=] is not null, or
|leadingBidInfo|'s [=leading bid info/component seller reporting result=] is not null.
1. Wait until one of the following fields of |leadingBidInfo| being not null:
* [=leading bid info/buyer reporting result=];
* [=leading bid info/seller reporting result=];
* [=leading bid info/component seller reporting result=].
1. If |buyerDone| is false and |leadingBidInfo|'s [=leading bid info/buyer reporting result=]
is not null:
1. Let |buyerMap| be |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s
[=reporting result/reporting beacon map=].
1. If |buyerMap| is null, set |buyerMap| to an empty [=map=] «[]».
1. Let |allowedReportingOrigins| be |leadingBidInfo|'s [=leading bid info/leading bid=]'s
[=generated bid/bid ad=]'s [=interest group ad/allowed reporting origins=].
1. Let |macroMap| be |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s
[=reporting result/reporting macro map=].
1. TODO: Pass |macroMap| and |allowedReportingOrigins| to [=Finalize a reporting destination=]
when it is updated to take the parameters. May need to convert |macroMap| to a list, based
on what that function expects.
1. [=Finalize a reporting destination=] with |reportingMap|,
{{FenceReportingDestination/buyer}}, and |buyerMap|.
1. [=Send report=] to |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s
Expand Down Expand Up @@ -1261,9 +1284,9 @@ To <dfn>generate and score bids</dfn> given an [=auction config=] |auctionConfig
1. If |originalAds| is not null:
1. Set |ig|'s [=interest group/ads=] to a new [=list=] of [=interest group ad=].
1. [=list/For each=] |ad| in |originalAds|:
1. If [=query ad k-anonymity count=] given |ig| and |ad|'s
[=interest group ad/render url=] returns true, [=list/append=] |ad| to |ig|'s
[=interest group/ads=].
1. If [=query ad k-anonymity count=] given |ig| and |ad|'s
[=interest group ad/render url=] returns true, [=list/append=] |ad| to |ig|'s
[=interest group/ads=].
1. Let |originalAdComponents| be |ig|'s [=interest group/ad components=].
1. If |originalAdComponents| is not null:
1. Set |ig|'s [=interest group/ad components=] to a new [=list=] of [=interest group ad=].
Expand Down Expand Up @@ -1867,7 +1890,7 @@ null |winningComponentConfig|:
1. [=map/Set=] |browserSignals|["{{ReportingBrowserSignals/buyerAndSellerReportingId}}"] to |igAd|'s [=interest group ad/buyer and seller reporting ID=].
1. Let |sellerReportingScript| be the result of [=fetching script=] with |config|'s
[=auction config/decision logic url=].
1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap| » be the result of
1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored » be the result of
[=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`", and
« |config|'s [=auction config/config idl=], |browserSignals| ».
1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]:
Expand Down Expand Up @@ -1932,8 +1955,8 @@ and a {{ReportingBrowserSignals}} |browserSignals|:
1. Otherwise, [=map/Set=] |reportWinBrowserSignals|["{{ReportWinBrowserSignals/interestGroupName}}"] to |winner|'s [=generated bid/interest group=] [=interest group/name=].
1. Let |buyerReportingScript| be the result of [=fetching script=] with |winner|'s
[=generated bid/interest group=]'s [=interest group/bidding url=].
1. Let « ignored, |resultUrl|, |reportingBeaconMap| » be the result of [=evaluating a
reporting script=] with |buyerReportingScript|, "`reportWin`", and
1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap| » be the result of
[=evaluating a reporting script=] with |buyerReportingScript|, "`reportWin`", and
« |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config idl=]'s
{{AuctionAdConfig/auctionSignals}}, |perBuyerSignalsForBuyer|, |sellerSignals|,
|reportWinBrowserSignals| ».
Expand All @@ -1944,6 +1967,9 @@ and a {{ReportingBrowserSignals}} |browserSignals|:

: [=reporting result/reporting beacon map=]
:: |reportingBeaconMap|

: [=reporting result/reporting macro map=]
:: |reportingMacroMap|
</div>

# K-anonymity # {#k-anonymity}
Expand Down Expand Up @@ -2279,8 +2305,10 @@ of the following global objects:
exception was [=exception/thrown=] in the previous step, keep |resultJSON| as "null".
1. Let |reportURL| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/report url=]
1. If |reportURL| is failure, set |reportURL| to null.
1. Let |macroMap| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=]
if |functionName| is "`reportWin`", null otherwise.
1. Return « |resultJSON|, |reportURL|,
|global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=] ».
|global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=], |macroMap| ».
</div>

<div algorithm>
Expand Down Expand Up @@ -2433,13 +2461,15 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
1. Let |adUrl| be the result of running the [=URL parser=] on
|generateBidOutput|["{{GenerateBidOutput/render}}"].
1. If |adUrl| is failure, return failure.
1. If [=validating an ad url=] given |adUrl|, |ig|, and false returns false, return failure.
1. Set |adDescriptor|'s [=ad descriptor/url=] to |adUrl|.
1. Otherwise:
1. Set |adDescriptor| to the result of [=converting an ad render=] given
|generateBidOutput|["{{GenerateBidOutput/render}}"], |ig| and false.
|generateBidOutput|["{{GenerateBidOutput/render}}"].
1. If |adDescriptor| is failure, return failure.
1. Let |bidAd| be the result of [=finding matching ad=] given |adDescriptor|, |ig|, and false.
1. If |bidAd| is null, return failure.
1. Set |bid|'s [=generated bid/ad descriptor=] to |adDescriptor|.
1. Set |bid|'s [=generated bid/bid ad=] to |bidAd|.
1. If |generateBidOutput|["{{GenerateBidOutput/adComponents}}"] [=map/exists=]:
1. Let |adComponents| be |generateBidOutput|["{{GenerateBidOutput/adComponents}}"].
1. Return failure if any of the following conditions hold:
Expand All @@ -2451,12 +2481,11 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
1. If |component| is {{DOMString}}:
1. Let |componentUrl| be the result of running the [=URL parser=] on |component|.
1. If |componentUrl| is failure, return failure.
1. If [=validating an ad url=] given |componentUrl|, |ig|, and true returns false, return failure.
1. Set |componentDescriptor|'s [=ad descriptor/url=] to |componentUrl|.
1. Otherwise:
1. Set |componentDescriptor| to the result of [=converting an ad render=] given |component|, |ig|,
and true.
1. Set |componentDescriptor| to the result of [=converting an ad render=] given |component|.
1. If |componentDescriptor| is failure, return failure.
1. If [=finding matching ad=] given |componentUrl|, |ig|, and true returns null, return failure.
1. [=list/Append=] |componentDescriptor| to |adComponentDescriptors|.
1. Set |bid|'s [=generated bid/ad component descriptors=] to |adComponentDescriptors|.
1. If |generateBidOutput|["{{GenerateBidOutput/adCost}}"] [=map/exists=]:
Expand Down Expand Up @@ -2490,12 +2519,10 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
</div>

<div algorithm>
To <dfn>convert an ad render</dfn> given an {{AdRender}} |adRender|, an [=interest group=] |ig|,
and a [=boolean=] |isComponent|:
To <dfn>convert an ad render</dfn> given an {{AdRender}} |adRender|:

1. Let |adUrl| be the result of running the [=URL parser=] on |adRender|["{{AdRender/url}}"].
1. If |adUrl| is failure, return failure.
1. If [=validating an ad url=] given |adUrl|, |ig|, and |isComponent| returns false, return failure.
1. Let |adDescriptor| be a new [=ad descriptor=].
1. Set |adDescriptor|'s [=ad descriptor/url=] to |adUrl|.
1. If |adRender|["{{AdRender/width}}"] [=map/exists=]:
Expand All @@ -2514,17 +2541,19 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
</div>

<div algorithm>
To <dfn>validate an ad url</dfn> given a [=URL=] |adUrl|, an [=interest group=] |ig|, and a
[=boolean=] |isComponent|:
To <dfn>find matching ad</dfn> given an [=ad descriptor=] |adDescriptor|, an [=interest group=]
|ig|, and a [=boolean=] |isComponent|:

1. If |adUrl|'s [=url/scheme=] is not "`https`", return false.
1. Let |adUrl| be |adDescriptor|'s [=ad descriptor/url=].
1. If |adUrl|'s [=url/scheme=] is not "`https`", return null.
1. TODO: Need to check [=ad descriptor/size=] as well.
1. If |isComponent|:
1. [=list/For each=] |ad| in |ig|'s [=interest group/ad components=]:
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return true.
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return |ad|.
1. Otherwise:
1. [=list/For each=] |ad| in |ig|'s [=interest group/ads=]:
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return true.
1. Return false.
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return |ad|.
1. Return null.
</div>

<div algorithm>
Expand Down Expand Up @@ -2590,17 +2619,24 @@ interface InterestGroupReportingScriptRunnerGlobalScope
: InterestGroupScriptRunnerGlobalScope {
undefined sendReportTo(DOMString url);
undefined registerAdBeacon(record&lt;DOMString, USVString&gt; map);
undefined registerAdMacro(DOMString name, USVString value);
};

</pre>

Note: {{InterestGroupReportingScriptRunnerGlobalScope/registerAdMacro(name, value)}} is only
available in [=report win=], but not [=report result=].

Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a
<dl dfn-for="InterestGroupReportingScriptRunnerGlobalScope">
: <dfn>report url</dfn>
:: Null, failure, or a [=URL=]. Defaulting to null.
: <dfn>reporting beacon map</dfn>
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=URLs=]. Defaulting to null.
: <dfn>reporting macro map</dfn>
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=strings=]. Defaulting to null.

</dl>

Expand Down Expand Up @@ -2646,6 +2682,13 @@ Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a
reporting beacon map=] to |map|.
</div>

<div algorithm>
The <dfn method for="InterestGroupReportingScriptRunnerGlobalScope">registerAdMacro(|name|,
|value|)</dfn> method steps are:

1. [=map/Set=] [=this=]'s [=relevant global object=]'s
[=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=][|name|] to |value|.
</div>

# Interest Group Updates # {#interest-group-updates}

Expand Down Expand Up @@ -3109,9 +3152,19 @@ An interest group ad is a [=struct=] with the following [=struct/items=]:
: <dfn>metadata</dfn>
:: Null or a [=string=]. Extra arbitary information about this ad, passed to `generateBid()`.
: <dfn>buyer reporting ID</dfn>
:: Null or a [=string=]. Will be passed in place of interest group name to `reportWin()`, subject to k-anonymity checks.
:: Null or a [=string=]. Will be passed in place of interest group name to [=report win=], subject
to k-anonymity checks. Only meaningful in [=interest group/ads=], but ignored in
[=interest group/ad components=].
: <dfn>buyer and seller reporting ID</dfn>
:: Null or a [=string=]. Will be passed in place of interest group name or [=interest group ad/buyer reporting ID=] to `reportWin()` and `reportResult()`, subject to k-anonymity checks.
:: Null or a [=string=]. Will be passed in place of interest group name or
[=interest group ad/buyer reporting ID=] to [=report win=] and [=report result=], subject to
k-anonymity checks. Only meaningful in [=interest group/ads=], but ignored in
[=interest group/ad components=].
: <dfn>allowed reporting origins</dfn>
:: Null or a [=list=] of [=origins=]. A list of up to 10 reporting origins that can receive reports
with registered macros. All origins must be HTTPS origins and
<a href="https://github.com/privacysandbox/attestation">enrolled</a>. Only meaningful in
[=interest group/ads=], but ignored in [=interest group/ad components=].

</dl>

Expand Down Expand Up @@ -3372,6 +3425,8 @@ the seller.
:: Null or an {{unsigned short}}. A 0-4095 integer (12-bits) passed to `reportWin()`, with noising.
: <dfn>interest group</dfn>
:: An [=interest group=], whose `generateBid()` invocation generated this bid.
: <dfn>bid ad</dfn>
:: The [=interest group ad=] within [=generated bid/interest group=] to display.
: <dfn>modified bid</dfn>
:: Null or a [=bid with currency=]. Being null for top level auction.
The bid value a component auction's `scoreAd()` script returns.
Expand Down Expand Up @@ -3536,6 +3591,11 @@ A <dfn>reporting result</dfn> is a [=struct=] with the following [=struct/items=
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=URLs=], initially null. Set by
{{InterestGroupReportingScriptRunnerGlobalScope/registerAdBeacon(map)}}.

: <dfn>reporting macro map</dfn>
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=strings=], initially null. Set by
{{InterestGroupReportingScriptRunnerGlobalScope/registerAdMacro(name, value)}}.
</dl>

# Privacy Considerations # {#privacy-considerations}
Expand Down

0 comments on commit 6a827bd

Please sign in to comment.