Feature Policy

Draft Community Group Report,

This version:
https://wicg.github.io/feature-policy/
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Google)

Abstract

This specification defines a mechanism that allows developers to selectively enable and disable use of various browser features and APIs.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction

The web-platform provides an ever-expanding set of features and APIs, offering richer functionality, better developer ergonomics, and improved performance. However, a missing piece is the ability for the developer to selectively enable, disable, or modify the behavior of some of these browser features and APIs within their application:

  1. The developer may want to selectively disable access to certain browser features and APIs to "lock down" their application, as a security or performance precaution, to prevent own and third-party content executing within their application from introducing unwanted or unexpected behaviors within their application.
  2. The developer may want to selectively enable access to certain browser features and APIs which may be disabled by default - e.g. some features may be disabled by default in embedded context unless explicitly enabled; some features may be subject to other policy requirements.
  3. The developer may want to use the policy to assert a promise to a client or an embedder about the use—or lack of thereof—of certain features and APIs. For example, to enable certain types of "fast path" optimizations in the browser, or to assert a promise about conformance with some requirements set by other embedders - e.g. various social networks, search engines, and so on.

This specification defines a feature policy mechanism that addresses the above use cases.

2. Examples

SecureCorp Inc. wants to disable use of Vibration and Geolocation APIs within their application. It can do so by delivering the following HTTP response header to define a feature policy:

Feature-Policy: {"vibrate": [], "geolocation": []}

By specifying an empty list of origins, the specified features will be disabled for all browsing contexts, regardless of their origin.

SecureCorp Inc. wants to disable use of Geolocation API within all browsing contexts except for its own origin and those whose origin is "https://example.com". It can do so by delivering the following HTTP response header to define a feature policy:

Feature-Policy: {"geolocation": ["self", "https://example.com"]}

The allowlist is a list of one or more origins, which can include the application’s origin, optionally with the keyword "self", and any third-party origin.

SecureCorp Inc. is hosting an application on "https://example.com" and wants to disable camera and microphone input on its own origin but enable it for a whitelisted embedee ("https://other.com"). It can do so by delivering the following HTTP response header to define a feature policy:

Feature-Policy: {"camera": ["https://other.com"], "microphone": ["https://other.com"]}

Some features are disabled by default in embedded contexts. The enable policy allows the application to selectively enable such features for whitelisted origins.

FastCorp Inc. wants to disable geolocation for all cross-origin child frames, except for a specific iframe. It can do so by delivering the following HTTP response header to define a feature policy:

Feature-Policy: {"geolocation": ["self"]}

and including an "allow" attribute on the iframe element:

<iframe src="https://other.com/map" allow="geolocation"></iframe>

Iframe attributes can selectively enable features in certain frames, and not in others, even if those contain documents from the same origin.

[HTML5] defines a sandbox attribute for iframe elements that allows developers to reduce the risk of including potentially untrusted content by imposing restrictions on content’s abilities - e.g. prevent it from submitting forms, running scripts and plugins, and more. The sandbox directive defined by [CSP2] extends this capability to any resource, framed or not, to ask for the same set of restrictions - e.g. via an HTTP response header (Content-Security-Policy: sandbox). These mechanisms enable the developer to:

However, there are several limitations to the above mechanism: the developer cannot automatically apply a policy across all contexts, which makes it hard or impossible to enforce consistently in some cases (e.g. due to third-party content injecting frames, which the developer does not control); there is no mechanism to selectively enable features that may be off by default; the sandbox mechanism uses a whietlist approach which is impossible to extend without compatibility risk.

Feature Policy is intended to be used in combination with the sandbox mechanism (i.e. it does not duplicate feature controls already covered by sandbox), and provides an extensible mechanism that addresses the above limitations.

4. Framework

4.1. Policy-controlled Features

A policy-controlled feature is an API or behaviour which can be enabled or disabled in a document or web worker by referring to it in a feature policy.

