feat: init born-multi recipients.txt + which recipients line (EGB-283)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cad5b66f77
commit
50b73083f1
2 changed files with 51 additions and 4 deletions
21
secrets
21
secrets
|
|
@ -1260,6 +1260,11 @@ Your key file has been left untouched."
|
|||
local pubkey
|
||||
pubkey=$(get_pubkey)
|
||||
|
||||
# EGB-283: born-multi — seed recipients.txt with this store's public key so
|
||||
# the store is multi-recipient-ready from day one. Committed (not gitignored),
|
||||
# staged by the first push like .secrets-format.
|
||||
printf '# self\n%s\n' "$pubkey" > "$RECIPIENTS_FILE"
|
||||
|
||||
info "Done! Your public key is:"
|
||||
echo " $pubkey"
|
||||
echo ""
|
||||
|
|
@ -2195,6 +2200,22 @@ cmd_which() {
|
|||
# v1 from v2 during the migration window. v1 = legacy store, no format marker.
|
||||
echo "format: v$(_store_format)"
|
||||
|
||||
# EGB-283: surface the recipient set (store-scoped; one key per team member).
|
||||
if [ -e "$RECIPIENTS_FILE" ] && [ ! -L "$RECIPIENTS_FILE" ]; then
|
||||
local rcount=0 rk rn rnames=""
|
||||
while IFS=$'\t' read -r rk rn; do
|
||||
rcount=$((rcount + 1))
|
||||
[ -n "$rn" ] && rnames="${rnames:+$rnames, }$rn"
|
||||
done < <(_recipients_dump)
|
||||
if [ -n "$rnames" ]; then
|
||||
echo "recipients: $rcount ($rnames)"
|
||||
else
|
||||
echo "recipients: $rcount"
|
||||
fi
|
||||
else
|
||||
echo "recipients: single-key (no $RECIPIENTS_FILE_NAME)"
|
||||
fi
|
||||
|
||||
# v2 manifest (.secrets.json): validate and summarize. Validation here
|
||||
# is deliberately fatal (symlink / malformed / unsupported version) so
|
||||
# `secrets which` doubles as the manifest linter.
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ make_second_identity() {
|
|||
BOB_PUB=$(age-keygen -y "$TEST_TMPDIR/bob.txt")
|
||||
}
|
||||
|
||||
@test "push without recipients.txt stays single-key (legacy behavior)" {
|
||||
@test "push with only-self recipients.txt encrypts to the store key (born-multi)" {
|
||||
init_with_remote
|
||||
# init now seeds recipients.txt with self — born-multi store.
|
||||
[ -e "$SECRETS_DIR/recipients.txt" ]
|
||||
create_project_dir myproj
|
||||
run "$SECRETS_BIN" push
|
||||
[ "$status" -eq 0 ]
|
||||
# No recipients.txt was created by push.
|
||||
[ ! -e "$SECRETS_DIR/recipients.txt" ]
|
||||
# Blob decrypts with the store's own key.
|
||||
# Blob must still decrypt with the store's own key.
|
||||
run age -d -i "$SECRETS_DIR/key.txt" "$SECRETS_DIR/myproj/.env.age"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
|
@ -49,6 +49,8 @@ make_second_identity() {
|
|||
init_with_remote
|
||||
STORE_PUB=$(age-keygen -y "$SECRETS_DIR/key.txt")
|
||||
printf '%s\n' "$STORE_PUB" > "$TEST_TMPDIR/elsewhere.txt"
|
||||
# Remove the born-multi recipients.txt so we can replace it with a symlink.
|
||||
rm -f "$SECRETS_DIR/recipients.txt"
|
||||
ln -s "$TEST_TMPDIR/elsewhere.txt" "$SECRETS_DIR/recipients.txt"
|
||||
create_project_dir myproj
|
||||
run "$SECRETS_BIN" push
|
||||
|
|
@ -58,6 +60,8 @@ make_second_identity() {
|
|||
|
||||
@test "recipients list on a legacy store shows the single derived key" {
|
||||
init_with_remote
|
||||
# Simulate a legacy store by removing the born-multi recipients.txt.
|
||||
rm -f "$SECRETS_DIR/recipients.txt"
|
||||
run "$SECRETS_BIN" recipients list
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"single-key"* ]] || false
|
||||
|
|
@ -117,6 +121,8 @@ make_second_identity() {
|
|||
create_project_dir myproj
|
||||
run "$SECRETS_BIN" push
|
||||
before=$(cat "$SECRETS_DIR/key.txt")
|
||||
# Simulate a legacy store by removing the born-multi recipients.txt.
|
||||
rm -f "$SECRETS_DIR/recipients.txt"
|
||||
run "$SECRETS_BIN" rekey
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(cat "$SECRETS_DIR/key.txt")" != "$before" ]
|
||||
|
|
@ -229,3 +235,23 @@ make_second_identity() {
|
|||
[ "$status" -ne 0 ]
|
||||
[[ "$output" == *"No recipient matches"* ]] || false
|
||||
}
|
||||
|
||||
@test "init seeds recipients.txt with the new store key (born-multi)" {
|
||||
run "$SECRETS_BIN" init
|
||||
[ "$status" -eq 0 ]
|
||||
[ -e "$SECRETS_DIR/recipients.txt" ]
|
||||
STORE_PUB=$(age-keygen -y "$SECRETS_DIR/key.txt")
|
||||
run cat "$SECRETS_DIR/recipients.txt"
|
||||
[[ "$output" == *"$STORE_PUB"* ]] || false
|
||||
}
|
||||
|
||||
@test "which reports the recipient count" {
|
||||
init_with_remote
|
||||
make_second_identity
|
||||
run "$SECRETS_BIN" recipients add "$BOB_PUB" --name bob
|
||||
create_project_dir myproj
|
||||
run "$SECRETS_BIN" which
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"recipients: 2"* ]] || false
|
||||
[[ "$output" == *"bob"* ]] || false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue