open-standards/wai/extensions/unidirectional-delivery.md

120 lines
6.7 KiB
Markdown

# 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.
- A key-log anchor a sink fetched from an origin on first use
([`jwp-receipts`](jwp-receipts.md) §7.3) is not a trust anchor here. When a
class is registered for pre-emption, its authority is confirmed only under a
pinned anchor, and only for a key the pinned revision itself lists with it
(jwp-receipts §7.4, §7.5).
- The same holds for receipts: a sink with no return path confirms keys only
under anchors provisioned in advance, and a key log that reaches it over the
bearer is held but anchors nothing (`anchor_on_bearer`,
[`bearer-receipts`](bearer-receipts.md) §8).
## 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, and [`bearer-receipts`](bearer-receipts.md) specifies it:
- A publisher **MAY** emit receipts for objects sent over a unidirectional
bearer. They are the receipts it emits for any bearer, byte for byte, and they
attest what was published, not what was received and not what was rendered.
- A publisher that does so **MUST** declare the bearer: for each group, a
`transmission` claim ([`jwp-receipts`](jwp-receipts.md) §2.4.14) naming the
bearer as `unidirectional`, signed by the group's key, whose subject is the
group's link hash (bearer-receipts §4). The declaration sits beside the
receipt and changes none of its bytes, so a group carried on several bearers
has one receipt and one declaration for each. It attests transmission, so a
relying party cannot mistake transmission for delivery: a group with
declarations and no reconciliation is `transmitted`, and a group presented as
delivered on that evidence is refused (`delivery_not_reconciled`,
bearer-receipts §6.3, §6.4). A sink that received a group over a
unidirectional bearer with no declaration for it reports `bearer_not_declared`
(bearer-receipts §6.5).
- A sink **MAY** retain object commitments and reconcile them out of band later,
in a `reconciliation` claim (jwp-receipts §2.4.15, bearer-receipts §5): signed
by the sink and never by the publisher, it names the group by its link hash and
the objects it received by a bitmap and a root under the group's own Merkle
tree, so it is checked against the publisher's root without the objects. A
reconciliation **MUST** be reported apart from the publisher's chain and never
folded into it as though it had been a hop. Like a `binding-recovery` record
(jwp-receipts §2.6.3), it attests less than a hop would, and says so
(`attests: "received"`).
- A transmission over a bearer whose receivers are not known is shared by
them, and its energy per receiver is stated only as an upper bound that
tightens as reconciliations arrive, never as a measurement
(bearer-receipts §7).
**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.