Skip to content

phase 4b-1: types + API client for pair flow; rip out bearer surface#248

Merged
bdraco merged 2 commits into
mainfrom
remote-build-phase-4b-1-types
May 9, 2026
Merged

phase 4b-1: types + API client for pair flow; rip out bearer surface#248
bdraco merged 2 commits into
mainfrom
remote-build-phase-4b-1-types

Conversation

@bdraco

@bdraco bdraco commented May 9, 2026

Copy link
Copy Markdown
Member

What does this implement/fix?

Phase 4b-1 of esphome/device-builder#106. Adds typed wrappers + types for the new pair-flow WS commands and event payloads, removes the dead bearer-token surface.

Backend already shipped (4a complete)

The bearer-token machinery is dead on the backend; this PR closes the gap on the frontend side.

What's added

  • New types mirroring backend models/remote_build.py: PeerStatus, PeerSummary, PairingSummary, PairingWindowState, four event-payload interfaces.
  • Four EventType enum values: REMOTE_BUILD_PAIR_REQUEST_RECEIVED, REMOTE_BUILD_PAIR_STATUS_CHANGED, REMOTE_BUILD_PAIRING_WINDOW_CHANGED, OFFLOADER_PAIR_STATUS_CHANGED.
  • InitialStateEventData.pairings (optional) so the frontend's first paint reads the snapshot the backend pushes once at subscribe time.
  • Seven typed wrappers: receiver-side listRemoteBuildPeers / approveRemoteBuildPeer / removeRemoteBuildPeer / setRemoteBuildPairingWindow; offloader-side previewRemoteBuildPair / requestRemoteBuildPair / unpairRemoteBuild. Each documents its error codes so consuming UIs don't have to grep the backend.
  • RemoteBuildSettings.peers: PeerSummary[] replaces tokens: TokenSummary[].
  • Wire-shape tests for all seven new wrappers.

What's removed

  • src/util/remote-build-bearer.ts + its test (mintRemoteBuildBearer helper).
  • src/components/generate-build-server-token-dialog.ts (sole consumer of the helper).
  • js-sha256 runtime dep + lockfile adjustments.
  • EventType.REMOTE_BUILD_BINDING_MISMATCH + RemoteBuildBindingMismatchEventData + buildServerBindingMismatchesContext; the 3c2d alert plumbing (consumers in app-shell + settings-dialog).
  • TokenSummary / AddRemoteBuildTokenArgs types + the three token-CRUD wrappers.
  • All token-related state, methods, and rendering in settings-dialog.ts.
  • 36 dead settings.build_server_token* / build_server_revoke* / build_server_alert* / build_server_generate_token* translation keys across the three locales.

Why combined with the bearer-deletion bits of 4b-4

Deleting mintRemoteBuildBearer without deleting its sole consumer leaves a non-buildable intermediate state, which the lockstep-deployment model in CLAUDE.md explicitly avoids. The 4b-4 reshape of 3c2d alerts (pin_mismatch / peer_revoked) stays its own PR — those wire/render contracts ship with the new event types in 4b-2 / 4b-3.

Verification

  • npm run lint (tsc --noEmit): clean
  • npm run test: 962/962 passing (vitest)
  • npm run build: succeeds
  • Stale-ref grep across src/ + test/ + package.json: empty

Unblocks 4b-2 (receiver-UI inbox) and 4b-3 (offloader-UI pair flow); they can land in parallel branches.

Related issue or feature (if applicable):

Types of changes

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • New feature (non-breaking change which adds functionality) — new-feature
  • Enhancement to an existing feature — enhancement
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) — breaking-change
  • Refactor (no behaviour change) — refactor
  • Documentation only — docs
  • Maintenance / chore — maintenance
  • CI / workflow change — ci
  • Dependencies bump — dependencies

Checklist

  • The code change is tested and works locally.
  • npm run lint passes.
  • npm run test passes.
  • Tests have been added to verify that the new code works (where applicable).

