Private keys have lived as plaintext-on-disk files guarded only by a
passphrase. This puts them in the same end-to-end-encrypted vaults as
.env secrets, and adds an agent path so a machine can use a key without
ever writing one to its disk.
- `ssh` provider: ~/.ssh as a value bag. Files are picked by sniffing
contents (PRIVATE KEY blocks, ssh-*/ecdsa-*/sk-* public keys) plus
config, config.d/* and allowed_signers. known_hosts and
authorized_keys are host-specific and access-granting, so they need
an explicit --include.
- Each file is one secret carrying a JSON envelope of path, mode and
body. The engine only hands write() the secrets that CHANGED, so a
separate manifest secret would be absent whenever a key's contents
change but the file list doesn't — self-describing values keep every
restore total.
- `logicsrc secrets ssh push|pull|list|agent`, addressed by PERSON not
project: the vault is ssh--<username>, which teams vaults reads as
project ssh, env <username>. One teammate's keys never land in
another's restore; sharing stays a deliberate teams grant.
- Both directions hold back anything that would overwrite a file that
already differs, and say what they skipped. --force opts in. A
restore onto a machine with its own keys is otherwise a way to lose
them.
- Restores chmod each file back to its recorded mode; writeFileSync's
mode applies only on create, so an existing world-readable key would
otherwise stay world-readable. The adapter declares delete:false.
- push warns about passphrase-less private keys before they go up.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>