diff --git a/wai/extensions/capability-constraints.md b/wai/extensions/capability-constraints.md new file mode 100644 index 000000000..6ac4c63b7 --- /dev/null +++ b/wai/extensions/capability-constraints.md @@ -0,0 +1,84 @@ +# WAI Extension: Capability Constraints + +> Status: Draft. Makes capability dispatch (WAI SPEC.md §4) a **precondition +> check** rather than a binary claim, by ingesting the constraint-set grammar and +> register pattern the broadcast-IP world already ratified. No transport, no +> registry service, no negotiation protocol — it evaluates values WAI already +> carries. +> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174. + +## 1. The problem: support is not binary + +WAI dispatch treats a capability as present or absent: a sink either claims +`cap` or does not. Real sinks are not like that. A decoder supports a codec *to +a level* — up to a resolution, a frame rate, a bit depth, a profile. "This +capability, but only to 4K60 10-bit, this profile" is the normal case and is +currently unexpressible. + +The consequence is that partial support fails at **decode time** rather than at +**selection time**. A sink advertises the capability, receives an object it +cannot actually handle, and fails after committing to the bytes. Worse, WAI's +rendition selection has nothing to evaluate, so it defers to a deployer policy +the specification never states. + +## 2. Constraint sets + +A **constraint set** is an ORed set of constraints over named parameters, each +constraint being an enumeration, a minimum, a maximum, or a combination. A sink +satisfies a capability when it advertises `cap` **and** the object's declared +parameters satisfy at least one of the registered constraint sets for `cap`. + +This grammar is deliberately not invented here. It is the shape AMWA's Receiver +and Sender Capabilities specifications (BCP-004-01 and BCP-004-02, both v1.0.0) +use, with parameters drawn from a public register rather than a bespoke schema +per implementation. WAI ingests the **grammar and the register pattern**, not the +transport or the discovery model those specifications sit in. + +- A capability registration **MAY** publish one or more constraint sets. A + capability with none is unconstrained, which is the current behaviour and + remains valid. +- A sink **MUST** evaluate constraint sets **before** dispatch, not during it. + The point is to move the failure earlier; a check performed at decode has + bought nothing. +- A sink **MUST NOT** advertise a capability whose constraint sets it cannot + evaluate. Advertising a capability while ignoring its constraints is the + binary behaviour this extension exists to replace. +- Where an object's declared parameters satisfy no set, the sink **MUST** treat + the capability as unsupported for that object — not as a decode error, and not + as a reason to attempt it anyway. + +## 3. Parameters and the register + +Parameters are named in a register, so two implementations constrain the same +property under the same name. WAI adopts the pattern; it does not adopt the +existing register wholesale, for a reason worth stating plainly: + +**The ratified registers are broadcast-essence-shaped.** They cover media type, +frame rate, colour sampling, bit depth, codec profile — which serves WAI's +conventional media capabilities and nothing else. There are no entries for the +neural, quantum, world or haptic families. Those register entries **WAI must +author itself**, and until it does, those capabilities remain unconstrained under +§2, which is the honest state rather than a pretended one. + +- A parameter name **MUST** resolve in a register. An implementation-local name + is not a constraint anyone else can evaluate. +- WAI-authored parameters **MUST** be namespaced so they cannot collide with + entries authored elsewhere. + +## 4. What this is not + +- It is **not** a negotiation protocol. There is no pre-flight exchange, no + controller, and no registry service. Capability-plus-budget binding before + execution is already owned by JCP, and duplicating it here would put two + mechanisms in the tree for one job. +- It is **not** a transport concern. Constraint evaluation reads values the + object already declares. +- It is **not** an energy mechanism. A constraint says what a sink can decode, + never what it should spend. + +## 5. Framing + +The grammar is thin — close to a JSON-Schema subset — and that is fine. The value +is not expressiveness; it is that a ratified, register-backed way of saying +"supported, to here" already exists, and WAI's dispatch is strictly worse for +having only "supported". diff --git a/wai/extensions/unidirectional-delivery.md b/wai/extensions/unidirectional-delivery.md new file mode 100644 index 000000000..4339734e4 --- /dev/null +++ b/wai/extensions/unidirectional-delivery.md @@ -0,0 +1,92 @@ +# WAI Extension: Unidirectional Delivery + +> Status: Draft. Covers bearers with **no return path** — terrestrial broadcast, +> satellite, and multicast object carriage — where the sink receives and can +> never answer. Generalised from deployed national early-warning systems, which +> are the only place these seams are currently exercised at scale. +> WAI defines no bearer here and none of this requires one. +> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174. + +## 1. What breaks without a return path + +Three assumptions in the tree quietly presume the sink can talk back: + +- [`jwp-receipts`](jwp-receipts.md) assumes relay-chain linkage throughout, and + a chain implies hops that report. +- Targeting presumes the source can learn something about the sink. +- Pre-emption — an object that must displace what is playing — has no signer + class, because nothing in WAI has needed to assert authority over a sink + before. + +None of these is repaired by defining a bearer. Each is a seam that can be +specified transport-independently, and each is specified below at the strength it +actually holds — which in one case is considerably weaker than it looks. + +## 2. Sink-evaluated predicates + +A **predicate capability** carries, in the object, a condition the **sink** +evaluates against locally-held state the source never learns. The canonical +deployed instance is geographic: an object is relevant to a region, the receiver +holds its own location, and the source is told nothing. + +The determinism contract is *predicate-equivalence*, in the shape +[`state-feeds`](state-feeds.md) §3 uses: two conforming sinks holding the same +local state **MUST** reach the same verdict on the same predicate. + +- A predicate **MUST** be a total function of the object and the sink's declared + state class. A predicate that can consult anything else is not evaluable + twice. +- A predicate **MUST NOT** be able to cause a request. The moment evaluation + emits a signal, the privacy property is gone and this is ordinary targeting. + +**The specifiable property is determinism and auditability, not enforcement.** +Every sink on the bearer receives every byte, and a sink can lie about its own +state. Nothing here prevents that and nothing here should claim to. The real +claim is narrow and worth having: **the source learns nothing** — which is the +dual of source-side targeting, where the source learns everything and the sink is +told nothing. + +## 3. Authority and pre-emption + +Pre-emption is the highest-authority instruction a media object can carry: it +displaces what a person chose to watch. WAI has no signer class for it, so today +an object either has no such field or has one anyone may set. + +- An object asserting pre-emption **MUST** carry a priority field **and** be + signed by a key the sink holds in a **trust anchor** for that assertion. +- The trust anchor **MUST** be sink-held and provisioned out of band. A trust + anchor delivered over the bearer it authorises is not a trust anchor. +- A sink **MUST NOT** act on pre-emption from an unanchored key, and **MUST NOT** + treat a valid signature alone as authority — signature validity establishes who + signed, never that they were entitled to. +- Authority **MUST NOT** be inferred from position in the delivery chain. The + entity that transmits is not thereby entitled to interrupt. + +## 4. Detached receipts + +A unidirectional bearer cannot carry a receipt back, so `jwp-receipts`' +relay-chain model does not apply. The deliverable is an honest profile, not a +proof: + +- A publisher **MAY** emit receipts for objects sent over a unidirectional + bearer, and those receipts attest **what was transmitted**, not what was + received and not what was rendered. +- Such a receipt **MUST** declare the bearer as unidirectional, so a relying + party cannot mistake transmission for delivery. +- A sink **MAY** retain object commitments and reconcile them out of band later. + A reconciliation **MUST** be reported as a `claim` of class + `binding-recovery`-style provenance, never folded into the publisher's chain + as though it had been a hop. + +**No receipt can prove rendering over a bearer with no return path.** This +section does not attempt it. What it prevents is the quieter error: a receipt +that says "delivered" because the transmitter transmitted, on a link that cannot +tell it whether anyone was listening. + +## 5. Framing + +These seams are exercised today in national early-warning deployments, which is +where a sink evaluating a condition the source never learns has had to be made to +work at scale. The mechanisms are worth having for that reason and not only that +one: a container that can only describe two-way delivery cannot describe +broadcast, and broadcast is not a legacy case.