fix: pre-landing review fixes for verify (test assertions, ekeys discard, double-report, docs)

Pre-landing review (0 critical, all informational) auto-fixes:
- Tighten external-corrupt test to assert the decrypt-fail message, not any
  external finding (was *"external"*, now *"does not decrypt"*).
- Pin the verified-count in the nested+external happy-path test so a silent
  under-count (exit 0 while skipping a blob) is caught.
- Account for an unsafe dotenv entry in `expected` so a matching stray blob
  isn't double-reported as both unsafe and orphan.
- Discard the unused external `keys` read field (read -r etype epath _).
- Document the optional [project] positional in the README verify row.

Deferred to EGB-701 (stage-2 dedup): the external blob-path literal and the
find-walk overlap with cmd_rekey/cmd_list. Full suite 210/210.
This commit is contained in:
Brian Majewski 2026-06-07 15:22:58 -07:00
parent 33aad4f89a
commit 414c02b902
3 changed files with 12 additions and 4 deletions

View file

@ -169,7 +169,7 @@ secrets clear
| `secrets list` | Show all projects that have stored secrets | | `secrets list` | Show all projects that have stored secrets |
| `secrets rm <project>` | Delete a project's secrets from the store | | `secrets rm <project>` | Delete a project's secrets from the store |
| `secrets rekey` | Generate a new encryption key and re-encrypt everything | | `secrets rekey` | Generate a new encryption key and re-encrypt everything |
| `secrets verify` | Check the current project's `.secrets.json` against the store (missing/orphaned blobs) and decrypt every blob | | `secrets verify [project]` | Check the current project's `.secrets.json` against the store (missing/orphaned blobs) and decrypt every blob. `[project]` overrides the store directory name; the manifest is still read from the current directory |
| `secrets verify --all` | Decrypt-test every blob in every project — a store-wide integrity sweep | | `secrets verify --all` | Decrypt-test every blob in every project — a store-wide integrity sweep |
### Automatic project detection ### Automatic project detection

View file

@ -1980,6 +1980,9 @@ _verify_project() {
if ! _validate_dotenv_rel_path "$rel" 2>/dev/null; then if ! _validate_dotenv_rel_path "$rel" 2>/dev/null; then
echo "FINDING: unsafe dotenv path in $SECRETS_JSON_NAME: '$rel' (will be refused)." >&2 echo "FINDING: unsafe dotenv path in $SECRETS_JSON_NAME: '$rel' (will be refused)." >&2
findings=$((findings + 1)) findings=$((findings + 1))
# Still account for it so a matching stray blob isn't ALSO flagged as an
# orphan (one bad entry → one finding, not two).
expected="$expected$rel.age"$'\n'
continue continue
fi fi
expected="$expected$rel.age"$'\n' expected="$expected$rel.age"$'\n'
@ -1997,8 +2000,9 @@ _verify_project() {
done < <(jq -r '.dotenv // [] | .[]' "$manifest") done < <(jq -r '.dotenv // [] | .[]' "$manifest")
# ── external entries: missing-blob + decrypt ── # ── external entries: missing-blob + decrypt ──
local etype epath ekeys slug erel eblob # verify only needs type + path to locate the blob; keys are irrelevant here.
while IFS=$'\t' read -r etype epath ekeys; do local etype epath slug erel eblob
while IFS=$'\t' read -r etype epath _; do
[ -n "$etype" ] || continue [ -n "$etype" ] || continue
slug=$(_secrets_files_slug "$epath") slug=$(_secrets_files_slug "$epath")
erel="external/$slug.$etype.age" erel="external/$slug.$etype.age"

View file

@ -754,6 +754,9 @@ m_nojq_path() {
"$SECRETS_BIN" push >/dev/null 2>&1 "$SECRETS_BIN" push >/dev/null 2>&1
run "$SECRETS_BIN" verify run "$SECRETS_BIN" verify
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
# Pin the count so a silent under-count (e.g. skipping the nested or external
# blob while still exiting 0) is caught: 3 dotenv + 1 external = 4.
[[ "$output" == *"4 blob(s) verified"* ]] || false
} }
@test "verify: declared-but-missing blob is a finding (exit 1)" { @test "verify: declared-but-missing blob is a finding (exit 1)" {
@ -870,7 +873,8 @@ m_nojq_path() {
printf 'garbage' > "$SECRETS_DIR/verifyextcorrupt/external/"*.age printf 'garbage' > "$SECRETS_DIR/verifyextcorrupt/external/"*.age
run "$SECRETS_BIN" verify run "$SECRETS_BIN" verify
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[[ "$output" == *"external"* ]] || false # Pin the decrypt-fail branch specifically, not just any external finding.
[[ "$output" == *"does not decrypt"* ]] || false
} }
@test "verify: an unsafe dotenv path in the manifest is a finding (exit 1)" { @test "verify: an unsafe dotenv path in the manifest is a finding (exit 1)" {