diff --git a/spec.bs b/spec.bs
index 447ce12..9c13897 100644
--- a/spec.bs
+++ b/spec.bs
@@ -292,6 +292,17 @@ Note: A later algorithm [=asserts=] that, for any [=contribution cache entry=]
before the [=process contributions for a batching scope=] steps are
performed given the entry's [=contribution cache entry/batching scope=].
+APIs exposing Private Aggregation {#apis-exposing-private-aggregation}
+----------------------------------------------------------------------
+
+This section is non-normative.
+
+This API is currently exposed in global scopes defined in the specifications of
+two APIs:
+1. Shared Storage and
+1. Protected Audience (via the
+ monkey patches below).
+
Structures {#structures}
========================
@@ -1185,269 +1196,6 @@ Note: Without this, [=aggregatable reports=] would be subject to delays, making
-Shared Storage API monkey patches {#shared-storage-api-monkey-patches}
-======================================================================
-
-Issue(43): This should be moved to the Shared Storage spec.
-
-Issue: Go through all monkey patches and ensure every definition (including)
- structures that is needed is exported.
-
-
-partial interface SharedStorageWorkletGlobalScope {
- readonly attribute PrivateAggregation privateAggregation;
-};
-
-dictionary SharedStoragePrivateAggregationConfig {
- USVString aggregationCoordinatorOrigin;
- USVString contextId;
- [EnforceRange] unsigned long long filteringIdMaxBytes;
-};
-
-partial dictionary SharedStorageRunOperationMethodOptions {
- SharedStoragePrivateAggregationConfig privateAggregationConfig;
-};
-
-
-The {{SharedStorageWorkletGlobalScope/privateAggregation}} [=getter steps=] are
-to [=get the privateAggregation=] given [=this=].
-
-Add the following algorithm in the subsection
-"Run
-Operation Methods on `SharedStorage`":
-
-
-To obtain the aggregation coordinator given a
-{{SharedStorageRunOperationMethodOptions}} |options|, perform the following
-steps. They return an [=aggregation coordinator=], null or a {{DOMException}}:
-
-1. If
- |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"]
- does not [=map/exist=], return null.
-1. If
- |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"]["{{SharedStoragePrivateAggregationConfig/aggregationCoordinatorOrigin}}"]
- does not [=map/exist=], return null.
-1. Let |url| be the result of running the [=URL parser=] on
- |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"]["{{SharedStoragePrivateAggregationConfig/aggregationCoordinatorOrigin}}"].
-1. If |url| is failure or null, return a new {{DOMException}} with name
- "`SyntaxError`".
-
- Issue: Consider throwing an error if the path is not empty.
-1. Let |origin| be |url|'s [=url/origin=].
-1. If the result of [=determining if an origin is an aggregation coordinator=]
- given |origin| is false, return a new {{DOMException}} with name
- "`DataError`".
-1. Return |origin|.
-
-
-
-
-To obtain the pre-specified report parameters given a
-{{SharedStorageRunOperationMethodOptions}} |options| and a [=browsing context=]
-|context|, perform the following steps. They return a [=pre-specified report
-parameters=], null, or a {{DOMException}}:
-1. If |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"]
- does not [=map/exist=], return null.
-1. Let |privateAggregationConfig| be
- |options|["{{SharedStorageRunOperationMethodOptions/privateAggregationConfig}}"].
-1. Let |contextId| be null.
-1. If |privateAggregationConfig|["{{SharedStoragePrivateAggregationConfig/contextId}}"]
- [=map/exists=], set |contextId| to
- |privateAggregationConfig|["{{SharedStoragePrivateAggregationConfig/contextId}}"].
-1. If |contextId|'s [=string/length=] is greater than 64, return a new
- {{DOMException}} with name "`DataError`".
-1. Let |filteringIdMaxBytes| be the [=default filtering ID max bytes=].
-1. If |privateAggregationConfig|["{{SharedStoragePrivateAggregationConfig/filteringIdMaxBytes}}"]
- [=map/exists=], set |filteringIdMaxBytes| to
- |privateAggregationConfig|["{{SharedStoragePrivateAggregationConfig/filteringIdMaxBytes}}"].
-1. If |filteringIdMaxBytes| is not [=set/contained=] in the [=valid filtering ID
- max bytes range=], return a new {{DOMException}} with name "`DataError`".
-1. If |context|'s [=browsing context/fenced frame config instance=] is not null:
- 1. If |filteringIdMaxBytes| is not the [=default filtering ID max bytes=] or
- |contextId| is not null, return a new {{DOMException}} with name
- "`DataError`".
-1. Return a new [=pre-specified report parameters=] with the items:
- : [=pre-specified report parameters/context ID=]
- :: |contextId|
- : [=pre-specified report parameters/filtering ID max bytes=]
- :: |filteringIdMaxBytes|
-
-
-
-The {{SharedStorageWorklet}}'s {{SharedStorageWorklet/run()}} method steps are
-modified in four ways. First, add the following steps just after step 4
-("[=Assert=]: window is a [=Window=]"), renumbering later
-steps as appropriate:
-
-5. Let |context| be window's [=Window/browsing context=].
-1. If |context| is null, then return [=a promise rejected with=] a
- {{TypeError}}.
-1. Let |preSpecifiedParams| be the result of [=obtaining the pre-specified
- report parameters=] given |options| and |context|.
-1. If |preSpecifiedParams| is a {{DOMException}}, return [=a promise rejected
- with=] |preSpecifiedParams|.
-1. Let |aggregationCoordinator| be the result of [=obtaining the aggregation
- coordinator=] given |options|.
-1. If |aggregationCoordinator| is a {{DOMException}}, return [=a promise
- rejected with=] |aggregationCoordinator|.
-
-
-Second, add the following steps in the nested scope just after "Let |operation|
-be |operationMap|[|name|]." (renumbering later steps as appropriate):
-
-2. Let |batchingScope| be a new [=batching scope=].
-1. Let debugScope be a new [=debug scope=].
-1. Let |privateAggregationTimeout| be null.
-1. Let |isDeterministicReport| be false.
-1. If |preSpecifiedParams| is not null:
- 1. Set |isDeterministicReport| to the result of [=determining if a report
- should be sent deterministically=] given |preSpecifiedParams|.
- 1. If |isDeterministicReport|:
- 1. Set |privateAggregationTimeout| to the [=current wall time=] plus the
- [=deterministic operation timeout duration=].
- 1. [=Set the pre-specified report parameters for a batching scope=] given
- |preSpecifiedParams| and |batchingScope|.
-1. If |aggregationCoordinator| is not null, [=set the aggregation coordinator
- for a batching scope=] given |aggregationCoordinator| and |batchingScope|.
-
-
-
-Third, add the following steps in the same nested scope just before the current
-penultimate step ("If options
-[=map/contains=] data", renumbering the last step as
-appropriate):
-
-1. Let |hasRunPrivateAggregationCompletionTask| be false.
-1. Let |privateAggregationCompletionTask| be an algorithm to perform the
- following steps:
- 1. If |hasRunPrivateAggregationCompletionTask|, return.
- 1. Set |hasRunPrivateAggregationCompletionTask| to true.
- 1. [=Mark a debug scope complete=] given debugScope.
- 1. [=Process contributions for a batching scope=] given
- batchingScope, outsideSettings'
- [=environment settings object/origin=], "shared-storage
"
- and |privateAggregationTimeout|.
-1. If isDeterministicReport>, run the following steps [=in
- parallel=]:
- 1. Wait until |privateAggregationTimeout|.
- 1. Run |privateAggregationCompletionTask|.
-
-
-
-Finally, at the end of the same nested scope, add the following step:
-
-9. When the above [=call=] returns, perform the following steps:
- 1. Run privateAggregationCompletionTask.
-
-
-
-The {{SharedStorageWorklet}}'s {{SharedStorageWorklet/selectURL()}} method steps
-are modified in three ways. First, add the following steps just after step 6
-("If context is null..."), renumbering later steps:
-
-7. Let |preSpecifiedParams| be the result of [=obtaining the pre-specified
- report parameters=] given |options| and context.
-1. If |preSpecifiedParams| is a {{DOMException}}, return [=a promise rejected
- with=] |preSpecifiedParams|.
-1. Let |aggregationCoordinator| be the result of [=obtaining the aggregation
- coordinator=] given |options|.
-1. If |aggregationCoordinator| is a {{DOMException}}, return [=a promise
- rejected with=] |aggregationCoordinator|.
-
-
-Second, add the following steps in the nested scope just after "Let |operation|
-be |operationMap|[|name|]." (renumbering later steps as appropriate):
-
-2. Let |batchingScope| be a new [=batching scope=].
-1. Let |debugScope| be a new [=debug scope=].
-1. Let |privateAggregationTimeout| be null.
-1. Let |hasRunPrivateAggregationCompletionTask| be false.
-1. Let |privateAggregationCompletionTask| be an algorithm to perform the
- following steps:
- 1. If |hasRunPrivateAggregationCompletionTask|, return.
- 1. Set |hasRunPrivateAggregationCompletionTask| to true.
- 1. [=Mark a debug scope complete=] given |debugScope|.
- 1. [=Process contributions for a batching scope=] given
- |batchingScope|, outsideSettings'
- [=environment settings object/origin=], "shared-storage
"
- and |privateAggregationTimeout|.
-1. If |aggregationCoordinator| is not null, [=set the aggregation coordinator
- for a batching scope=] given |aggregationCoordinator| and |batchingScope|.
-1. If |preSpecifiedParams| is not null:
- 1. Let |isDeterministicReport| be the result of [=determining if a report
- should be sent deterministically=] given |preSpecifiedParams|.
- 1. If |isDeterministicReport|:
- 1. Set |privateAggregationTimeout| to the [=current wall time=] plus the
- [=deterministic operation timeout duration=].
- 1. [=Set the pre-specified report parameters for a batching scope=] given
- |preSpecifiedParams| and |batchingScope|.
- 1. If |isDeterministicReport|, run the following steps [=in parallel=]:
- 1. Wait until |privateAggregationTimeout|.
- 1. Run |privateAggregationCompletionTask|.
-
-
-Finally, at the end of the same nested scope, add the following steps:
-
-13. Run privateAggregationCompletionTask.
-
-
-
-Issue: Once
- shared-storage/88 is resolved, align the above monkey patches with how
- `keepAlive` is handled at operation completion.
-
-The {{Worklet/addModule()}} steps are modified to add a new step just before
-the final step ("Return promise."), renumbering the last step
-as appropriate:
-
-7. If |this| is a {{SharedStorageWorklet}}, [=upon fulfillment=] of |promise| or
- [=upon rejection=] of |promise|, run the following steps:
- 1. Let |globalScopes| be |this|'s [=Worklet/global scopes=].
- 1. [=Assert=]: |globalScopes|' [=list/size=] equals 1.
- 1. Let |privateAggregationObj| be |globalScopes|[0]'s
- {{SharedStorageWorkletGlobalScope/privateAggregation}}.
- 1. Set |privateAggregationObj|'s [=PrivateAggregation/allowed to use=] to
- the result of determining whether [=this=]'s [=relevant global
- object=]'s [=associated document=] is [=allowed to use=] the
- "[=private-aggregation=]
" [=policy-controlled feature=].
-
- Issue: Consider adding an early return here (and equivalently for
- Protected Audience) if the permissions policy check is made first.
- 1. Set |privateAggregationObj|'s [=PrivateAggregation/scoping details=] to a
- new [=scoping details=] with the items:
- : [=scoping details/get batching scope steps=]
- :: An algorithm that returns the [=batching scope=] that is scheduled to
- be passed to [=process contributions for a batching scope=] when the
- call currently executing in |scope| returns.
- : [=scoping details/get debug scope steps=]
- :: An algorithm that returns the [=debug scope=] that is scheduled to be
- passed to [=mark a debug scope complete=] when the call currently
- executing in |scope| returns.
-
- Note: Multiple operation invocations can be in-progress at the same
- time, each with a different batching scope and debug scope. However,
- only one can be currently executing.
-
-
-
-Issue: Once
- shared-storage/89 is resolved, align the above monkey patch with how
- access to `sharedStorage` is prevented in
- {{SharedStorageWorkletGlobalScope}}s until {{Worklet/addModule()}}'s initial
- execution is complete.
-
-Note: This extends Shared Storage's existing {{Worklet/addModule()}}
-
- monkey patch.
-
-[=Implementation-defined=] values {#shared-storage-implementation-defined-values}
----------------------------------------------------------------------------------
-
-Deterministic operation timeout duration is a non-negative
-[=duration=] that controls how long a Shared Storage operation may make Private
-Aggregation contributions if it is triggering a deterministic report and,
-equivalently, when that report should be sent after the operation begins.
-
Protected Audience API monkey patches {#protected-audience-api-monkey-patches}
==============================================================================