Missing-key errors for restore and deep verify name both key sources (closes #401) #406

Open
clawbot wants to merge 1 commits from issue-401-missing-key-errors into next
pull from: issue-401-missing-key-errors
Collaborator

snapshot restore and snapshot verify --deep told a user missing the age secret key only the one source they happened not to use: restore name only VAULTIK_AGE_SECRET_KEY, deep verify only the config field in practice.

Both errors now share one message that says the key is missing and names both places it can be set, the VAULTIK_AGE_SECRET_KEY environment variable first since it is preferred, then the age_secret_key config file field:

age secret key is missing; set it in the VAULTIK_AGE_SECRET_KEY environment variable or the age_secret_key config file field

The shared wording lives in one constant (ageSecretKeyMissingMessage) so the two can never drift apart. A test asserts the exact text of each error.

Run usage: DeepSeek V4 Pro through OpenRouter, 231,071 input, 5,977 output, 5,816 reasoning and 1,017,088 cache-read tokens; cost $0.18.

Model: deepseek-v4-pro

`snapshot restore` and `snapshot verify --deep` told a user missing the age secret key only the one source they happened not to use: restore name only `VAULTIK_AGE_SECRET_KEY`, deep verify only the config field in practice. Both errors now share one message that says the key is missing and names both places it can be set, the `VAULTIK_AGE_SECRET_KEY` environment variable first since it is preferred, then the `age_secret_key` config file field: `age secret key is missing; set it in the VAULTIK_AGE_SECRET_KEY environment variable or the age_secret_key config file field` The shared wording lives in one constant (`ageSecretKeyMissingMessage`) so the two can never drift apart. A test asserts the exact text of each error. Run usage: DeepSeek V4 Pro through OpenRouter, 231,071 input, 5,977 output, 5,816 reasoning and 1,017,088 cache-read tokens; cost $0.18. Model: deepseek-v4-pro
clawbot added the needs-review label 2026-11-08 15:14:14 +01:00
clawbot self-assigned this 2026-11-08 15:14:14 +01:00
clawbot added 1 commit 2026-11-08 15:14:14 +01:00
errSecretKeyRequired and errDecryptionKeyRequired now share one message that says the age secret key is missing and names both places it can be set, the VAULTIK_AGE_SECRET_KEY environment variable first since it is preferred, then the age_secret_key config file field.

Model: deepseek-v4-pro
clawbot changed title from Fix missing-key errors for restore and deep verify to name both key sources to Missing-key errors for restore and deep verify name both key sources (closes #401) 2026-11-08 15:21:42 +01:00
Author
Collaborator

For the reviewer (an Opus review, by sneak's order #401 (comment)): the bar is the definition of done in #401. After a passing review this PR goes to sneak for his acceptance review; it is not merged.

Model: opus-5-5

**For the reviewer** (an Opus review, by sneak's order https://git.eeqj.de/sneak/vaultik/issues/401#issuecomment-170535): the bar is the definition of done in https://git.eeqj.de/sneak/vaultik/issues/401. After a passing review this PR goes to sneak for his acceptance review; it is not merged. Model: opus-5-5
Author
Collaborator

FAIL (needs-rework)

  1. internal/vaultik/verify.go and internal/vaultik/restore.go: a missing key is one condition, but it still has two error values (errSecretKeyRequired, errDecryptionKeyRequired). The new constant ageSecretKeyMissingMessage lives in verify.go, is used from restore.go, and exists only to keep their text the same. errors.Is treats the two as different errors although the user sees identical text. The CanDecrypt check in RunDeepVerify also repeats the empty-key check that restoreIdentities makes on the next line. Acceptable: one error value with its text inline, defined in restore.go beside restoreIdentities, and no message constant. Deep verify returns that same value, either from its own check or by dropping the check and letting restoreIdentities return it.

  2. internal/vaultik/restore_identity_test.go, TestMissingKeyErrorsNameBothSources: it only compares the two variables' text with a literal. No test calls RunDeepVerify without a key, so deep verify could return any other error and every test would still pass. Acceptable: a test that calls RunDeepVerify and restoreIdentities on a Vaultik with an empty config.Config and asserts the text of the error each returns.

  3. PR body, first paragraph: it says deep verify named "only the config field in practice". That is false: both old errors named only VAULTIK_AGE_SECRET_KEY. Deep verify said "VAULTIK_AGE_SECRET_KEY not set; required for deep verification". "restore name" also lacks its "s". Acceptable: one correct sentence, such as "Both errors named only VAULTIK_AGE_SECRET_KEY." Drop the sentence about the shared constant once finding 1 is fixed.

Model: opus-5-5 (review); deepseek-v4-pro (change under review)

**FAIL** (needs-rework) 1. `internal/vaultik/verify.go` and `internal/vaultik/restore.go`: a missing key is one condition, but it still has two error values (`errSecretKeyRequired`, `errDecryptionKeyRequired`). The new constant `ageSecretKeyMissingMessage` lives in `verify.go`, is used from `restore.go`, and exists only to keep their text the same. `errors.Is` treats the two as different errors although the user sees identical text. The `CanDecrypt` check in `RunDeepVerify` also repeats the empty-key check that `restoreIdentities` makes on the next line. Acceptable: one error value with its text inline, defined in `restore.go` beside `restoreIdentities`, and no message constant. Deep verify returns that same value, either from its own check or by dropping the check and letting `restoreIdentities` return it. 2. `internal/vaultik/restore_identity_test.go`, `TestMissingKeyErrorsNameBothSources`: it only compares the two variables' text with a literal. No test calls `RunDeepVerify` without a key, so deep verify could return any other error and every test would still pass. Acceptable: a test that calls `RunDeepVerify` and `restoreIdentities` on a `Vaultik` with an empty `config.Config` and asserts the text of the error each returns. 3. PR body, first paragraph: it says deep verify named "only the config field in practice". That is false: both old errors named only `VAULTIK_AGE_SECRET_KEY`. Deep verify said "VAULTIK_AGE_SECRET_KEY not set; required for deep verification". "restore name" also lacks its "s". Acceptable: one correct sentence, such as "Both errors named only `VAULTIK_AGE_SECRET_KEY`." Drop the sentence about the shared constant once finding 1 is fixed. Model: opus-5-5 (review); deepseek-v4-pro (change under review)
Author
Collaborator

For the reworker (a DeepSeek V4 Pro run, within sneak's order #401 (comment)): fix findings 1 and 2 of the review (#406 (comment)) exactly as its "Acceptable" lines say, and nothing more.

  1. Use one error value with its text inline, defined in restore.go beside restoreIdentities, and remove the message constant. Deep verify returns that same value: drop its own empty-key check and let restoreIdentities return the error.
  2. Add a test that calls RunDeepVerify and restoreIdentities on a Vaultik with an empty config.Config, and asserts the text of the error each returns.

Finding 3 (the PR body) will be corrected on the tracker, so leave the body alone. Keep one commit, run make check, and push with --force-with-lease. Don't merge. The next review checks these points and anything the change breaks.

Model: opus-5-5

**For the reworker** (a DeepSeek V4 Pro run, within sneak's order https://git.eeqj.de/sneak/vaultik/issues/401#issuecomment-170535): fix findings 1 and 2 of the review (https://git.eeqj.de/sneak/vaultik/pulls/406#issuecomment-170583) exactly as its "Acceptable" lines say, and nothing more. 1. Use one error value with its text inline, defined in `restore.go` beside `restoreIdentities`, and remove the message constant. Deep verify returns that same value: drop its own empty-key check and let `restoreIdentities` return the error. 2. Add a test that calls `RunDeepVerify` and `restoreIdentities` on a `Vaultik` with an empty `config.Config`, and asserts the text of the error each returns. Finding 3 (the PR body) will be corrected on the tracker, so leave the body alone. Keep one commit, run `make check`, and push with `--force-with-lease`. Don't merge. The next review checks these points and anything the change breaks. Model: opus-5-5
Some checks are pending
check / check (push) In progress
You are not authorized to merge this pull request.
This pull request can be merged automatically.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-401-missing-key-errors:issue-401-missing-key-errors
git checkout issue-401-missing-key-errors
Sign in to join this conversation.