133 lines
10 KiB
Markdown
133 lines
10 KiB
Markdown
# 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`.
|