From 952200ee263e3f3e8cba37b39cb8050846af5dc4 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Mon, 11 May 2026 18:44:36 +0200 Subject: [PATCH] docs: align migration guide and analysis with simplified pre-flight MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIGRATION-GUIDE.md step 5 — replaces the "Telnet round-trip probe" bullet with two honest variants: the new passive observer for already-migrated speakers, and a skip-row explainer for not-yet- migrated speakers pointing at the Apply + reboot cycle. The rollback section drops the obsolete tangent about the probe step leaving persisted URLs untouched (the probe no longer exists, and the wizard already writes both layers). TELNET-MIGRATION-METHOD.md — §9.4's pre-flight table swaps the deprecated `POST /setup/telnet-probe` row for the new `POST /setup/peer-probe` row plus a skip-explainer row for the not-yet-migrated case. §9.5 gains a "REMOVED — see §9.8" header pointer (the section is kept as historical record of what was tried). §9.6's backend-additions table replaces the deleted `probeRegistry` + `RunTelnetRoundTripProbe` + `/setup/telnet-probe` row with the `peerObserver` + `RunPeerReachabilityProbe` + `/setup/peer-probe` row that supersedes it. NEXT.md is local-working-tree only (deliberately untracked) and gains a ✅ Resolved header pointing at §9.8; not part of this commit. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/analysis/TELNET-MIGRATION-METHOD.md | 21 ++++++++++++++------- docs/guides/MIGRATION-GUIDE.md | 5 +++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/analysis/TELNET-MIGRATION-METHOD.md b/docs/analysis/TELNET-MIGRATION-METHOD.md index 4d686f8..1b8e571 100644 --- a/docs/analysis/TELNET-MIGRATION-METHOD.md +++ b/docs/analysis/TELNET-MIGRATION-METHOD.md @@ -561,12 +561,13 @@ abort. Checks: -| Check | When | Backend route | -|-------------------------------|-----------------------------------------------|--------------------------------| -| Backend summary re-check | always | `GET /setup/summary` | -| HTTPS connection from device | `ssh_success && server_https_url` | `POST /setup/test-connection` | -| Telnet round-trip probe | `!ssh_success && telnet_reachable` (see §9.5) | `POST /setup/telnet-probe` | -| DNS redirection from device | `methods.includes("resolv") && ssh_success` | `POST /setup/test-dns` | +| Check | When | Backend route | +|---------------------------------------|------------------------------------------------------------|--------------------------------| +| Backend summary re-check | always | `GET /setup/summary` | +| HTTPS connection from device | `ssh_success && server_https_url` | `POST /setup/test-connection` | +| Reachability check (passive observer) | `telnet_reachable && is_migrated` (see §9.8) | `POST /setup/peer-probe` | +| Round-trip skip explainer | `telnet_reachable && !is_migrated` — runs after reboot | _none_ (UI-side skip row) | +| DNS redirection from device | `methods.includes("resolv") && ssh_success` | `POST /setup/test-dns` | The HTTPS check uses `use_explicit_ca=true` so it exercises the trust path even when CA install is part of the plan (i.e. forward-looking). @@ -576,6 +577,12 @@ is reachable") rather than silently dropped, per the user's ### 9.5 Telnet round-trip probe — the SSH-less reachability check +> **REMOVED — see §9.8.** Empirical testing showed the swUpdate +> daemon caches its target URL at boot and ignores live config +> writes, so the active flip described below could never reach the +> running daemon. The section is retained as a historical record of +> what was tried; the running code uses the passive observer in §9.8. + The reachability gap §7 left open for USB-unlock-refusing speakers is closed by `Manager.RunTelnetRoundTripProbe` (`pkg/service/setup/telnet_probe.go`). Sequence: @@ -613,7 +620,7 @@ configured `swUpdateUrl`. | `telnetURLsFromOptions(targetURL, options)` | `pkg/service/setup/telnet_migration.go` | Same option family as above, plus envswitch arg derivation rule (arg1 = final Marge verbatim; the soundcork-suffix case drops out). | | Per-axis booleans + `IsPaired` + `Warnings` | `MigrationSummary` | Surfaces partial-state cells and SSH-XML ⇄ telnet-getpdo cross-check disagreements. | | `parseGetpdoConfig` | `pkg/service/setup/preflight_crosscheck.go` | Parses the Protobuf-text-like nested-block reply (`key { text: "..." }`) FW 27.0.6 actually sends, plus the legacy `key=value` shape as a tolerance path. | -| `probeRegistry` + `RunTelnetRoundTripProbe` + `/setup/telnet-probe` | `pkg/service/handlers` / `pkg/service/setup` | §9.5. | +| `peerObserver` + `RunPeerReachabilityProbe` + `/setup/peer-probe` | `pkg/service/handlers` / `pkg/service/setup` | §9.8. Replaces the removed `probeRegistry` + `RunTelnetRoundTripProbe` + `/setup/telnet-probe` from §9.5. | | `migrationOptionKeys` allow-list | `pkg/service/handlers/migration_options.go` | Unknown query keys never reach the manager. Both XML mode keys and `*_url` keys are recognised. | | Telnet client default timeouts: dial 4s, read 7s, write 3s, idle 600ms | `pkg/telnet/telnet.go` | Bumped from the original 2s/5s/2s/400ms after observing transient i/o-timeout flakes on healthy speakers that recovered on retry. | diff --git a/docs/guides/MIGRATION-GUIDE.md b/docs/guides/MIGRATION-GUIDE.md index b6891de..96a1b16 100644 --- a/docs/guides/MIGRATION-GUIDE.md +++ b/docs/guides/MIGRATION-GUIDE.md @@ -165,7 +165,8 @@ The wizard switches to a visible **Pre-flight checks** panel and runs every appl - **Backend summary re-check** — confirms transports, hostname resolution, and that the URLs you plan to write match what the backend would produce. - **HTTPS connection from device** (SSH-capable speakers) — uploads a temporary CA and runs `curl` from the speaker to your service. -- **Telnet round-trip probe** (SSH-less speakers) — temporarily points the speaker's swUpdateUrl at our service via telnet, triggers `:8090/swUpdateCheck`, and watches the inbound land. +- **Reachability check (passive observer)** (already-migrated speakers) — nudges `:8090/swUpdateCheck` on the device and watches for *any* request from the speaker to land on the service. Used when the speaker is already migrated and the service is the natural target of its outbounds. +- **"Round-trip validation runs after Apply + reboot"** (not-yet-migrated speakers) — surfaced as a skip row with a rationale. The speaker's swUpdate daemon caches its URL at boot, so there is no useful no-reboot round-trip check pre-migration; the canonical telnet flow is Apply → reboot → re-run pre-flight on the migrated speaker. - **DNS redirection from device** — when DNS interception is part of the plan. On all-green, the wizard auto-proceeds. On any failure, it pauses with *Proceed Anyway* / *Cancel* buttons so you can override on a known-false-positive (slow DNS, etc.) or fix the underlying issue and retry. @@ -210,7 +211,7 @@ Each speaker is migrated independently. You can run multiple migrations in paral If you need to undo a migration: - **From the web UI**: Use the **Revert to Defaults** action on the device — this restores the `.original` backup files created on the speaker during the XML migration. -- **Telnet-only migrations**: the wizard writes only the runtime configuration layer via telnet; the speaker's persistent "envswitch" layer keeps the original Bose URLs. **A single reboot reverts a telnet-only migration automatically.** To make a telnet migration permanent, the wizard also writes `envswitch boseurls set …` as part of the URL flip step — only the *probe* step (used by the pre-flight check) leaves the persisted URLs untouched. +- **Telnet-only migrations**: the wizard writes both the runtime configuration layer (`sys configuration …`) and the persistent layer (`envswitch boseurls set …`) so the migration survives reboot. If you want to revert quickly, the cleanest path is to re-run the wizard with the original Bose URLs in the URL editor. - **Via SSH**: The original XML config is backed up on the speaker with a `.original` suffix. Restore it manually if the UI is unreachable. - **Factory reset**: As a last resort, perform a factory reset (see [Device Initial Setup](DEVICE-INITIAL-SETUP.md) for button sequences). This wipes all configuration and returns the speaker to out-of-box state.