# 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. ### 3.1 The register this revision holds WAI's parameters are named under the prefix `wai:`. Each value is an integer or a string, so every evaluation is exact; a rate that would be a rational elsewhere is an integer in a stated unit here. | parameter | value | what it is | |---|---|---| | `wai:codec` | string | the codec string a decoder is configured with | | `wai:frame_width` | integer | the coded width, in samples | | `wai:frame_height` | integer | the coded height, in samples | | `wai:frame_rate_milli` | integer | frames per 1000 seconds | | `wai:bit_depth` | integer | bits per sample | | `wai:chroma` | string | the chroma sampling: `4:2:0`, `4:2:2`, `4:4:4` or `4:0:0` | | `wai:sample_rate` | integer | audio samples per second, per channel | | `wai:channel_count` | integer | audio channels | | `wai:bitrate` | integer | bits per second | The families §3 names (neural, quantum, world, haptic) have no entries yet, and stay unconstrained until they do. The form a page evaluates constraint sets in, and their evaluation, are [browser-sink](browser-sink.md) §5; its reference implementation is the `browser_sink` module of `wai-rs`. ## 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, which has only "supported", gains a range by adopting it.