For brevity, policy-controlled features will often be referred to in this document simply as "Features". Unless otherwise indicated, the term "feature" refers to policy-controlled features. Other specification, defining such features, should use the longer term to avoid any ambiguity.

Policy-controlled features have a feature name keyword, which is a token used in policy directives, and a default allowlist, which defines whether the policy-controlled feature is available to top-level documents, and how access to that feature is inherited by cross-origin frames.

A user agent has a set of supported features, which is the set of features which it allows to be controlled through policies. User agents are not required to support every feature.

The policy-controlled features themselves are not themselves part of this framework. A non-normative list of currently-defined features is included as an appendix to this specification.

4.2. Policies

A Document or WorkerGlobalScope has a feature policy, which consists of:

4.3. Inherited policies

Each document in a frame tree inherits a set of policies from its parent frame, or in the case of the top-level document, from the defined defaults for each policy-controlled feature. This inherited policy set determines the initial state (enabled or disabled) of each feature, and whether it can be controlled by a declared policy in the document.

In a Document in a top-level browsing context, or in a WorkerGlobalScope, the inherited feature set is based on defined defaults for each feature.

In a Document in a nested browsing context, the inherited feature set is based on the parent document’s feature policy, as well as any allow attributes defined on the browsing context container.

An inherited policy declares a feature as Enabled or Disabled.

An inherited policy set for a Document or WorkerGlobalScope is the set of inherited policies for each feature available in that scope.

4.4. Declared policies

A declared policy is an ordered map from features to allowlists.

A Document or WorkerGlobalScope is considered feature-policy-aware if it has a declared policy which is not empty.

A Document or WorkerGlobalScope is which is not feature-policy-aware is considered feature-policy-oblivious.

4.5. Header policies

A header policy is a list of policy directives delivered via an HTTP header with the document. This forms the document’s feature policy’s declared policy.

4.6. Container policies

In addition to the header policy, each frame has a container policy, which is a policy directive, which may be empty. The container policy can set by attributes on the browsing context container.

The container policy for a frame influences the inherited policy of any document loaded into that frame. (See §8.8 Define an inherited policy for feature)

Currently, the container policy cannot be set directly, but is indirectly set by iframe "allowfullscreen", "allowpaymentrequest", and "allow" attributes. Future revisions to this spec may introduce a mechanism to explicitly declare the full container policy.

4.7. Policy directives

A policy directive is an ordered map, mapping feature names to corresponding allowlists of origins.

A policy directive is represented in HTTP headers and HTML attributes as the string serialization of a JSON object.

The following sections define the set of known feature names. Future versions of this document may define additional such names, as user agents ignore policy directives with unrecognized names when parsing the policy.

4.8. Allowlists

A feature policy allowlist is a set of origins. An allowlist may be empty, in which case it does not match any origin, or it may contain a list of origins, or it may match every origin. When defining an allowlist in a policy, the special string "self" may be used, which refers to the origin of the document which the policy is associated with.

An allowlist matches an origin o if it matches every origin, or if it contains an origin which is same origin-domain with o.

4.9. Default Allowlists

Every policy-controlled feature has a default allowlist, which is an allowlist. The default allowlist controls the origins which are allowed to access the feature when used in a top-level document with no declared policy, and also determines whether access to the feature is automatically delegated to child documents.

Features are currently defined to have one of these three default allowlists:

["*"]
The feature is allowed at the top level by default, and when allowed, is allowed by default to documents in child frames.
["self"]
The feature is allowed at the top level by default, and when allowed, is allowed by default to same-origin domain documents in child frames, but is disallowed by default in cross-origin documents in child frames.
[]
The feature is disallowed at the top level by default, and is also disallowed by default to documents in child frames.

5. Feature Policy Serialization

5.1. JSON serialization

Policy Directives are represented in HTTP headers and in HTML attributes as JSON text [RFC7159].

policy-directive-json must match:

origin is the ASCII serialization of an origin.

feature-name is a JSON string.

