phase 4b-1: types + API client for pair flow; rip out bearer surface#248
Merged
Conversation
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).
Contributor
There was a problem hiding this comment.
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
ESPHomeAPIWS 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-sha256dependency.
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. |
… 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)").
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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)
pair_requestflow), Render is_list sections as a repeatable list in the editor #489 (bearer tearout)helpers.storage.Store)The bearer-token machinery is dead on the backend; this PR closes the gap on the frontend side.
What's added
models/remote_build.py:PeerStatus,PeerSummary,PairingSummary,PairingWindowState, four event-payload interfaces.EventTypeenum 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.listRemoteBuildPeers/approveRemoteBuildPeer/removeRemoteBuildPeer/setRemoteBuildPairingWindow; offloader-sidepreviewRemoteBuildPair/requestRemoteBuildPair/unpairRemoteBuild. Each documents its error codes so consuming UIs don't have to grep the backend.RemoteBuildSettings.peers: PeerSummary[]replacestokens: TokenSummary[].What's removed
src/util/remote-build-bearer.ts+ its test (mintRemoteBuildBearerhelper).src/components/generate-build-server-token-dialog.ts(sole consumer of the helper).js-sha256runtime dep + lockfile adjustments.EventType.REMOTE_BUILD_BINDING_MISMATCH+RemoteBuildBindingMismatchEventData+buildServerBindingMismatchesContext; the 3c2d alert plumbing (consumers in app-shell + settings-dialog).TokenSummary/AddRemoteBuildTokenArgstypes + the three token-CRUD wrappers.settings-dialog.ts.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
mintRemoteBuildBearerwithout deleting its sole consumer leaves a non-buildable intermediate state, which the lockstep-deployment model inCLAUDE.mdexplicitly 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): cleannpm run test: 962/962 passing (vitest)npm run build: succeedssrc/+test/+package.json: emptyUnblocks 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
bugfixnew-featureenhancementbreaking-changerefactordocsmaintenancecidependenciesChecklist
npm run lintpasses.npm run testpasses.