Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 185 additions & 8 deletions api.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1068,14 +1068,13 @@ For example, "`extra.example.com`" is parsed as "`example.com`".

## State For Privacy Budget Management ## {#privacy-state}

[=User agents=] maintain three pieces of state
[=User agents=] maintain several pieces of state
that are used to manage the expenditure of [=privacy budgets=]:

* The [=privacy budget store=] records the state
of the per-[=site=] and per-[=epoch=] [=privacy budgets=].
It is updated by [=deduct privacy budget=].


* The [=epoch start store=] records when each [=epoch=] starts
for [=conversion sites=].
This store is initialized as a side effect
Expand All @@ -1084,15 +1083,27 @@ that are used to manage the expenditure of [=privacy budgets=]:
* A singleton [=last browsing history clear=] value
that tracks when the browsing activity for a [=site=] was last cleared.

* The [=global privacy budget store=] records the state
of the per-[=epoch=] global [=privacy budget=]
that applies across all [=sites=].

* The [=impression site quota store=] records the state
of per-[=impression site=] and per-[=epoch=] quota [=privacy budgets=].

* The [=conversion site quota store=] records the state
of per-[=conversion site=] and per-[=epoch=] quota [=privacy budgets=].

* The [=user action context store=] records which [=sites=]
have accessed quota [=privacy budgets=] within the current [=user action context=].

<p class=note>
Like the [=impression store=],
the [=privacy budget store=] does not use a [=storage key=].
the [=privacy budget store=] and related stores do not use a [=storage key=].
These stores have some additional constraints
on how information is cleared;
see [[#clear-budget-store]] for details.

<p class=issue>
The [=safety limits=] need to be described in more detail.
Some references to clearing
the [=impression store=] may need to be
updated to refer to the [=privacy budget store=] as well.
Expand Down Expand Up @@ -1173,6 +1184,113 @@ is added to the aggregated histogram.

</div>




### Global Privacy Budget Store ### {#s-global-privacy-budget-store}

The <dfn>global privacy budget store</dfn> is a [=map=] whose keys are
[=epoch indices=] and whose values are [=32-bit unsigned integers=]
in units of [=microepsilons=].

The [=global privacy budget store=] enforces a single [=privacy budget=]
per [=epoch=] that applies across all [=sites=].
This provides a [=safety limit=] against adversaries
that can correlate activity for the same person across multiple [=sites=].

<p class=note>Unlike the per-[=site=] [=privacy budget store=],
the [=global privacy budget store=] is keyed only by [=epoch index=],
not by [=site=].


### Impression Site Quota Store ### {#s-impression-site-quota-store}

The <dfn>impression site quota store</dfn> is a [=map=] whose keys are
[=impression site quota keys=] and whose values are [=32-bit unsigned integers=]
in units of [=microepsilons=].

An <dfn>impression site quota key</dfn> is a [=tuple=] consisting of the following items:

<dl dfn-for="impression site quota key">
: <dfn ignore>epoch index</dfn>
:: An [=epoch index=]
: <dfn ignore>impression site</dfn>
:: An [=impression site=]

</dl>

The [=impression site quota store=] limits the amount of "stock"
(privacy budget related to [=impressions=])
that any single [=impression site=] can contribute in an [=epoch=].
This prevents a single [=impression site=]
from enabling excessive budget
that could be maliciously triggered.


### Conversion Site Quota Store ### {#s-conversion-site-quota-store}

The <dfn>conversion site quota store</dfn> is a [=map=] whose keys are
[=conversion site quota keys=] and whose values are [=32-bit unsigned integers=]
in units of [=microepsilons=].

A <dfn>conversion site quota key</dfn> is a [=tuple=] consisting of the following items:

<dl dfn-for="conversion site quota key">
: <dfn ignore>epoch index</dfn>
:: An [=epoch index=]
: <dfn ignore>conversion site</dfn>
:: A [=conversion site=]

</dl>

The [=conversion site quota store=] limits the amount of "flow"
(privacy budget consumed by reports)
that any single [=conversion site=] can trigger in an [=epoch=].
This constrains the budget that can be drawn by a [=conversion site=],
limiting its ability to rapidly deplete the [=global privacy budget=].


### User Action Context Store ### {#s-user-action-context-store}

The <dfn>user action context store</dfn> is a [=map=] keyed by [=user action contexts=]
and containing values that are [=sets=] of [=sites=].

A <dfn>user action context</dfn> is an identifier
for a sequence of API invocations
that are associated with a single intentional user action,
such as a navigation or click.

The [=user action context store=] tracks which [=sites=]
have accessed quota [=privacy budgets=]
(either [=impression site quota store|impression site quotas=]
or [=conversion site quota store|conversion site quotas=])
within the current [=user action context=].
This enables enforcement of the [=quota count cap=].

<p class=note>A [=user action context=] typically corresponds to
a top-level navigation or other substantial user interaction.
[=User agents=] determine when a new [=user action context=] begins
based on their understanding of intentional user actions.

<div algorithm>
To get the <dfn>current user action context</dfn>,
returning a [=user action context=]:

1. If the [=user agent=] has an active [=user action context=]
associated with the current execution context, return it.

1. Otherwise, create a new [=user action context=] identifier,
add it to the [=user action context store=] with an empty [=set=] value,
and return it.

<p class=note>The [=user agent=] determines when [=user action contexts=] expire
and are removed from the [=user action context store=].
Contexts typically expire after some period of inactivity
or when a new top-level navigation occurs.

</div>


### Epoch Start Store ### {#s-epoch-start}

An [=epoch=] starts at a randomly-selected time
Expand Down Expand Up @@ -1248,6 +1366,33 @@ returning an [=epoch index=]:

</div>

### Safety Limits Configuration ### {#safety-limits-configuration}

[=User agents=] configure [=safety limits=] by defining the following values:

* <dfn>Global budget per epoch</dfn> (&epsilon;<sub>global</sub>):
The maximum privacy budget available across all [=sites=] per [=epoch=],
specified in [=microepsilons=].

* <dfn>Impression site quota per epoch</dfn> (&epsilon;<sub>imp-quota</sub>):
The maximum privacy budget that a single [=impression site=]
can enable to be consumed from the [=global privacy budget=] per [=epoch=],
specified in [=microepsilons=].

* <dfn>Conversion site quota per epoch</dfn> (&epsilon;<sub>conv-quota</sub>):
The maximum privacy budget that a single [=conversion site=]
can consume from the [=global privacy budget=] per [=epoch=],
specified in [=microepsilons=].

* <dfn>Quota count cap</dfn> (<var>k</var><sub>quota-count</sub>):
The maximum number of distinct [=sites=]
that can create new quota budgets
within a single [=user action context=].

<p class=note>Typical values might be:
TODO


### Last Browsing History Clear Time ### {#last-clear}

The <dfn>last browsing history clear</dfn> is a [=moment=]
Expand Down Expand Up @@ -1367,6 +1512,10 @@ and a [=moment=] |now|:

1. [=map/clear|Clear=] the [=epoch start store=].

<p class=issue>TODO: Define how to clear [=safety limits=] stores:
[=global privacy budget store=], [=impression site quota store=],
[=conversion site quota store=], and [=user action context store=].

1. If |sites| [=set/is empty|is not empty=]:

1. [=set/iterate|For each=] |impression| in the [=impression store=],
Expand Down Expand Up @@ -1459,6 +1608,7 @@ The <dfn method for=Attribution>saveImpression(|options|)</dfn> method steps are
:: |options|.{{AttributionImpressionOptions/priority}}
1. If the Attribution API is [[#opt-out|enabled]],
save |impression| to the [=impression store=].

1. Let |result| be a new {{AttributionImpressionResult}}.
1. Return [=a promise resolved with=] |result| in |realm|.

Expand Down Expand Up @@ -1496,6 +1646,10 @@ The <dfn method for=Attribution>measureConversion(|options|)</dfn> method steps
1. otherwise, the result of
[=obtain a site|obtaining a site=]
from |settings|' [=environment settings object/origin=].
1. Let |uaContext| be the [=current user action context=].

<p class=note>The [=user agent=] determines when a new [=user action context=] begins,
typically corresponding to a top-level navigation or other substantial user interaction.
1. Let |validatedOptions| be the result of
[=validate AttributionConversionOptions|validating=] |options|,
returning [=a promise rejected with=] any thrown reason.
Expand All @@ -1505,7 +1659,7 @@ The <dfn method for=Attribution>measureConversion(|options|)</dfn> method steps
|validatedOptions|' [=validated conversion options/histogram size=].
1. If the Attribution API is [[#opt-out|enabled]], set |report| to the
result of [=do attribution and fill a histogram=] with |validatedOptions|,
|topLevelSite|, |intermediarySite|, and |now|.
|topLevelSite|, |intermediarySite|, |uaContext|, and |now|.
1. Let |aggregationService| be |validatedOptions|'s [=validated conversion options/aggregation service=].
1. Switch on the value of |aggregationService|.{{AttributionAggregationService/protocol}}:
<dl class="switch">
Expand Down Expand Up @@ -1628,6 +1782,7 @@ To <dfn>do attribution and fill a histogram</dfn>, given
[=validated conversion options=] |options|,
[=site=] |topLevelSite|,
[=site=] or `undefined` |intermediarySite|,
[=user action context=] |uaContext|,
and [=moment=] |now|:

1. Let |matchedImpressions| be an [=set/is empty|empty=] [=set=].
Expand All @@ -1648,7 +1803,6 @@ To <dfn>do attribution and fill a histogram</dfn>, given
with |options|, |topLevelSite|, |intermediarySite|, |currentEpoch|, and |now|.

1. If |singleEpoch| is false:

1. For each |epoch| from |startEpoch| to |currentEpoch|, inclusive:

1. Let |impressions| be the result of invoking [=common matching logic=]
Expand All @@ -1664,12 +1818,25 @@ To <dfn>do attribution and fill a histogram</dfn>, given
|options|'s [=validated conversion options/max value=],
and null.

1. If |budgetOk| is true, [=set/extend=] |matchedImpressions| with |impressions|.
1. Let |safetyOk| be the result of invoking [=check and deduct safety limit budgets for impression sites=]
with |epoch|,
|impressionSites|,
|topLevelSite|,
|uaContext|,
|options|' [=validated conversion options/epsilon=],
|options|' [=validated conversion options/value=],
|options|'s [=validated conversion options/max value=],
and null.

1. If |budgetOk| is true and |safetyOk| is true, [=set/extend=] |matchedImpressions| with |impressions|.



1. If |matchedImpressions| [=set/is empty=], return the result of invoking
[=create an all-zero histogram=] with
|options|' [=validated conversion options/histogram size=].


1. Set |histogram| to the result of [=fill a histogram with last-n-touch attribution=] with |matchedImpressions|,
|options|' [=validated conversion options/histogram size=],
|options|' [=validated conversion options/value=], and
Expand All @@ -1688,7 +1855,17 @@ To <dfn>do attribution and fill a histogram</dfn>, given
|options|'s [=validated conversion options/max value=],
and |l1Norm|.

1. If |budgetOk| is false, set |histogram| to the result of invoking
1. Let |safetyOk| be the result of invoking [=check and deduct safety limit budgets for impression sites=]
with |currentEpoch|,
|impressionSites|,
|topLevelSite|,
|uaContext|,
|options|' [=validated conversion options/epsilon=],
|options|' [=validated conversion options/value=],
|options|'s [=validated conversion options/max value=],
and |l1Norm|.

1. If |budgetOk| is false or |safetyOk| is false, set |histogram| to the result of invoking
[=create an all-zero histogram=] with |options|' [=validated conversion options/histogram size=].

1. Return |histogram|.
Expand Down
Loading