secret init calls vault.CreateVault(..., "default") (internal/cli/init.go, setupDefaultVault), and CreateVault (internal/vault/management.go) does not check whether the vault already exists: it MkdirAlls the directories, picks a derivation index, overwrites the vault metadata, and init then overwrites the passphrase unlocker and longterm.age. Every existing secret stays encrypted to the old long-term key, which the vault no longer records, so secret get fails for all of them. With a different mnemonic the old key is gone for good; with the same one, recovery needs the old derivation index, which the overwritten metadata no longer holds. The same applies to secret vault create with an existing vault name.
Definition of done
secret init refuses when the default vault already exists, and secret vault create NAME refuses when NAME exists, each with a clear error naming the vault, before anything is written. Use the existing "already exists" sentinel if there is one.
The check is in CreateVault itself, so no caller can bypass it.
Tests: init twice, and vault create with an existing name, each leave the state directory byte-for-byte unchanged (record every file and directory with contents before and after) and the existing secret still decrypts.
TODO.md updated in the same commit.
Sequencing
After #69 lands (it changes CreateVault and init).
Model: opus-5-5
Found in the review of https://git.eeqj.de/sneak/secret/pulls/69. Present on `next`.
## Problem
`secret init` calls `vault.CreateVault(..., "default")` (`internal/cli/init.go`, `setupDefaultVault`), and `CreateVault` (`internal/vault/management.go`) does not check whether the vault already exists: it `MkdirAll`s the directories, picks a derivation index, overwrites the vault metadata, and `init` then overwrites the passphrase unlocker and `longterm.age`. Every existing secret stays encrypted to the old long-term key, which the vault no longer records, so `secret get` fails for all of them. With a different mnemonic the old key is gone for good; with the same one, recovery needs the old derivation index, which the overwritten metadata no longer holds. The same applies to `secret vault create` with an existing vault name.
## Definition of done
- `secret init` refuses when the default vault already exists, and `secret vault create NAME` refuses when `NAME` exists, each with a clear error naming the vault, before anything is written. Use the existing "already exists" sentinel if there is one.
- The check is in `CreateVault` itself, so no caller can bypass it.
- Tests: `init` twice, and `vault create` with an existing name, each leave the state directory byte-for-byte unchanged (record every file and directory with contents before and after) and the existing secret still decrypts.
- `TODO.md` updated in the same commit.
## Sequencing
After https://git.eeqj.de/sneak/secret/pulls/69 lands (it changes `CreateVault` and `init`).
Model: opus-5-5
Labelled critical: running secret init a second time (or secret vault create with an existing name) overwrites the vault key records, and every secret already stored becomes undecryptable for its owner.
Model: opus-5-5
Labelled critical: running `secret init` a second time (or `secret vault create` with an existing name) overwrites the vault key records, and every secret already stored becomes undecryptable for its owner.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found in the review of #69. Present on
next.Problem
secret initcallsvault.CreateVault(..., "default")(internal/cli/init.go,setupDefaultVault), andCreateVault(internal/vault/management.go) does not check whether the vault already exists: itMkdirAlls the directories, picks a derivation index, overwrites the vault metadata, andinitthen overwrites the passphrase unlocker andlongterm.age. Every existing secret stays encrypted to the old long-term key, which the vault no longer records, sosecret getfails for all of them. With a different mnemonic the old key is gone for good; with the same one, recovery needs the old derivation index, which the overwritten metadata no longer holds. The same applies tosecret vault createwith an existing vault name.Definition of done
secret initrefuses when the default vault already exists, andsecret vault create NAMErefuses whenNAMEexists, each with a clear error naming the vault, before anything is written. Use the existing "already exists" sentinel if there is one.CreateVaultitself, so no caller can bypass it.inittwice, andvault createwith an existing name, each leave the state directory byte-for-byte unchanged (record every file and directory with contents before and after) and the existing secret still decrypts.TODO.mdupdated in the same commit.Sequencing
After #69 lands (it changes
CreateVaultandinit).Model: opus-5-5
Labelled critical: running
secret inita second time (orsecret vault createwith an existing name) overwrites the vault key records, and every secret already stored becomes undecryptable for its owner.Model: opus-5-5