Partially reverts #27540 and the plain-http part of #27552, which broke web
pairing on upgrade for 1.4.227 users who open Orca at a LAN or Tailscale address:
- The host no longer refuses a first pairing from a plain-http page on another
machine (insecure_origin, ORCA_ALLOW_INSECURE_WEB_PAIRING).
- Such a page keeps its pairing code in local storage and signs in with it, as
in 1.4.227, so reloads, new tabs and bookmarks stay paired; no notice.
- Session-only browser keys (pairing.device-key-ephemeral.v1, the idle sweep)
stay for browsers without Ed25519.
- A web client whose credentials are refused shows the host's reason instead
of an empty workspace and "Session restore failed".
* feat(runtime): session-only browser keys and an opt-in for pairing from plain-http pages (host)
- pairing.registerDeviceKey accepts ephemeral: true (advertised as
pairing.device-key-ephemeral.v1). Such keyed rows are dropped when the host
restarts and after 12 hours with no live socket; a sweep removes them and cuts
any socket still bound to them, so later key auth gets device_revoked.
- The WebSocket upgrade Origin is recorded per socket. A first pairing (a
never-used pairing code) from an http:// page on another machine is refused
with a sealed insecure_origin error unless the operator sets
ORCA_ALLOW_INSECURE_WEB_PAIRING=1. Already-paired browsers, https and loopback
pages, and native clients are unchanged.
- Registry file reading moved to device-registry-file-read.ts to keep the
registry under the size cap.
* fix(runtime): gate first pairings only for the marked web client, never phones
React Native sends an http Origin on every LAN WebSocket, so the Origin alone
refused first-time QR pairing from released phones. The web bundle now marks
its upgrade with ?orca-client=web; only a marked socket from an http page on
another machine is gated. Released hosts ignore the query string.
---------
Co-authored-by: m4air <m4air@Mac.localdomain>