The stub previously panicked on all methods including NewKeychainUnlocker,
which is called from vault code when processing keychain-type unlocker
metadata. This caused crashes on Linux/Windows when a vault synced from
macOS contained keychain unlockers.
Now returns proper error values, allowing graceful degradation and
cross-platform vault portability.
The decrypted data from io.ReadAll was copied into a memguard
LockedBuffer but the original byte slice was never zeroed, leaving
plaintext in swappable, dumpable heap memory.
NumSecrets() previously looked for non-directory, non-'current' files
directly under each secret directory, but the only children are
'current' (file, excluded) and 'versions' (directory, excluded),
so it always returned 0.
Now checks for the existence of the 'current' file, which is the
canonical indicator that a secret exists and has an active version.
This fixes the safety check in UnlockersRemove that was always
allowing removal of the last unlocker.