6 Commits
Author SHA1 Message Date
Tobias GesellchenandClaude Sonnet 5 81b915bfca fix(on-device): stop leaking the speaker's own hostname into BMX/TLS URLs
On an on-device install, soundtouch-service defaulted its server URL to
os.Hostname() when --server-url wasn't set. Since the service runs on the
speaker's own Linux, that returns the speaker's internal variant codename
(e.g. "spotty", "mojo") -- never resolvable, not even by the speaker itself
-- breaking TuneIn/BMX playback with CURL ErrorCode 6 (issue #546).

Add a --deployment-mode/DEPLOYMENT_MODE flag (on-device, private-network,
public-network) so the fallback is chosen deliberately instead of guessed:
on-device defaults to localhost, public-network refuses to start rather
than guess a public address, and the previous hostname-guessing behavior
is kept for private-network/unset installs, now with a startup warning.

The on-device init script sets DEPLOYMENT_MODE=on-device automatically and
now auto-exports aftertouch.conf into the daemon's environment generally,
which also unblocks discussion #610 (setting MGMT_USERNAME/MGMT_PASSWORD
on-device) without any further code change.

Verified end-to-end on real ST20 hardware: service now resolves
http://localhost:8000, a re-migrate updates the speaker's own runtime
config to match, and TuneIn playback works again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 20:12:44 +02:00
Tobias GesellchenandClaude Opus 4.8 1cac9989be fix(service): detect first run by settings.json absence, not empty server_url
Startup treated an empty server_url as "first run" and wrote a fresh
default settings.json via createDefaultSettings, which builds the struct
from CLI flags and does not merge the existing file. A hand-authored
settings.json that sets, say, trust_forwarded_headers but leaves
server_url to the --server-url flag has no server_url, so it was
silently clobbered on first start (losing the operator's keys).

Gate the default-seed (and the lost-volume "first run" notice) on the
ABSENCE of settings.json instead. An existing file is now always
respected; a genuinely empty data dir still gets defaults and the
notice. This also fixes a latent loop where a never-set server_url made
every start look like a first run.

Adds regression tests: settingsFileExists, plus first-run seed both
preserving a hand-authored file and writing defaults when absent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 16:06:13 +02:00
Tobias GesellchenandClaude Sonnet 4.6 93248659a5 fix(tls): also cover derived OAuth subdomain in served cert SAN list
#337's first commit added the OAuth-derivation to the DNS interceptor
but missed the served TLS certificate. With a serverURL of
`http://mac.fritz.box:8000` the cert SAN list covered `mac.fritz.box`
but not `macoauth.fritz.box`, so the speaker would resolve the OAuth
host correctly (via the new DNS hijack) and then immediately fail the
TLS handshake — Spotify / Amazon Music token refresh dies before
reaching AfterTouch.

getDomains now calls discovery.DeriveOAuthHostnames(serverURL) and
discovery.DeriveOAuthHostnames(httpsServerURL), feeding the derived
names into the SAN map alongside the existing entries. IP-based
serverURLs continue to produce no derivation (the OAuth construction
is unrecoverable for them — see the existing oauth_target_reachable
health check).

Tests in cmd/soundtouch-service/main_test.go lock in:
  - Hostname serverURL → derived OAuth variant present in SAN list.
  - IP serverURL → no malformed `192oauth.…` entry leaks in.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:34:36 +02:00
Tobias GesellchenandClaude Sonnet 4.6 3a0b30bc33 feat(tls): persist TLSExtraHosts + Settings UI + speaker_marge_url QuickFix
Operators who deploy AfterTouch on an IP-only host (no DNS hostname) and
who get a speaker_marge_url health warning previously had to SSH in, edit
their systemd unit or docker-compose, add --tls-extra-host, and restart.
The fix is now reachable from the UI:

- datastore.Settings gains TLSExtraHosts []string. At startup
  applyPersistedSettings merges CLI/env values (still authoritative)
  with persisted ones, deduplicating while preserving order.
- /setup/settings (GET) exposes tls_extra_hosts (editable list) and
  tls_san_hosts (the full effective SAN list, read-only).
- /setup/settings (POST) accepts tls_extra_hosts (*[]string so callers
  can distinguish "field omitted" from "explicitly empty").
- Settings tab grows a "TLS extra hosts" textarea + an info panel
  explaining the restart-required dance.
- speaker_marge_url emits a QuickFix labelled "Add <host> to TLS hosts"
  alongside the existing CLI manual command. The fix re-probes the
  device's /info, extracts the margeURL host, and appends it to the
  persisted list — race-safe against stale findings.
- HTTPS-SETUP.md documents both paths.

Tests cover: merge dedup + ordering + whitespace, the new QuickFix
emission shape, and the margeURL host extraction across HTTPS/HTTP/bare
input forms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 20:32:44 +02:00
Tobias Gesellchen 6ee0fc8115 Remove Soundcork fallback 2026-02-26 22:26:35 +01:00
Tobias Gesellchen 087006c483 Add regression test for settings persistence 2026-02-15 23:28:45 +01:00