docs: align migration guide and analysis with simplified pre-flight

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) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-05-11 20:31:24 +02:00
co-authored by Claude Opus 4.7
parent 62dd53777d
commit 952200ee26
2 changed files with 17 additions and 9 deletions
+14 -7
View File
@@ -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. |
+3 -2
View File
@@ -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.