open-standards/wai/live-conformance/remote/README.md
2026-10-26 10:49:59 -04:00

133 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# live-conformance/remote — remote desktop
The corpus of [`extensions/remote-desktop.md`](../../extensions/remote-desktop.md) §13: remote
desktop sessions in rooms of [live-rooms](../../extensions/live-rooms.md), the screen statements
(`WDS1`), input statements (`WDI1`), outcomes (`WDO1`), floor statements (`WDF1`) and latency
records (`WDL1`) their principals sent as `meta` events, some of them with key, text and
clipboard actions sealed to the host (§5.5), and what a verifier states of them at the
commitment level and at the opened level (§11.4).
**Remote desktop equivalence.** For each vector, a conforming verifier given its `descriptor`,
`grants`, `key_log` and `chains` (§11.1) reaches the `outcome` the vector states, with its
`reason` and `at` when it refuses, and, for an accepted room or a room with a gap (§11.3):
- `room` and `gaps`;
- `screens`, in the merged order: each screen statement's `digest`, `host`, `t`, `state`, size,
`fps`, `scope`, `floor`, the action types it `accepts`, and its `capability`, `codec`,
`encoder`, `api` and `hardware`;
- `inputs`, in the merged order: each input statement's `digest`, `author`, `host`, `t`, the
`classes` of its actions, `sealed` (the number of its sealed actions) for one that has any, and
its `fate`: `applied` with the `group` and `object` of the frame its outcome names, `refused`
with the host's `reason`, `unanswered`, or `unchecked` in a room with a gap;
- `floor`: each change of a host's floor in effect, with its `t` and `holder` (or `null`);
- `floor_refused`, where the session has one: each floor statement §7.2 refuses, in the merged
order, with its `digest`, `author`, `host`, `t`, `action` and `reason` (§12's third table).
It changes nothing: `floor` is computed without it;
- `latencies`, in the merged order: each latency record's `digest`, `viewer`, `source`,
`latency_us` and `legs` (`up`, `host`, `down`, and the `uncertainty` of the two that cross
estimates), or `unchecked`;
- `totals`, by host: inputs `applied`, `refused` for each reason of rules 1 to 7 of §12's second
table and for rules 8 and 9 where that count is not zero, `unanswered` and `unchecked`.
**The opened level.** A vector that holds a seal also states `opened`: what the opened level
gives it under the corpus's `opening_key` (the host's X25519 private key), in the same form, its
`inputs` each sealed one with `seal`: `opened` and `opened`, the input statement as it reads opened
(hexadecimal), or a reason of §12's fourth table. For every other vector, which holds no seal, a
conforming verifier at the opened level reaches what it states for the commitment level.
`about` says what each vector is, and is not checked. A verifier that reaches another outcome,
reason, place or fact does not conform.
**Provenance.** Generated here: `wai_remote_desktop_vectors gen` writes `vectors.json` from
sessions authored in code, from fixed seeds. Each key is SHA-256 of
`wai:remote-desktop/corpus/key`, a zero byte and the principal's index (`principals` lists their
public keys). A frame's content hash, which a frame's receipt states, is SHA-256 of
`wai:remote-desktop/corpus/frame`, a zero byte and the group as a u64 little-endian: the corpus
holds no media, and an outcome and a latency record name a frame by its track, group, object and
content hash alone. Each session is written from a script in room-clock order, and every outcome
as the script states it, so a refused vector is a host, a controller or a viewer that states
what the rules do not. Ed25519 is deterministic, so the file is the same bytes on every machine.
Sealing keys, salts and ephemeral keys come from fixed seeds too (`seal_seed`): a principal's
sealing key pair is HPKE's DeriveKeyPair of SHA-256 of `wai:remote-desktop/corpus/seal`, a zero
byte and its index; a sealed action's salt the first 16 bytes of SHA-256 of
`wai:remote-desktop/corpus/salt`, a zero byte, the author, the screen statement's digest, the
action's index and its `dt_us`; a seal's ephemeral key DeriveKeyPair of SHA-256 of
`wai:remote-desktop/corpus/enc`, a zero byte, the author and the statement through its last
action. A deployment draws all three from a random source. The generator asserts that each
vector reaches the outcome it was written to have at both levels, and that the corpus gives every
reason of the four tables of §12, before it writes. A refused vector holds its
session up to the record it is refused at, and a little past it. No recorded data.
## Layout
`vectors.json`: `principals` (informative), `key_seed`, `frame_content`, `seal_seed`,
`opening_key` and `vectors`. Every
session has the registered `screen` profile, and the host's grant marks it a host
(`remote_host` `true`) and lets it publish the `screen` kind. The host's first screen is a
1280 × 720 display at 30 frames a second with a 24-pixel strip redacted at its top, its pointer
drawn, every action type but touch injected, 256 bytes of clipboard text, actions at most a
second old, and a floor kept.
- `floor_session`: alice (`remote_control` 7: pointer, keys, touch), bob (11: every class but
touch), a viewer (no control power) and a lead (the direct power). The host gives alice the
floor; her click and a key are applied, and her latency record of the click states its legs.
The viewer's move is refused `input_not_permitted`, bob's `input_no_floor`. Bob requests the
floor, the host gives it, his clipboard text is applied and his latency record states its
legs; alice's move is refused `input_no_floor`. Bob releases, and the lead gives alice the
floor. The host resizes to 1920 × 1080; alice's move in the old coordinates is refused
`input_wrong_screen`, a touch `input_unsupported`, a move at x 1920 `input_out_of_bounds`, and
a move the host decides 1.5 s later `input_stale`; one move is never answered. The host
pauses, and a move is refused `input_screen_paused`; it resumes, and alice's wheel turn and
composed text are applied, with a latency record of the text. The host takes the floor back,
gives it to bob, and bob holds it when he leaves.
- `open_handover`: an open screen. Alice (`remote_control` 3) and carol (none); at 3 s the
clock exchanges alice's grant for one without the control power and carol's for one with it.
Alice's move and key before it are applied and her move after it refused
`input_not_permitted`; carol's move before it is refused and her right click after it applied.
- `floor_session_gap`: `floor_session` with alice's move off the floor (the fourth record of her
chain) not delivered: the gap stated, the host's outcome naming it passed over, and the
unanswered input stated `unchecked`.
- Accepted with a floor statement §7.2 refuses, each `floor_session` held up to a little past the
statement: the floor given by the viewer (`floor_given_by_viewer`, `floor_not_permitted`),
given to the viewer (`floor_given_to_viewer`, `floor_not_eligible`), released by alice while
bob holds it (`floor_released_by_other`, `floor_not_holder`), requested by the viewer
(`floor_requested_by_viewer`), taken by a controller (`floor_taken_by_controller`), and stated
for a principal that is no host (`floor_of_no_host`), each `floor_not_permitted`. Each is
stated in `floor_refused`, and the floor is what the statements before it made it.
- Refused, each `floor_session` with one defect: a `remote_control` of 16; a screen statement
accepting clipboard text with no bound, one by the viewer, one naming another room's track,
one whose `prev` is zero; an input statement of no action, one whose actions are out of order,
one by the clock; an outcome naming no input, one by the viewer, a second for one input, an
applied one anchoring no frame, one whose frame was captured before the injection; a host that
applies an input each rule of §5.3 refuses (seven vectors), refuses the holder's good click,
or states `input_not_permitted` where the rule is `input_no_floor`; and latency records by the
clock, naming another viewer, signed by another key, of another room, of another controller's
input, of another frame, with a latency one more than its instants, and presented after their
own event.
- Whole floor sessions with a floor statement §7.2 refuses, the holder after it the one before
it and every input's fate the floor session's: `floor_give_by_non_holder` (alice, a controller
that does not hold the floor, gives it to herself while bob holds it: `floor_not_permitted`),
`floor_release_by_non_holder` (alice releases the floor bob holds: `floor_not_holder`), and
`floor_late_release` (alice's release takes its place 50 ms after the host took the floor back,
a race on the wire: `floor_not_holder`).
- Sealed, after every vector above, each stating `opened`. `sealed_session`: an open screen
whose host states a sealing key; alice and bob control pointer, keys and clipboard, the viewer
nothing. Alice's move in the clear with two keys down and up and a composed text, sealed, is
applied, and her latency record of the first key states its legs; her clipboard text, sealed, is
applied; her text in the clear is refused `input_unsealed`; her text sealed to the viewer's
sealing key, one whose commitment is another text's, one whose opening has a padding byte that
is not zero, and bob's copy of her first input are refused `input_bad_seal`, which the opened
level finds `seal_not_opened`, `seal_commitment`, `seal_unreadable` and `seal_not_opened`; the
viewer's sealed key is refused `input_not_permitted`; the host states a screen with no sealing
key, on which alice's sealed text is refused `input_bad_seal` (`seal_no_key`) and her keys in
the clear are applied. Accepted at the commitment level and refused `outcome_mismatch` at the
opened level: the host applies the text sealed to the viewer's key
(`sealed_applies_wrong_key`), applies the text whose commitment is another's
(`sealed_applies_commitment_mismatch`), refuses the first input, whose seal opens, by rule 9
(`sealed_refuses_good_seal`). Refused at both levels: the host applies the text in the clear
(`sealed_applies_unsealed`), applies the sealed text to the screen with no sealing key
(`sealed_applies_no_key`), refuses the keys in the clear by rule 9
(`sealed_refuses_clear_by_seal`), all `outcome_mismatch`; a ciphertext one byte short
(`sealed_malformed_length`), a sealed action stating that it seals a touch
(`sealed_malformed_type`) and a sealing key of 31 bytes (`screen_seal_malformed`), all
`rd_statement_malformed`.