The string "self" may be used as an origin in an allowlist. When it is used in this way, it will refer to the origin of the document which contains the feature policy.
The begin-array and end-array marks ("[" and "]") are semantically part of the JSON representation of the declared policy, but they do not appear in the HTTP headers. Those characters are added to the HTTP headers before parsing, so that the entire set of concatenated headers are parsed as a single array.

6. Delivery

6.1. Feature-Policy HTTP Header Field

The Feature-Policy HTTP header field can be used in the response (server to client) to communicate the feature policy that should be enforced by the client.

The header’s value is the §5.1 JSON serialization of one or more policy directives:.

FeaturePolicy = policy-directive-json *("," policy-directive-json)

When the user agent receives a Feature-Policy header field, it MUST process and enforce the serialized policy as described in §7.1 Integration with HTML.

6.2. The allow attribute of the iframe element

partial interface HTMLIFrameElement {
    [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList allow;
};

iframe elements have an "allow" attribute, which contains an unordered set of unique space-separated tokens that are ASCII case-insensitive. The allowed values are names of features. Unrecognized values must be ignored.

When not empty, the "allow" attribute will result in adding an allowlist for each recognized feature to the frame’s container policy, when it is contructed.

The allowlist will contain a single origin, which is the origin of the URL in the iframe’s src attribute.

6.3. Additional attributes to support legacy features

Some features controlled by Feature Policy have existing iframe attributes defined. This specification redefines these attributes to act as declared policies for the iframe element.

6.3.1. allowfullscreen

The "allowfullscreen" iframe attribute controls access to requestFullscreen().

If the iframe element has an "allow" attribute whose value contains the token "fullscreen", then the "allowfullscreen attribute must have no effect.

Otherwise, the presence of an "allowfullscreen" attribute on an iframe will result in adding an allowlist of ["*"] for the "fullscreen" feature to the frame’s container policy, when it is constructed.

This is different from the behaviour of <iframe allow="fullscreen">, and is for compatibility with existing uses of allowfullscreen. If allow="fullscreen" and allowfullscreen are both present on an iframe element, then the more restrictive allowlist of allow="fullscreen" will be used.

6.3.2. allowpaymentrequest

The "allowpaymentrequest" iframe attribute controls access to Payment interface.

If the iframe element has an "allow" attribute whose value contains the token "payment", then the "allowpaymentrequest attribute must have no effect.

Otherwise, the presence of an "allowpaymentrequest" attribute on an iframe will result in adding an allowlist of ["*"] for the "payment" feature to the frame’s container policy, when it is constructed.

This is different from the behaviour of <iframe allow="payment">, and is for compatibility with existing uses of allowpaymentrequest. If allow="payment" and allowpaymentrequest are both present on an iframe element, then the more restrictive allowlist of allow="payment" will be used.

7. Integrations

This document defines a set of algorithms which other specifications will use in order to implement the restrictions which Feature Policy defines. The integrations are outlined here for clarity, but those external documents are the normative references which ought to be consulted for detailed information.

7.1. Integration with HTML

  1. Document and WorkerGlobalScope objects have a Feature Policy, which is populated via the §8.7 Initialize global’s Feature Policy from response algorithm that is called during the "Initialising a new Document object" and "Run a Worker" algorithms.
  2. Replace the existing step 12 of "Initialising a new Document object" with the following step:
  3. A feature policy is enforced for a Document or WorkerGlobalScope by setting it as the Document or WorkerGlobalScope's Feature Policy.
  4. The "allowed to use" algorithm calls into §8.9 Is feature enabled in global for origin?, as follows:

    1. Replace the current steps #3 and #4 with the following step:
      • If Document’s feature policy enables the feature indicated by allowattribute for the origin of Document, then return true.
Monkey-patching! As soon as we know that this is the direction we wish to pursue, upstream all of this.

8. Algorithms

8.1. Process response policy

Given a response (response) and global object (global), this algorithm returns a declared feature policy.

