Commit Graph
10 Commits
Author SHA1 Message Date
vicrodh 196887534a chore: log the three failures that were silently discarded
Volume restore (desktop session and qbzd driver), a playback-thread panic
at stop, and a credentials decrypt failure (now naming the file and the
likely cause, without the inert legacy retry).

cc
2026-09-13 03:36:51 -06:00
vicrodh 0c7629b275 fix(credentials): derive the Windows machine id from COMPUTERNAME
machine_id_stable_source had no Windows arm. It read /etc/machine-id, then
HOSTNAME, then USER -- two UNIX names Windows itself never sets but an
MSYS environment may.

Measured on the box: Git-Bash sets HOSTNAME as a shell variable it does not
export, so a child process reads None, and leaves USER empty. The chain
returned None and the persisted random fallback kept the key stable. Stable by
accident: any environment that exports either name would silently derive a
different key, and a key that moves is a credentials file that no longer
decrypts.

COMPUTERNAME is set by Windows for every process, however the app was
launched, so the value is now stable by construction. Approved with the
one-time re-authentication that moving the key costs; verified by smoke that
no re-authentication was in fact needed, because the master key lives in the
Credential Manager and this derivation is the fallback path.

cc
2026-08-27 12:44:21 -06:00
vicrodh b94e0e6cdb fix(secrets): select the keyring backend per target and refuse the mock
qbz-credentials still asked for the Linux features on every target with
default_features on. keyring 3 has no default backend: without the
per-platform feature it exports the in-memory mock, whose writes succeed
and whose contents die with the process, so the offline-cache master key
was regenerated every launch and every wrapped blob failed AES-GCM on the
next start, with the logs reporting a working keyring. It survived only
because Cargo unified features with qbz-secrets, which is the fragility
the per-target block exists to remove.

Also refuse a non-disk-backed backend at runtime and take the KDF path.
Measured in keyring-3.6.3, not assumed: windows.rs, macos.rs and
secret_service.rs all inherit the trait default UntilDelete
(credential.rs:171); mock.rs:228 overrides it to EntryOnly. Testing for
ProcessOnly, as first drafted, would never have fired.

cc
2026-08-26 23:06:41 -06:00
vicrodh 47506cb5b7 fix(credentials): derive the daemon token key without the XDG portal secret
The token encryption key mixed in the XDG portal secret (session-bus
dependent): a login run in a graphical session wrote a token an
init-started/headless qbzd could never decrypt, reported as a bare
"not logged in". PortalKey policy: desktop root keeps Session, daemon
root uses Never; one-shot migration on read (decrypt with Session,
rewrite portal-free); oauth_token_file_present_at() +
latch_undecryptable_token() so status distinguishes "no token" from
"token I cannot decrypt". Live-verified 3x (OpenRC, headless Pi,
migration path).

km
2026-07-22 09:03:07 -06:00
vicrodh 4d0f52138a feat(qbzd): headless runtime bring-up with daemon-root stores and credential restore
Adds additive _at credential fns (crypto/format untouched), DaemonAdapter
broadcast bus, numbered boot per 01 §8.1 incl. the #521 shutdown pair.

cc
2026-07-14 13:40:49 -06:00
Afonso Jorge Ramos 39dccd8b01 fix(credentials): tighten permissions of existing secret files on load 2026-07-13 13:48:30 +02:00
Afonso Jorge Ramos e1c34005e0 fix(credentials): write secret files with mode 0o600 on Unix
Salt, machine-id fallback, encrypted credentials, and OAuth token files
must not inherit a permissive umask.
2026-07-13 13:47:18 +02:00
vicrodh 6c9964481a fix(dbus): stop forcing the zbus 5 executor onto tokio
zbus features unify across the dependency graph and "tokio" wins over
"async-io": enabling it via rfd, ashpd (secret portal) and ksni's
default features flipped the shared zbus 5 executor to tokio for
accesskit_unix/atspi too — Slint's accessibility backend opens its
D-Bus connection on a plain thread and panicked at startup ("there is
no reactor running, must be called from the context of a Tokio 1.x
runtime"), killing AT-SPI support. Switch every zbus-5 consumer we
control to the async-io backend (rfd "async-std", ashpd "async-io",
ksni default-features off + "async-io"): async-io connections
self-drive from any thread and the futures still await fine inside our
tokio runtime. The zbus 4 group (keyring/secret-service/mpris-server/
qbz-audio) is a separate feature graph and stays on tokio by design.

cc
2026-07-05 10:26:18 -06:00
vicrodh 46c15f507b feat(qobuz): track lyrics endpoint with live-verified wire DTOs
Add /track/lyricsUrl (signed RPC, method name "tracklyricsUrl") plus
the CDN document fetch through the offline choke point. Wire shapes
were validated against live captures (2026-06-10) and diverge from the
inferred yaml: numeric track_id in the step-1 envelope, CDN document
wrapped in {translation_langs, publishers, writers, original}, "wsync"
word-synced discriminator instead of "lsync" (per-word timestamps),
plain lines as objects, and miss = HTTP 404 error body mapped to a
typed Ok(None) instead of an error. Unit tests deserialize fixture
excerpts of the captures; examples/lyrics_probe.rs is the read-only
live probe used for the capture.

Also expose qbz_credentials::load_oauth_token_from_file so a stale
keyring entry cannot shadow the authoritative encrypted token file.

cc
2026-06-10 16:03:44 -06:00
vicrodh aa64f3fafb refactor(qbz-credentials): extract credential store into a crate
Moves the credentials module (keyring + AES-256-GCM encrypted file
store for Qobuz credentials and the OAuth token) out of src-tauri into
a new qbz-credentials crate. src-tauri/credentials re-exports it, so the
Tauri app keeps identical behavior while the Slint shell can share the
exact same implementation, encrypted file, and keyring entries.

The module was already fully self-contained (no Tauri, no crate::
references); only the dependency declarations move with it.

cc
2026-05-18 13:42:17 -06:00