The rust:1-bookworm CI image has no libdbus-1-dev, so libdbus-sys's
pkg-config build failed. Enable the dbus store's `vendored` feature to build
libdbus from bundled source (self-contained, the proven path the earlier
keyring-4 build used). `crypto-rust` keeps it OpenSSL-free; openssl-sys is only
an inert lock entry (the conditional `openssl?/vendored` reference), compiled
nowhere. Linux footprint unchanged at 235 crates; vendored libdbus is a
build-time C compile, not new crates.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
keyring 4's `keyring` meta-crate has no feature gating and compiles every
platform credential backend for the target. On Linux that dragged in the zbus
async stack, a redundant libdbus secret-service, the keyutils store, a
sqlite/zstd db-keystore, and OpenSSL (~290 crates in its subtree) — a real cost
on the RAM/CPU-constrained CI runner building with CARGO_BUILD_JOBS=1.
Depend on keyring-core (the API) + exactly one store crate per OS instead:
- macOS -> apple-native-keyring-store (keychain feature)
- Linux -> dbus-secret-service-keyring-store (crypto-rust; libdbus, no openssl)
oauth.rs registers the per-target store as the keyring-core default itself
(replacing keyring::use_native_store). Runtime behavior is unchanged (tokens
still go to the macOS Keychain / Linux Secret Service).
hephd's Linux dependency graph: 401 -> 235 crates (-166), dropping the zbus
ecosystem and two C builds (zstd-sys, plus the redundant secret-service path).
macOS builds + the full suite are green here (228 tests, clippy -D warnings,
fmt, prek); the Linux store path is CI-verified (API confirmed from source).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cheap "seam" that keeps the single-owner hub from calcifying, ahead of
the gilbert -> indri bring-up:
- Replace the single-tenant gate `Store::authorize_owner_sub(sub) -> bool`
with `resolve_owner(sub) -> Option<owner_id>`. The hub auth middleware now
resolves the token's identity to the owner it may act as (Some -> allow,
None -> 403). Behavior is identical for the single-owner hub (claim-on-first;
strangers still 403), but the contract no longer assumes one global owner, so
serving N owners later is additive, not a rewrite. The per-request owner is
marked at the exact line where downstream scoping wires through.
- New how-to docs/how-to/set-up-sync-hub.md: stand up the hub and connect an
existing device as an offline-capable spoke, the data-safe way (Path A: the
hub adopts the device's identity rather than rewriting the device).
The decision (cheap seam now, defer full multi-tenancy + adoption rewrite) is
recorded in the Adoption + multi-tenant task's context doc. Two enabler gaps
the how-to surfaced (heph daemon hub/spoke service flags; Path-A seeding tool)
are filed as Hephaestus tasks.
Green: 228 tests, clippy -D warnings + fmt + prek clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>