  1. Abort these steps if the response’s header list does not contain a header whose name is "Feature-Policy".
  2. Let header be the concatenation of the values of all header fields in response’s header list whose name is "Feature-Policy", separated by commas (according to [RFC7230, 3.2.2]).
  3. Add a leading "[" U+005B character, and a trailing "]" U+005D character to header.
  4. Let feature policy be the result of executing §8.2 Parse header from value and origin on header and global’s origin.
  5. Return feature policy.

8.2. Parse header from value and origin

Given a string (value) and an origin (origin) this algorithm will return a declared feature policy.

  1. Let policy be an empty list.
  2. Let list be the result of parsing value with a JSON Parser. If value cannot be parsed, return policy.
    Note: If value can be parsed, list must be a valid JSON Array.
  3. For each element of list:
    1. If element is not a JSON object, then continue.
    2. Let directive be the result of executing §8.3 Parse policy directive from value and origin on element and origin
    3. Run §8.4 Merge directive with declared policy on directive and policy.
  4. Return policy.

8.3. Parse policy directive from value and origin

Given a JSON object (value) and an origin (origin) this algorithm will return a policy directive.

  1. Let directive be an empty ordered map.
  2. For each keytargetlist of value:
    1. If key is not equal to the name of any recognized policy-controlled feature, then continue.
    2. Let feature be the policy-controlled feature named by key.
    3. If targetlist is not an array, then continue.
    4. Let allowlist be a new allowlist.
    5. If targetlist contains the string "*", set allowlist to match every origin.
    6. Otherwise, for each element in targetlist:
      1. If element is an ASCII case-insensitive match for "self", let result be origin.
      2. Otherwise, let result be the result of executing the URL parser on element.
      3. If result is not failure:
        1. Let target be the origin of result.
        2. If target is not an opaque origin, append target to allowlist.
    7. Set directive[feature] to allowlist.
  3. Return directive

8.4. Merge directive with declared policy

Given a policy direcive (directive) and a declared policy (policy), this algorithm will modify policy to account for the new directive.

  1. For each featureallowlist of directive:
    1. If policy does not contain an allowlist for feature, then set policy[feature] to allowlist.

8.5. Process feature policy attributes

Given an element element, this algorithm returns a declared feature policy, which may be empty.

  1. Let policy be a new policy directive.
  2. Let valid-features be the result of running Parse allow attribute on the value of element’s allow attribute.
  3. For each feature in valid-features:
    1. If policy does not contain an allowlist for feature:
      1. Construct a new declaration for feature, whose allowlist is origin.
      2. Add declaration to policy.
  4. If element is an iframe element:
    1. If element’s allowfullscreen attribute is specified, and policy does not contain an allowlist for fullscreen,
      1. Construct a new declaration for fullscreen, whose allowlist matches all origins.
      2. Add declaration to policy.
    2. If element’s allowpaymentrequest attribute is specified, and policy does not contain an allowlist for payment,
      1. Construct a new declaration for payment, whose allowlist matches all origins.
      2. Add declaration to policy.
  5. Return policy.

8.6. Parse allow attribute

Given a list, this algorithm returns a list of feature name keywords, which may be empty.

  1. Let valid-features be an empty list.
  2. If list is null or empty, return valid-features.
  3. For each item of list:
    1. Convert item to ASCII-lowercase.
    2. If item matches a defined feature name which is not present in valid-features,
      1. Append item to valid-features.
  4. Return valid-features.

8.7. Initialize global’s Feature Policy from response

Given a response (response) and a global object (global), this algorithm populates global’s Feature Policy

  1. Let inherited policies be a new ordered map.
  2. Let declared policies be a new ordered map.
  3. For each feature supported,
    1. Let isInherited be the result of running §8.8 Define an inherited policy for feature on feature and global.
    2. Set inherited policies[feature] to isInherited.
  4. Let d be the result of executing §8.1 Process response policy on response and global.
  5. For each feature -> allowlist of d:
    1. If inherited policies[feature] is true, then set declared policies[feature] to allowlist.
  6. Let policy be a new feature policy, with inherited policy set inherited policies and declared policy set declared policies.
  7. Enforce the policy policy.

8.8. Define an inherited policy for feature

Given a string (feature) and a browsing context (context), this algorithm returns the inherited policy for that feature.