Backend pair flow (4a-r1 + 4a-r2 + 4a-o, all merged) is the
production shape; the bearer-token machinery from 3b1-3c2d is dead
on the backend (torn out in esphome/device-builder#489) and now
needs to come out of the frontend too. Combines 4b-1 (types + API
client) with the bearer-deletion bits of 4b-4 because the helper
import sites can't be cleaved cleanly (deleting
``mintRemoteBuildBearer`` without deleting its sole consumer
``<esphome-generate-build-server-token-dialog>`` would leave a
non-buildable intermediate state, which the lockstep-deployment
model in CLAUDE.md explicitly avoids). The 4b-4 reshape of 3c2d
alerts (``pin_mismatch`` / ``peer_revoked``) stays its own PR;
those are wire/render contracts that ship with the new event
types in 4b-2 / 4b-3.

What's added:

* ``PeerStatus`` / ``PeerSummary`` / ``PairingSummary`` /
  ``PairingWindowState`` types mirroring backend's
  ``models/remote_build.py`` shapes. Drops
  ``StoredPairing.static_x25519_pub`` projection on both wire
  views; wire payloads carry the ``pin_sha256`` form UIs render
  for OOB-verification.
* Four new ``EventType`` enum values:
  ``REMOTE_BUILD_PAIR_REQUEST_RECEIVED``,
  ``REMOTE_BUILD_PAIR_STATUS_CHANGED``,
  ``REMOTE_BUILD_PAIRING_WINDOW_CHANGED``,
  ``OFFLOADER_PAIR_STATUS_CHANGED`` (offloader-side counterpart;
  keys on receiver coordinates because the offloader's
  ``StoredPairing`` doesn't store the receiver's
  ``dashboard_id``).
* Matching event-payload interfaces with docstrings explaining
  the firing paths the receiver / offloader controllers take.
* ``InitialStateEventData.pairings`` (optional, present only when
  ``remote_build`` controller is wired up) so the Send-builds
  initial paint can read the snapshot the backend pushes once at
  subscribe time.
* Seven new typed wrappers on ``ESPHomeAPI``: receiver-side
  ``listRemoteBuildPeers`` / ``approveRemoteBuildPeer`` /
  ``removeRemoteBuildPeer`` / ``setRemoteBuildPairingWindow``
  (replaces the deleted token-CRUD trio + adds the pairing-window
  surface); offloader-side ``previewRemoteBuildPair`` /
  ``requestRemoteBuildPair`` / ``unpairRemoteBuild``. Each
  documents its error codes (``UNAVAILABLE`` /
  ``PRECONDITION_FAILED`` / ``NO_PAIRING_WINDOW`` /
  ``INVALID_ARGS``) so the consuming UIs in 4b-2 / 4b-3 don't
  have to grep the backend.
* Test coverage for all seven new wrappers (wire shape +
  args + result unwrap pinning); drops the three token-wrapper
  tests it replaces.
* ``RemoteBuildSettings.peers: PeerSummary[]`` replaces the
  former ``tokens: TokenSummary[]`` (the receiver-side
  view of "who's paired").

What's removed:

* ``src/util/remote-build-bearer.ts`` + its test — the
  client-side bearer mint helper. The receiver no longer accepts
  bearer-authenticated requests post-pivot.
* ``src/components/generate-build-server-token-dialog.ts`` — the
  Settings UI for issuing new bearer tokens. Pairing happens
  through the receiver-side inbox in 4b-2.
* ``js-sha256`` runtime dep + ``package-lock.json`` adjustments.
* ``EventType.REMOTE_BUILD_BINDING_MISMATCH`` /
  ``RemoteBuildBindingMismatchEventData`` /
  ``buildServerBindingMismatchesContext`` and their consumers in
  ``app-shell.ts`` / ``settings-dialog.ts``. The 3c2d alert
  surface goes; 4b-4 brings it back as
  ``pin_mismatch`` / ``peer_revoked``.
* ``TokenSummary`` / ``AddRemoteBuildTokenArgs`` types,
  ``listRemoteBuildTokens`` / ``addRemoteBuildToken`` /
  ``removeRemoteBuildToken`` wrappers.
