From 102770e30195a31bfbddd7f54190892e7ed0cf8a Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 10 May 2026 23:30:29 +0200 Subject: [PATCH] feat(web): account pairing folded into Plan card and Apply orchestrator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pairing was previously its own post-telnet pop-up pane — loadAccountIDSuggestions(deviceId) was called only after a successful telnet migration, leaving the user to interact with a separate panel and click a separate "Pair Account" button. XML migrations didn't surface pairing at all. The Plan card now has its own Account pairing section between Service URLs and Suggested plan, with the same affordances (current state, 7-digit input, Generate button, datastore picker) but always visible. The implicit intent — read by readPlanPairTarget — is: - empty input + currently paired → no pairing step (current ID kept) - empty input + currently unpaired → no pairing step (warning hint visible) - input matches summary.account_id → no pairing step - input is exactly 7 digits, differs → pair step queued at Apply - input is non-empty but malformed → blocks Apply with a clear error Both Apply orchestrators (applySuggestedPlan, applyCustomPlan) now queue a `pairAccount(deviceId, accountId)` call when the intent says to. It runs *after* the URL flip / DNS / CA steps so the user sees the migration succeed before pairing — pairing is independent of the migration target so order is purely UX. First-failure-aborts is preserved: a pair-account error stops the rest of the sequence. Removed: - #pair-account-pane HTML and all its descendants - loadAccountIDSuggestions / generateAccountID / pairAccount(deviceId) (the old pane-bound functions) - the "if method === telnet → loadAccountIDSuggestions" trigger in migrate() Added: - renderPlanPairing(summary, deviceId) — populates the section on every showSummary - loadPlanAccountSuggestions(deviceId) — fetches /setup/account-id- suggestions; gracefully degrades on failure - onPlanPairIDChange / onPlanPairPick / generatePlanAccountID — UI handlers with implicit-intent status hints - readPlanPairTarget — orchestrator-facing intent extractor - pairAccount(deviceId, accountId) — POSTs and throws on failure (replaces the old pane-bound function with a step-friendly shape) - resetPlanCardForDeviceSwitch clears the pairing input on speaker change so the previous device's ID can't leak Backend untouched — all the pairing endpoints (/setup/account-id- suggestions, /setup/pair-account) and the setup.PairAccount + telnet- fallback logic stay exactly as-is. Co-Authored-By: Claude Opus 4.7 (1M context) --- pkg/service/handlers/web/index.html | 76 ++----- pkg/service/handlers/web/js/script.js | 289 +++++++++++++++++--------- 2 files changed, 218 insertions(+), 147 deletions(-) diff --git a/pkg/service/handlers/web/index.html b/pkg/service/handlers/web/index.html index 7c9fc1a..cf5884c 100644 --- a/pkg/service/handlers/web/index.html +++ b/pkg/service/handlers/web/index.html @@ -890,6 +890,28 @@ > +
+

Account pairing

+

+
+ + + + +
+
+
+

Suggested plan

- -