  1. If context is a nested browsing context:
    1. Let parent be context’s parent browsing context’s active document.
    2. Let origin be parent’s origin
    3. Let container policy be the result of running §8.5 Process feature policy attributes on context’s browsing context container.
    4. If feature is a key in container policy:
      1. If the allowlist for feature in container policy matches origin, and parent’s inherited policy for feature is Enabled, return Enabled.
      2. Otherwise return Disabled.
    5. Otherwise, if feature is allowed by parent’s feature policy for origin, return Enabled.
    6. Otherwise, return Disabled.
  2. Otherwise, return Enabled.

8.9. Is feature enabled in global for origin?

Given a string (feature) and a global object (global), and an origin (origin), this algorithm returns "Disabled" if feature should be considered disabled, and "Enabled" otherwise.

  1. Let policy be global’s Feature Policy
  2. If policy’s inherited policy for feature is Disabled, return "Disabled".
  3. If feature is present in policy’s declared policy:
    1. If the allowlist for feature in policy’s declared policy matches origin, then return "Enabled".
    2. Otherwise return "Disabled".
  4. If feature’s default allowlist is ["*"], return "Enabled".
  5. If feature’s default allowlist is ["self"], and origin is same origin-domain with global’s active document’s origin, return "Enabled".
  6. Return "Disabled".

9. IANA Considerations

The permanent message header field registry should be updated with the following registration [RFC3864]:

Header field name
Feature-Policy
Applicable protocol
http
Status
standard
Author/Change controller
W3C
Specification document
Feature Policy API

10. Privacy and Security

TODO

Appendix A: Policy-Controlled Features

This appendix is a reference to currently-defined valid policy-controlled features, their feature name keywords, and their effect effect when applied via a directive as part of a feature policy. This reference is non-normative; the actual definitions are given in subsections below.

As soon as possible, move the definitions to their respective controlling specifications, and link to those specifications from this one. This spec shouldn’t be required to enumerate every policy-controlled feature.
Feature name Default allowlist Brief description
camera self Controls access to video input devices.
eme self Controls whether requestMediaKeySystemAccess() is allowed.
fullscreen self Controls whether requestFullscreen() is allowed.
geolocation self Controls access to Geolocation interface.
microphone self Controls access to audio input devices.
midi self Controls access to requestMIDIAccess() method.
payment self Controls access to PaymentRequest interface.
speaker self Controls access to audio output devices.
vibrate self Controls access to vibrate() method.

Feature Definitions

camera

The camera feature controls access to video input devices requested through the NavigatorUserMedia interface ([MEDIACAPTURE-API]).

If disabled in a document, then calls to getUserMedia() MUST NOT grant access to video input devices in that document.

The feature name for camera is "camera"

The default allowlist for camera is ["self"].

eme

The eme feature controls whether encrypted media extensions [encrypted-media] are available.

If disabled in a document, the promise returned by requestMediaKeySystemAccess() must reject with a NotSupportedError.

The feature name for eme is "eme"

The default allowlist for eme is ["self"].

fullscreen

The fullscreen feature controls whether the requestFullscreen() method ([WHATWG-FULLSCREEN]) is allowed to request fullscreen.

If disabled in any document, the document will not be allowed to use fullscreen. If enabled, the document will be allowed to use fullscreen.

The feature name for fullscreen is "fullscreen"

The default allowlist for fullscreen is ["self"].

geolocation

The geolocation feature controls whether the current document is alowed to use the Geolocation interface ([GEOLOCATION-API]).

If disabled in any document, calls to both getCurrentPosition and watchPosition must result in the error callback being invoked with PERMISSION_DENIED.

The feature name for geolocation is "geolocation"

The default allowlist for geolocation is ["self"].

microphone

The microphone feature controls access to audio input devices requested through the NavigatorUserMedia interface ([MEDIACAPTURE-API]).

If disabled in a document, then calls to getUserMedia() MUST NOT grant access to audio input devices in that document.

The feature name for microphone is "microphone"

The default allowlist for microphone is ["self"].

midi

The midi feature controls whether the current document is allowed to use the requestMIDIAccess() method ([WEBMIDI]).

If disabled in a document, the promise returned by requestMIDIAccess must reject with a DOMException parameter.

The feature name for midi is "midi"

The default allowlist for midi is ["self"].

payment

The payment feature controls whether the current document is allowed to use the PaymentRequest interface ([PAYMENT-REQUEST]).

If disabled in a document, then calls to the PaymentRequest constuctor MUST throw a SecurityError.

The feature name for payment is "payment"

The default allowlist for payment is ["self"].

speaker

The speaker feature controls access to audio output devices requested through the NavigatorUserMedia interface ([audio-output]).

If disabled in a document, then calls to getUserMedia() MUST NOT grant access to audio output devices in that document.

The feature name for speaker is "speaker"

The default allowlist for speaker is ["self"].

vibrate

The vibrate feature controls whether the vibrate() method ([VIBRATION]) is allowed to cause device vibration.

If disabled in a document, then calls to the vibrate() method should silently do nothing. If enabled, the browser may allow the device to vibrate.

The feature name for vibrate is "vibrate"

The default allowlist for vibrate is ["self"].

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSP3]
Mike West. Content Security Policy Level 3. URL: https://w3c.github.io/webappsec-csp/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. Registration Procedures for Message Header Fields. September 2004. Best Current Practice. URL: https://tools.ietf.org/html/rfc3864
[RFC7159]
T. Bray, Ed.. The JavaScript Object Notation (JSON) Data Interchange Format. March 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7159
[WebIDL]
Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. URL: https://heycam.github.io/webidl/
[WHATWG-DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[WHATWG-URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/

Informative References

[AUDIO-OUTPUT]
Justin Uberti; Guido Urdaneta. Audio Output Devices API. URL: https://w3c.github.io/mediacapture-output/
[CSP2]
Mike West; Adam Barth; Daniel Veditz. Content Security Policy Level 2. URL: https://w3c.github.io/webappsec-csp/
[ENCRYPTED-MEDIA]
David Dorwin; et al. Encrypted Media Extensions. URL: https://w3c.github.io/encrypted-media/
[GEOLOCATION-API]
Andrei Popescu. Geolocation API Specification 2nd Edition. URL: http://dev.w3.org/geo/api/spec-source.html
[HTML5]
Ian Hickson; et al. HTML5. URL: https://www.w3.org/html/wg/drafts/html/master/
[MEDIACAPTURE-API]
Dzung D Tran; Ilkka Oksanen; Ingmar Kliche. The Media Capture API. 3 September 2010. ED. URL: http://dev.w3.org/2009/dap/camera/Overview-API.html
[PAYMENT-REQUEST]
Adrian Bateman; Zach Koch; Roy McElmurry. Payment Request API. URL: https://w3c.github.io/browser-payment-api/
[VIBRATION]
Anssi Kostiainen. Vibration API (Second Edition). URL: https://w3c.github.io/vibration/
[WEBMIDI]
Chris Wilson; Jussi Kalliokoski. Web MIDI API. URL: https://webaudio.github.io/web-midi-api/
[WHATWG-FULLSCREEN]
Anne van Kesteren. Fullscreen API Standard. Living Standard. URL: https://fullscreen.spec.whatwg.org/

IDL Index

partial interface HTMLIFrameElement {
    [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList allow;
};

Issues Index

Monkey-patching! As soon as we know that this is the direction we wish to pursue, upstream all of this.
TODO
As soon as possible, move the definitions to their respective controlling specifications, and link to those specifications from this one. This spec shouldn’t be required to enumerate every policy-controlled feature.