* All token-related state, methods, and rendering in
  ``settings-dialog.ts`` (``_buildServerTokens`` /
  ``_buildServerTokensLoadFailed`` / ``_pendingRevokeTokenId`` /
  ``_revokeConfirmDialog`` / ``_generateTokenDialog`` /
  ``_loadBuildServerTokens`` / ``_onGenerateTokenRequest`` /
  ``_onTokenIssued`` / ``_onRevokeRequest`` /
  ``_onRevokeConfirm`` / ``_renderBuildServerTokens`` /
  ``_renderTokenRow`` / ``_renderBuildServerAlerts`` /
  ``_renderBuildServerAlert``).
* 36 dead ``settings.build_server_token*`` /
  ``build_server_revoke*`` / ``build_server_alert*`` /
  ``build_server_generate_token*`` translation keys across the
  three locale files.

Verification:
- ``npm run lint`` (tsc --noEmit) — clean.
- ``npm run test`` — 962/962 passing.
- ``npm run build`` — succeeds (rspack warnings about bundle
  size are pre-existing).
- ``grep -rln "TokenSummary|RemoteBuildBindingMismatch|
  REMOTE_BUILD_BINDING_MISMATCH|mintRemoteBuildBearer|js-sha256|
  listRemoteBuildTokens|addRemoteBuildToken|removeRemoteBuildToken|
  generate-build-server-token-dialog|buildServerBindingMismatchesContext"
  src/ test/ package.json`` — empty.

Unblocks 4b-2 (receiver-UI inbox) and 4b-3 (offloader-UI pair
flow); they can land in parallel branches against this PR's
typed surface.

Companion backend PRs already merged: esphome/device-builder #472,
#473, #476, #479, #489 (receiver), #494, #495, #501, #507
(offloader), #508 / #509 (per-file Store helper).
Copilot AI review requested due to automatic review settings May 9, 2026 23:46
@github-actions github-actions Bot added the enhancement Improvement to an existing feature label May 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the frontend remote-build surface to match the backend’s Noise XX pair-flow: it adds typed event payloads + typed WS command wrappers for pairing, and removes the now-dead bearer-token generation/management UI and dependencies.

Changes:

  • Add remote-build pair-flow types (peers/pairings, pairing window state, new event payloads) and corresponding typed ESPHomeAPI WS wrappers.
  • Remove bearer-token minting helper + token CRUD wrappers/UI, plus related translations and alert plumbing.
  • Update unit tests to pin the new wire shapes and remove bearer-related coverage and the js-sha256 dependency.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/util/remote-build-bearer.test.ts Removes tests for the deleted bearer-mint helper.
test/api/esphome-api.test.ts Updates wrapper wire-shape tests from token CRUD to pair-flow commands.
src/util/remote-build-bearer.ts Removes bearer-mint implementation (no longer used by backend).
src/util/copy-to-clipboard.ts Updates commentary now that bearer hashing helper is removed.
src/translations/en.json Removes token-related Settings strings.
src/translations/fr.json Removes token-related Settings strings (FR).
src/translations/nl.json Removes token-related Settings strings (NL).
src/context/index.ts Stops exporting the removed binding-mismatch alert context.
src/context/contexts.ts Removes the binding-mismatch alert context definition.
src/components/settings-dialog.ts Removes token list, generate/revoke flows, and binding-mismatch alerts from Build server settings.
src/components/generate-build-server-token-dialog.ts Removes the token generation dialog component.
src/components/app-shell.ts Removes handling/state for the removed binding-mismatch event stream.
src/api/types.ts Adds pair-flow types + new remote-build event types; replaces token settings types with peers/pairings.
src/api/esphome-api.ts Replaces token CRUD wrappers with peer/pairing WS command wrappers for the new pair flow.
package.json Drops js-sha256 runtime dependency.
package-lock.json Drops js-sha256 lock entries.

Comment thread src/api/esphome-api.ts Outdated
… header

The receiver-side WS commands now list pairings via Noise XX (phase
4a-r1 / 4a-o), not bearer tokens. The divider comment + the
docstring lead-in for listRemoteBuildPeers still referred to
"receiver-issued bearer tokens"; rename to match the actual surface
("receiver-side pairing inbox (phase 4a-r1)").
@bdraco bdraco merged commit c0d0838 into main May 9, 2026
7 checks passed
@bdraco bdraco deleted the remote-build-phase-4b-1-types branch May 9, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement to an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants