Refuse an existing vault before asking for the mnemonic (closes #151)
check / check (push) Canceled after 0s

`secret init` and `secret vault create` asked for the mnemonic and the
unlocker passphrase, and `secret init` printed "Initialized secrets
manager at", before refusing a vault that already exists. The check
`vault.CreateVault` made before writing is now `vault.CheckNewVaultName`,
which both commands call while holding the state directory lock, before
the first prompt; `CreateVault` still calls it. `secret init` prints the
"Initialized" line only once the vault is created, so
`TestMnemonicNotReadNamesOnlyMnemonic` no longer expects it.

Judgement call: the same check validates the name, so `secret vault
create` with an invalid name also fails before the prompts.

Model: opus-5-5
This commit is contained in:
2026-10-14 20:47:29 +00:00
parent fe94e99801
commit e8b442445f
6 changed files with 107 additions and 30 deletions
+47 -4
View File
@@ -220,10 +220,53 @@ func TestMnemonicNotReadNamesOnlyMnemonic(t *testing.T) {
output, err := cmd.CombinedOutput()
require.Error(t, err)
require.Equal(t, "Initialized secrets manager at: "+stateDir+"\n"+
"Error: failed to read mnemonic: stdin is not a terminal (piped input "+
"or script). Please set the SB_SECRET_MNEMONIC environment variable "+
"or run interactively\n", string(output))
require.Equal(t, "Error: failed to read mnemonic: stdin is not a terminal "+
"(piped input or script). Please set the SB_SECRET_MNEMONIC environment "+
"variable or run interactively\n", string(output))
}
// TestCreateExistingVaultAsksForNothing is a regression test for
// https://git.eeqj.de/sneak/secret/issues/151: `secret init` and `secret
// vault create` asked for the mnemonic and the unlocker passphrase before
// refusing a vault that already exists, and `secret init` printed
// "Initialized secrets manager at" first. Each runs here as the built binary,
// with no terminal and neither SB_SECRET_MNEMONIC nor SB_UNLOCK_PASSPHRASE
// set, so asking for either fails. Each must fail saying only that the vault
// exists.
func TestCreateExistingVaultAsksForNothing(t *testing.T) {
t.Parallel()
stateDir := t.TempDir()
_, err := vault.CreateVault(afero.NewOsFs(), stateDir, "default", nil, nil)
require.NoError(t, err)
tests := []struct {
args []string
output string
}{
{
[]string{"init"},
"Error: failed to create default vault: vault default already exists\n",
},
{
[]string{"vault", "create", "default"},
"Error: vault default already exists\n",
},
}
for _, tt := range tests {
//nolint:gosec // G204: test executes the freshly built secret binary
cmd := exec.CommandContext(t.Context(), secretBinaryPath(t), tt.args...)
cmd.Env = []string{
secret.EnvStateDir + "=" + stateDir,
"PATH=" + os.Getenv("PATH"),
"HOME=" + os.Getenv("HOME"),
}
output, err := cmd.CombinedOutput()
require.Error(t, err, "secret %v", tt.args)
require.Equal(t, tt.output, string(output), "secret %v", tt.args)
}
}
// TestStopDuringCreateLeavesWholeVaultOrNone is a regression test for