- Refactors BMX service to support multiple radio providers
- Adds RadioBrowser.com API integration with search and browse
- Splits TuneIn logic into separate module for better organization
- Adds new web UI components for radio station discovery
- Includes new SVG icons for RadioBrowser branding
Phase 4 of the docs portion of the rfc-5737-cleanup. Replaces all
192.168.1.x example IPs in tracked .md / .txt files with the
equivalent last-octet under 192.0.2.x.
192.168.1.x is RFC-1918 private space and routes on real networks,
which leaves readers guessing whether a documented IP is a placeholder
or a documented LAN. 192.0.2.0/24 is reserved by RFC 5737 exclusively
for documentation — readers know on sight that they're examples.
58 files touched, 551 line pairs. Includes .github issue/PR templates,
all docs/ references, example READMEs, and one script doc. No code
changes, no test changes; test files still carry the 192.168.1.x
placeholder pending Phase 2 in _/RFC-5737-cleanup/assessment.md.
Also fixed a small fallout in docs/analysis/ANONYMIZATION-SUMMARY.md
where the explanatory sentence "a reader can't tell whether
192.168.1.10 is a placeholder or a documented LAN address" had
itself been swept by the regex (inverting the point); restored the
literal example and noted the sweep progress inline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The maintainer's two test-speaker MACs (A81B6A536A98 / A81B6A849D99,
plus colon-separated forms) appeared throughout documentation, runbooks,
and example READMEs. Public repo — same hygiene argument as the LAN-IP
sweep in 787c4fa.
Mapping:
A81B6A536A98 → AABBCCDDEEFF
A81B6A849D99 → AABBCCDDEE01
A8:1B:6A:53:6A:98 → AA:BB:CC:DD:EE:FF
A8:1B:6A:84:9D:99 → AA:BB:CC:DD:EE:01
The placeholders use the IANA-reserved AA:BB:CC:DD:EE:FF address that's
clearly synthetic, matching the convention the earlier anonymisation
pass had already adopted. 13 .md files touched; no tests, no code.
ANONYMIZATION-SUMMARY.md left for a dedicated rewrite commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
storePreset on the speaker was failing with "AddPreset - failed due to
invalid SourceID" because the watchdog priming path only pushed ZeroConf
credentials and never registered a SPOTIFY ConfiguredSource in marge.
PrimeDeviceWithSpotify now:
- resolves the device's paired account via live :8090/info
(margeAccountUUID), falling back to ServiceDeviceInfo.AccountID — same
order as setup.populateDeviceInfo;
- writes a SPOTIFY ConfiguredSource under that account (providerID=15,
BoseSecret as credential), mirroring bridgeSpotifyToMarge;
- POSTs `<updates><sourcesUpdated/></updates>` so the speaker re-fetches
its on-device Sources.xml from marge.
Also introduce zeroconf.ErrAddUserNoOp for the narrow firmware quirk
(404 + empty body on ?action=addUser when activeUser already matches).
Recognised only on that exact pattern; real 4xx/5xx still surface loudly
with full response details. Same treatment applied to Amazon priming.
Docs:
- new docs/concepts/spotify-overview.md anchors the topic (mental model,
streamingoauth.bose.com DNS gotcha, token lifecycle, clientId notes,
troubleshooting table);
- spotify-oauth.md drops the removed install-primer endpoint and the
on-device boot-primer install sections, adds /mgmt/spotify/prime;
- spotify-priming-strategy.md and MUSIC-SERVICES.md link to the
overview.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Attempting to request amazon_music:access with a standard application
client ID (amzn1.application-oa2-client.*) returns HTTP 400
lwa-invalid-parameter-bad-scope from the LWA authorization endpoint.
The scope is gated to Amazon Music partner device client IDs.
Revert scope to "profile" (working state) and document the confirmed
blocker with the exact error. Path forward: Amazon Music partner
registration for a device client ID; one-line change to AmazonScopes
when available.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Amazon bridge: fall back to sync/legacy on any error from
SetMusicServiceOAuthAccount (not only error 1029); timeouts from
unresponsive speakers no longer silently skip the fallback chain
- Amazon bridge: reduce speaker client timeout from 30s to 5s for
faster failure on local network calls
- marge: resolveSourceName now prefers SourceName/DisplayName over
SourceKeyAccount, so Amazon (and Spotify) sources show the account
holder's name instead of the raw account ID
- docs: update amazon-music-oauth.md with real-world test results;
music-api.amazon.com returns 401 because standard LWA apps lack
music::* partner scopes — infrastructure is complete but streaming
is blocked pending Amazon partner access
- docs: add SELF-HOSTING.md and MUSIC-SERVICES.md user guides; link
both in SUMMARY.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Mark status as Implemented
- Add "Trying It Out" section: LWA app setup, service flags, OAuth flow,
account verification, speaker priming, DNS requirement, site_id open question
- Fix stale endpoint table entry (no longer a stub)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Mark ZeroConf Spotify priming and 404 handler as addressed in both docs
- Remove stale "Remaining gaps" and "Already adopted" tracking tables from
community-tools.md; detail now lives in PARITY-SOUNDCORK.md
- Update PARITY-SOUNDCORK.md summary to reflect Groups and ZeroConf as done;
add cross-reference to community-tools.md
- Rename remaining "gesellix" project references to "AfterTouch" throughout
community-tools.md (URLs and author attribution unchanged)
- Add soundcork-stockholm-app (entry 7) to community projects list
- Correct DNS priority entry: built-in DNS server requires no external tools
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the simplified tokenType=accesstoken push with the full Spotify
Connect ZeroConf protocol: GET getInfo to fetch the speaker's 768-bit DH
public key, derive AES-128-CTR + HMAC-SHA1 keys from the shared secret,
and POST an encrypted LoginCredentials protobuf blob. Speakers that
receive a proper blob can self-refresh their Spotify session
independently, eliminating the need for periodic re-priming on token
expiry. Falls back to the raw token approach automatically when getInfo
fails, preserving compatibility with older firmware.
SHA1 is mandated by the Spotify Connect ZeroConf protocol spec for DH key derivation. This cannot be changed without breaking protocol compatibility.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>