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>
- Add GetAccountByRefreshToken to amazon.Service — the speaker sends
the bare Atzr| refresh token (extracted from AmazonSecret JSON), not
a surrogate, so lookup must match against Account.RefreshToken
- Add amazonService field, SetAmazonService and IsAmazonConfigured to
Server (step 5 essentials required by the handler)
- Replace HandleBoseAmazonToken 501 stub with full implementation:
lookup by refresh token → RefreshAccessToken; fallback to
GetFreshToken; fallback to HandleBoseProxy if no service configured;
scope intentionally omitted from response
- Add handler tests covering the by-refresh-token path (mock LWA
server), the default-account path, and the no-service fallback
- Unlock assertions in post_oauth_token_amazon.http integration test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract DH key exchange crypto from pkg/service/spotify into new
pkg/service/zeroconf package with exported functions and
AuthTypeOAuthToken constant (both Spotify and Amazon use auth type 4)
- Reduce pkg/service/spotify/zeroconf.go to thin wrappers around the
shared package; public API (PushSpotifyCredentials, ZeroConfGetInfo)
is preserved
- Add pkg/service/amazon package mirroring the Spotify service with
Amazon-specific differences: LWA endpoints, POST body credentials
(not Basic Auth), user_id/name profile fields, amazon/accounts.json
- Add PushAmazonCredentials delegating to shared zeroconf.PushCredentials
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>