You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
No OS keychain, on any OS (operator ruling 2026-10-10). abstractcore.comms.email.SecretVault seals with AES-256-GCM under ONE key file — by default <config dir>/secrets/sealing.key (0600 in a 0700 folder, 32 bytes from os.urandom, made on first use); a host passes its own (SecretVault(dir, key_file=...), EmailAccountStore(..., key_file=..., vault=...); AbstractGateway uses <data dir>/secrets/sealing.key for every store of its data folder). Each seal binds the store's place relative to the key root, so a folder moved or restored with its secrets/ keeps working and a sealed file copied into another store does not open. The keyring dependency is removed and nothing imports it (the email test suite fails any test during which keyring is imported). On Windows, where Python's modes only toggle the read-only flag, the key folder and file also get a best-effort owner-only ACL (icacls /inheritance:r /grant:r <user>). New helpers ensure_key_file, read_key_file, key_fingerprint.
Credentials sealed by an older version with the key in a keychain are never opened (no keychain call, no password prompt): load() raises EmailSecretUnavailable (email_secret_sealed_with_keychain, or the host's own sentence and code), legacy_keychain() / retire_legacy_keychain() let a host mark or move such a store, and public() says secret_storage: "old-keychain" with the sentence in secret_warning. Stores sealed with the older per-store key file (secret.key) are opened and re-sealed under the sealing key (reseal_legacy=False reads without writing). secret_storage is now sealing-key | old-keychain | key-file (was os-keychain | key-file); --key-storage accepts auto / file only (both mean the key file), key_backend="keyring" is refused. What the key file protects (copies without secrets/; not code running as the same user, as before) is in docs/email.md.
Changed
Requires AbstractVoice 0.15.0 or newer in the base install and in the [apple] and [gpu] extras (abstractvoice[all-apple], abstractvoice[all-gpu]), the version whose engine runtime carries the mlx-whisper engine; the route engine check's floor moves with it.
Speech input (input.voice) recommends Whisper large-v3 on every host (was base). On Apple silicon with the apple setting the pick is AbstractVoice's mlx-whisper engine, which runs it on the Apple GPU (about 1.4 s for a 17-second clip on an M5 Max, against about 20 s on the processor); the light install and every other host keep faster-whisper (CUDA on an NVIDIA GPU). Stored routes are never changed; fresh installs and apply-recommended follow the new pick. On a processor, the recommendation notes that large-v3-turbo is faster (about 6 s for that clip).
recommendations.voice_input_hint(route, host): the served one-line hint for a configured speech-input route (on Apple silicon, a faster-whisper route runs on the processor while mlx-whisper runs the same model on the GPU). The capability-defaults grid carries it on the input.voice row as route_hint{code, sentence, route}.
Fixed
The Hugging Face weights probe counts .npz weight files (MLX checkpoints such as mlx-community/whisper-large-v3-mlx), which it reported as not downloaded.