Settings window titles itself after the visible pane like System
Settings; the popover subtitle adopts the website tagline (Your AI
Bill, Itemized); About stops printing dev (dev) when version and build
match; remaining user-facing em-dashes across popover and service
strings become sentence breaks.
Cache reads run on the background quota timer, so they must not be able to
put a panel on screen. Measured on macOS 15 against a throwaway keychain:
with the keychain locked, SecItemCopyMatching blocks on an unlock panel even
when the query carries kSecUseAuthenticationUI: ...Fail or a non-interactive
LAContext. Both of those govern the data-protection keychain; unlocking a
file-based keychain is something securityd drives itself. The only reliable
suppression is not issuing the read, so check lock state first and report
.unavailable instead.
.unavailable is separate from readFailed on purpose: a locked keychain means
"cannot look right now", not "the item is gone", and callers must not turn it
into a disconnect. It also carries a readable errorDescription so a -25308
reaching the UI reads as "Keychain unavailable" rather than a struct dump.
SecKeychainGetStatus is soft-deprecated with no replacement that reports
file-keychain lock state; annotating the warning away only moves it to the
call site, so it is left visible with a comment.
Adds the first test that touches a real Keychain, against a throwaway service
name no build reads, skipped when the host has no usable Keychain.
Stop writing OAuth caches as Application Support JSON. Persist
CodeBurn-owned items in Keychain, secure-read and migrate leftover
0644 files only after read-back verification, and keep Claude from
storing a refresh token.