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
|
local pubkey
|
||||||
pubkey=$(get_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:"
|
info "Done! Your public key is:"
|
||||||
echo " $pubkey"
|
echo " $pubkey"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
@ -2195,6 +2200,22 @@ cmd_which() {
|
||||||
# v1 from v2 during the migration window. v1 = legacy store, no format marker.
|
# v1 from v2 during the migration window. v1 = legacy store, no format marker.
|
||||||
echo "format: v$(_store_format)"
|
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
|
# v2 manifest (.secrets.json): validate and summarize. Validation here
|
||||||
# is deliberately fatal (symlink / malformed / unsupported version) so
|
# is deliberately fatal (symlink / malformed / unsupported version) so
|
||||||
# `secrets which` doubles as the manifest linter.
|
# `secrets which` doubles as the manifest linter.
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ make_second_identity() {
|
||||||
BOB_PUB=$(age-keygen -y "$TEST_TMPDIR/bob.txt")
|
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_with_remote
|
||||||
|
# init now seeds recipients.txt with self — born-multi store.
|
||||||
|
[ -e "$SECRETS_DIR/recipients.txt" ]
|
||||||
create_project_dir myproj
|
create_project_dir myproj
|
||||||
run "$SECRETS_BIN" push
|
run "$SECRETS_BIN" push
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
# No recipients.txt was created by push.
|
# Blob must still decrypt with the store's own key.
|
||||||
[ ! -e "$SECRETS_DIR/recipients.txt" ]
|
|
||||||
# Blob decrypts with the store's own key.
|
|
||||||
run age -d -i "$SECRETS_DIR/key.txt" "$SECRETS_DIR/myproj/.env.age"
|
run age -d -i "$SECRETS_DIR/key.txt" "$SECRETS_DIR/myproj/.env.age"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
@ -49,6 +49,8 @@ make_second_identity() {
|
||||||
init_with_remote
|
init_with_remote
|
||||||
STORE_PUB=$(age-keygen -y "$SECRETS_DIR/key.txt")
|
STORE_PUB=$(age-keygen -y "$SECRETS_DIR/key.txt")
|
||||||
printf '%s\n' "$STORE_PUB" > "$TEST_TMPDIR/elsewhere.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"
|
ln -s "$TEST_TMPDIR/elsewhere.txt" "$SECRETS_DIR/recipients.txt"
|
||||||
create_project_dir myproj
|
create_project_dir myproj
|
||||||
run "$SECRETS_BIN" push
|
run "$SECRETS_BIN" push
|
||||||
|
|
@ -58,6 +60,8 @@ make_second_identity() {
|
||||||
|
|
||||||
@test "recipients list on a legacy store shows the single derived key" {
|
@test "recipients list on a legacy store shows the single derived key" {
|
||||||
init_with_remote
|
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
|
run "$SECRETS_BIN" recipients list
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[[ "$output" == *"single-key"* ]] || false
|
[[ "$output" == *"single-key"* ]] || false
|
||||||
|
|
@ -117,6 +121,8 @@ make_second_identity() {
|
||||||
create_project_dir myproj
|
create_project_dir myproj
|
||||||
run "$SECRETS_BIN" push
|
run "$SECRETS_BIN" push
|
||||||
before=$(cat "$SECRETS_DIR/key.txt")
|
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
|
run "$SECRETS_BIN" rekey
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$(cat "$SECRETS_DIR/key.txt")" != "$before" ]
|
[ "$(cat "$SECRETS_DIR/key.txt")" != "$before" ]
|
||||||
|
|
@ -229,3 +235,23 @@ make_second_identity() {
|
||||||
[ "$status" -ne 0 ]
|
[ "$status" -ne 0 ]
|
||||||
[[ "$output" == *"No recipient matches"* ]] || false
|
[[ "$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