Files
openclaw/docs
Peter Steinberger 75bcc5cebe fix(ui): keep Control UI device identity working on plain-HTTP origins (#124724)
* fix(ui): keep Control UI device identity working on plain-HTTP origins

@noble/ed25519 defaults its SHA-512 provider to crypto.subtle, which
browsers gate to secure contexts, so device identity silently vanished
on http:// LAN dashboards and connects fell back to shared-credential
auth with no pairing. Wire a lazy pure-JS @noble/hashes fallback for
SHA-512 and the fingerprint SHA-256, and drop the isSecureContext gate
in the connect path. Secure contexts keep the platform digests and pay
no startup bytes: the fallback loads as its own lazy chunk, kept out of
the gateway-runtime startup chunk on purpose.

* test(ui): cover device identity minting and signing without crypto.subtle

New jsdom regression suite fails on pre-fix code (subtle-less crypto stub
with getRandomValues, which real insecure contexts keep). Rewrites the
gateway connect tests that previously asserted the device-less insecure
fallback: an insecure context now attaches a device identity.

* docs(web): plain-HTTP dashboards now pair with a device identity

The signing key never crosses the wire, so HTTP+pairing is strictly
stronger than the old HTTP token-only fallback; HTTPS (Tailscale Serve)
stays the recommendation for transport privacy.

* fix(ui): drop unnecessary boolean literal compare in secure-context timing meta

* test(ui): declare device.id on the connect-frame test shape

* test(ui): split the subtle-less scope-upgrade e2e into the two real invariants

Without crypto.subtle the browser can now sign, so the banner offers the
explicit admin upgrade; manual-only guidance is reserved for browsers that
cannot mint an identity at all (no WebCrypto RNG). Also corrects the
connect-path comment: blocked storage yields an ephemeral identity, only a
failed mint degrades device-less.

* fix(ui): address review findings on the HTTP device-identity path

- Storage-blocked pages keep one stable in-memory identity per page
  lifetime instead of minting a fresh unpaired key on every reconnect,
  and a write-rejecting store no longer fails the mint (regression tests
  bite pre-fix).
- Connect timing now reports the real browser secure-context fact via a
  shared browserSecureContext() helper instead of inferring it from
  device-identity presence.
- Docs state the accepted trusted-proxy contract: browsers attach a
  device identity on every origin, so first connects follow the standard
  pairing flow (deviceAutoApprove or a one-time approval); device-less
  admission remains only for browsers that cannot mint an identity.

* refactor(ui): trim the connect-path additions under the max-lines cap
2026-08-16 12:20:00 -07:00
..