The previous form passed rclone paths like releases:banger/v0.1.0/,
which rclone parses as bucket=banger, key=v0.1.0/... — wrong, because
the actual R2 bucket is named "releases" (BUCKET_PATH was meant as
an in-bucket key prefix only). Uploads 403'd because the token has
no view of a bucket called "banger".
Introduce RCLONE_BUCKET as a separate env var (default: "releases")
and route every rclone copy through ${RCLONE_REMOTE}:${RCLONE_BUCKET}/${BUCKET_PATH}.
The public URLs in the manifest stay unchanged: BASE_URL is the
bucket's public custom domain, so the bucket name is implicit there.
The defaults now resolve to the live setup:
rclone target: releases:releases/banger/<version>/<file>
public URL: https://releases.thaloco.com/banger/<version>/<file>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous form did
COSIGN_PASSWORD="${COSIGN_PASSWORD:-}" cosign sign-blob ...
which set COSIGN_PASSWORD to "" when the caller hadn't exported one.
cosign sees an explicit empty password and tries to decrypt with
it instead of prompting interactively, so any real password-protected
offline key fails with "decryption failed".
Drop the prefix entirely. If COSIGN_PASSWORD is already in env, it
gets inherited normally; if it isn't, cosign prompts on the terminal
— which is the right UX for a maintainer running the publish script
locally with the offline private key.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two bugs found while dry-running the publish flow end-to-end:
1. The awk pipeline that pulled BangerReleasePublicKey out of
verify_signature.go didn't strip Go's raw-string-literal wrapping
(`var ... = ` + backtick on the BEGIN line, trailing backtick on
the END line). The "verify against embedded pub key" step thus
compared sigs against a malformed PEM. Replaced with a sed pair
that yields a clean PEM block byte-identical to cosign.pub.
2. cosign v3.x defaults sign-blob to a new bundle format and
pushes signatures to Rekor; both are incompatible with banger's
"embedded pub key, raw ASN.1 DER signature" trust model.
Add --use-signing-config=false / --tlog-upload=false /
--new-bundle-format=false to opt out, and --insecure-ignore-tlog
on verify-blob. These flags also work on cosign v2.x, so the
script is forward- and backward-compatible across the v2→v3
boundary.
Validated by an end-to-end dry-run on this machine: built binaries,
tarred, sha256summed, cosign-signed, verified against the embedded
pub key, then re-verified through internal/updater's
crypto/ecdsa.VerifyASN1 path — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
README gets a top-level Updating section; docs/privileges.md gains
a step-by-step trust-model writeup of `banger update`. The new
scripts/publish-banger-release.sh drives the manual release cut:
build, tar, sha256sum, cosign sign-blob, verify against the embedded
public key, jq-merge into manifest.json, rclone upload to the R2
bucket. Refuses outright if the embedded key is still the placeholder
so we can't accidentally publish an unverifiable release. Also folds
in gofmt drift accumulated across the updater package and a few
sibling files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>