From 4bed04ac9d42e286ad2012ab7f592099e21c16e8 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Mon, 11 May 2026 07:04:08 +0200 Subject: [PATCH 01/10] feat(release): BEE-1781 cosign keyless + CycloneDX SBOM + SLSA L3 provenance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every release artifact now ships with a complete supply-chain attestation: - cosign keyless signature (.sig) + Fulcio cert (.pem) tied to the workflow OIDC identity at this commit. Sigstore Rekor records the signing event in its transparency log. - CycloneDX SBOM (.cdx.json) per artifact via syft, listing component + license + version metadata. - SLSA L3 build provenance (.intoto.jsonl) covering every artifact in the release, generated by slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 on an isolated hermetic builder. Pipeline wiring: - New per-matrix step emits each archive's SHA256 + uploads as a hash sidecar. - New combine-hashes job aggregates per-target hashes into the base64 subject blob expected by the SLSA reusable workflow. - New provenance job consumes the blob, uploads the resulting intoto.jsonl to the release. - release job: cosign-installer + sign-blob loop + syft SBOM step + permissions: id-token: write for keyless OIDC. - Body composition adds a ๐Ÿ›ก๏ธ Supply chain section with verify snippets and a cross-link to docs/supply-chain.md. New: .github/workflows/verify-supply-chain.yml โ€” runs on every published release (and manual dispatch) to exercise the same verification recipe a downstream consumer would, catching drift between signing pipeline and documented verify steps. New: docs/supply-chain.md โ€” canonical install + verify recipe per OS, trust-root reference, threat model. External scaffolding (external/tap + external/scoop-bucket) gets comment-only mentions of cosign + SLSA so the transplanted files in beeping-io/tap and beeping-io/scoop-bucket carry the same context. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 175 +++++++++++++++- .github/workflows/verify-supply-chain.yml | 124 ++++++++++++ docs/supply-chain.md | 187 ++++++++++++++++++ external/README.md | 17 +- external/scoop-bucket/bucket/beeping-cli.json | 2 +- external/tap/Formula/beeping-cli.rb | 6 + 6 files changed, 499 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/verify-supply-chain.yml create mode 100644 docs/supply-chain.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 91bdcc3..6827b39 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -233,10 +233,96 @@ jobs: path: beeping-cli-${{ matrix.target }}.${{ matrix.archive }} retention-days: 30 + - name: ๐Ÿ”ข Emit per-artifact SHA256 (BEE-1781 โ€” SLSA L3 input) + # The SLSA L3 reusable workflow (`generator_generic_slsa3.yml`) + # signs a base64-encoded list of ` ` pairs. + # Each matrix entry contributes one line; a downstream + # `combine-hashes` job aggregates them into a single base64 + # blob that the SLSA generator consumes. Failed matrix entries + # contribute nothing (the upload is conditional on file + # existence), so partial matrix releases still get a valid โ€” + # but partial โ€” provenance attestation. + id: hash + if: hashFiles(format('beeping-cli-{0}.{1}', matrix.target, matrix.archive)) != '' + shell: bash + run: | + line=$(shasum -a 256 "beeping-cli-${{ matrix.target }}.${{ matrix.archive }}") + echo "$line" + echo "hash-line=$line" >> "$GITHUB_OUTPUT" + + - name: โฌ†๏ธ Upload hash sidecar + if: steps.hash.outputs.hash-line + uses: actions/upload-artifact@v4 + with: + name: hash-${{ matrix.target }} + # cargo-mutants-style sidecar: tiny text file consumed by the + # combine-hashes job below. Retention 1 day is enough โ€” once + # the SLSA workflow signs them, the sidecars are not needed. + path: | + beeping-cli-${{ matrix.target }}.${{ matrix.archive }} + retention-days: 1 + if-no-files-found: ignore + + combine-hashes: + name: ๐Ÿงฎ Combine SLSA subjects (BEE-1781) + needs: build + runs-on: ubuntu-latest + # Run even if some matrix entries failed โ€” the SLSA provenance + # then attests the artifacts that DID build, mirroring the + # partial-release behaviour of the `release` job below. + if: ${{ !cancelled() && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} + outputs: + hashes: ${{ steps.combine.outputs.hashes }} + steps: + - uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: true + - name: ๐Ÿงฎ Aggregate per-artifact SHA256 + base64-encode + id: combine + run: | + set -euo pipefail + cd artifacts + # Concatenate per-artifact hashes into one ` ` + # newline-separated string, then base64-encode the whole + # blob (without `-w 0` since macOS / BSD `base64` defaults + # to no-wrap on Linux GH runners running coreutils). + # The SLSA reusable workflow expects this exact format. + if compgen -G '*.tar.xz' >/dev/null || compgen -G '*.zip' >/dev/null; then + HASHES=$(shasum -a 256 -- *.tar.xz *.zip 2>/dev/null || shasum -a 256 -- *.tar.xz) + echo "$HASHES" + B64=$(printf '%s\n' "$HASHES" | base64 -w0) + echo "hashes=$B64" >> "$GITHUB_OUTPUT" + else + echo "::warning::No release artifacts found โ€” skipping SLSA provenance" + echo "hashes=" >> "$GITHUB_OUTPUT" + fi + + provenance: + name: ๐Ÿ›ก๏ธ SLSA L3 provenance (BEE-1781) + needs: combine-hashes + if: ${{ !cancelled() && needs.combine-hashes.outputs.hashes != '' }} + permissions: + id-token: write # OIDC token for keyless signing + contents: write # upload .intoto.jsonl to the release + actions: read # SLSA generator inspects the workflow run + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 + with: + base64-subjects: ${{ needs.combine-hashes.outputs.hashes }} + upload-assets: true + upload-tag-name: ${{ github.ref_name }} + provenance-name: beeping-cli.intoto.jsonl + release: name: ๐Ÿš€ Publish GitHub Release - needs: build + needs: [build, provenance] runs-on: ubuntu-latest + permissions: + # `id-token: write` is required for cosign keyless signing + # (Sigstore Fulcio fetches the OIDC token from the GH Actions + # runtime). `contents: write` is needed by `gh release upload`. + id-token: write + contents: write # `!cancelled()` lets the release job run even when some build matrix # entries fail (e.g. Windows + ARM64 deferred to BEE-1897). The job # then composes a release with whatever artifacts succeeded โ€” the @@ -266,12 +352,60 @@ jobs: echo '--- SHA256SUMS ---' cat SHA256SUMS + - name: ๐Ÿ” Install cosign (BEE-1781 โ€” keyless signing) + uses: sigstore/cosign-installer@v3 + with: + cosign-release: v2.4.1 + + - name: ๐Ÿ” cosign sign-blob each artifact (BEE-1781) + # Keyless signing via the GH Actions OIDC identity. Fulcio + # issues a short-lived cert tied to the workflow + ref + + # event_name; the resulting `.sig` + `.pem` pair lets users + # verify the artifact's provenance without managing keys. + # We sign every published artifact (tarballs + zip + the + # SHA256SUMS file itself) so the chain of trust is complete: + # SHA256SUMS provides integrity for partial downloads; the + # cosign sigs provide authenticity for the publishing identity. + env: + COSIGN_YES: "true" + run: | + cd artifacts + for f in *.tar.xz *.zip SHA256SUMS; do + [ -f "$f" ] || continue + cosign sign-blob \ + --output-signature "${f}.sig" \ + --output-certificate "${f}.pem" \ + "$f" + echo "::notice::signed $f -> $f.sig + $f.pem" + done + + - name: ๐Ÿ“œ SBOM CycloneDX per artifact (BEE-1781) + # `anchore/sbom-action` introspects each artifact and emits a + # CycloneDX JSON SBOM. Per-artifact SBOMs let downstream + # consumers verify that, e.g. the Linux x86_64 binary was + # built from the same crate set as the macOS arm64 binary. + # The action uses `syft` under the hood; default detector + # output is JSON-encoded CycloneDX 1.6. + run: | + # Install syft separately so we can iterate per artifact; + # the action wrapper expects a single artifact at a time. + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin + cd artifacts + for f in *.tar.xz *.zip; do + [ -f "$f" ] || continue + syft "$f" -o cyclonedx-json="${f}.cdx.json" + echo "::notice::SBOM emitted: $f.cdx.json" + done + - name: ๐Ÿš€ Upsert release + upload assets # release-please creates a non-draft release before this workflow # fires. If absent (e.g. manual tag for testing), fall back to a # draft so a human reviews before promoting. The upload step is # idempotent via `--clobber` โ€” re-running this job replaces assets - # without duplicates. + # without duplicates. Uploads everything in `artifacts/`: tarballs + # + zips + SHA256SUMS + cosign sigs/certs (BEE-1781) + per-artifact + # CycloneDX SBOMs (BEE-1781). The SLSA L3 `.intoto.jsonl` is + # uploaded by the `provenance` reusable workflow upstream. env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -284,12 +418,15 @@ jobs: fi gh release upload "$TAG" artifacts/* --clobber - - name: ๐Ÿ“ Compose release body with Downloads + Verify (BEE-1780) - # Append a "## ๐Ÿ“ฆ Downloads" + "## ๐Ÿ” Verify" section to whatever - # release-please generated (CHANGELOG content). Idempotent via - # awk-based strip of any previous Downloads section before - # appending โ€” re-running this job overwrites the Downloads - # section in-place without duplicating it. + - name: ๐Ÿ“ Compose release body (Downloads + Verify + Supply chain) + # Append `## ๐Ÿ“ฆ Downloads` + `## ๐Ÿ” Verify` + `## ๐Ÿ›ก๏ธ Supply chain` + # to whatever release-please generated (CHANGELOG content). + # Idempotent via awk-based strip of any previous Downloads + # section onwards before appending โ€” re-running this job + # overwrites the trailing sections in place without duplicating. + # The Supply chain section (BEE-1781) cites the cosign / SBOM / + # SLSA artifacts that ship with each binary + cross-refs + # `docs/supply-chain.md` for the full verify recipe. env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -318,6 +455,28 @@ jobs: printf 'shasum -a 256 -c SHA256SUMS # macOS / BSD\n' printf 'sha256sum -c SHA256SUMS # Linux\n' printf '```\n' + printf '\n## ๐Ÿ›ก๏ธ Supply chain (BEE-1781)\n\n' + printf 'Each binary ships with:\n\n' + printf -- '- **`.sig` + `.pem`** โ€” cosign keyless signature + Sigstore Fulcio cert tied to this workflow run.\n' + printf -- '- **`.cdx.json`** โ€” CycloneDX SBOM (per-artifact dep + binary metadata).\n' + printf -- '- **`beeping-cli.intoto.jsonl`** โ€” SLSA L3 build provenance attestation (covers ALL artifacts in this release).\n\n' + printf 'Quick verify (replace `` with the file you downloaded):\n\n' + printf '```sh\n' + printf '# 1. cosign keyless verification\n' + printf 'cosign verify-blob \\\n' + printf ' --certificate .pem \\\n' + printf ' --signature .sig \\\n' + printf " --certificate-identity-regexp '^https://github.com/beeping-io/beeping-cli/.github/workflows/release.yml@.+\$' \\\\\n" + printf ' --certificate-oidc-issuer https://token.actions.githubusercontent.com \\\n' + printf ' \n\n' + printf '# 2. SLSA L3 provenance verification\n' + printf 'slsa-verifier verify-artifact \\\n' + printf ' --provenance-path beeping-cli.intoto.jsonl \\\n' + printf ' --source-uri github.com/beeping-io/beeping-cli\n\n' + printf '# 3. SBOM schema validation\n' + printf 'cyclonedx-cli validate --input-file .cdx.json\n' + printf '```\n\n' + printf 'Full recipe + install commands: [`docs/supply-chain.md`](https://github.com/%s/blob/develop/docs/supply-chain.md)\n' "$REPO" } > /tmp/release-body.md echo '--- composed body ---' diff --git a/.github/workflows/verify-supply-chain.yml b/.github/workflows/verify-supply-chain.yml new file mode 100644 index 0000000..67a51d2 --- /dev/null +++ b/.github/workflows/verify-supply-chain.yml @@ -0,0 +1,124 @@ +# ๐Ÿ›ก๏ธ Verify supply chain โ€” exercise the cosign + SLSA + SBOM verify recipe +# documented in `docs/supply-chain.md` against a published release. +# +# BEE-1781 โ€” proves end-to-end that the artifacts we ship pass the same +# verification commands a downstream consumer would run. Catches drift +# between the release.yml signing pipeline and the documented verify +# steps. Runs: +# +# - on every release published (immediate post-publish smoke) +# - manually via workflow_dispatch with a `tag` input (test arbitrary tags) +# +# This workflow is informational; failures DO NOT block the release +# itself (already published) but DO surface the drift loudly so the +# next release fixes it. + +name: ๐Ÿ›ก๏ธ Verify supply chain + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: "Release tag to verify (e.g. v0.1.0)" + type: string + required: true + +permissions: + contents: read + +jobs: + verify: + name: ๐Ÿ›ก๏ธ Verify ${{ github.event.release.tag_name || inputs.tag }} + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ›‚ Checkout + uses: actions/checkout@v5 + + - name: ๐Ÿ“ฆ Resolve tag + id: tag + run: | + TAG="${{ github.event.release.tag_name || inputs.tag }}" + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "Verifying release tag: $TAG" + + - name: ๐Ÿ”ง Install cosign + uses: sigstore/cosign-installer@v3 + with: + cosign-release: v2.4.1 + + - name: ๐Ÿ”ง Install slsa-verifier + uses: slsa-framework/slsa-verifier/actions/installer@v2.6.0 + + - name: ๐Ÿ”ง Install cyclonedx-cli + run: | + curl -sSfL -o /usr/local/bin/cyclonedx \ + https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.27.2/cyclonedx-linux-x64 + chmod +x /usr/local/bin/cyclonedx + cyclonedx --version + + - name: โฌ‡๏ธ Download all release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir -p assets + gh release download "${{ steps.tag.outputs.tag }}" \ + --repo "${{ github.repository }}" \ + --dir assets \ + --pattern '*' + ls -la assets/ + + - name: ๐Ÿ” Verify cosign signatures (per artifact) + # Each tarball/zip ships with a .sig + .pem alongside. Iterate + # and verify them all against the workflow OIDC identity that + # produced them. + run: | + cd assets + fail=0 + for art in *.tar.xz *.zip SHA256SUMS; do + [ -f "$art" ] || continue + [ -f "${art}.sig" ] || { echo "::error::missing ${art}.sig"; fail=1; continue; } + [ -f "${art}.pem" ] || { echo "::error::missing ${art}.pem"; fail=1; continue; } + echo "::group::cosign verify $art" + cosign verify-blob \ + --certificate "${art}.pem" \ + --signature "${art}.sig" \ + --certificate-identity-regexp "^https://github.com/${GITHUB_REPOSITORY}/.github/workflows/release.yml@.+$" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + "$art" + echo "::endgroup::" + done + exit $fail + + - name: ๐Ÿ›ก๏ธ Verify SLSA L3 provenance + # The provenance file covers ALL artifacts in this release in a + # single intoto.jsonl. slsa-verifier accepts a list of artifacts. + run: | + cd assets + [ -f beeping-cli.intoto.jsonl ] || { echo "::error::missing intoto.jsonl"; exit 1; } + for art in *.tar.xz *.zip; do + [ -f "$art" ] || continue + echo "::group::slsa-verifier $art" + slsa-verifier verify-artifact "$art" \ + --provenance-path beeping-cli.intoto.jsonl \ + --source-uri "github.com/${GITHUB_REPOSITORY}" + echo "::endgroup::" + done + + - name: ๐Ÿ“œ Validate CycloneDX SBOM schemas + run: | + cd assets + for sbom in *.cdx.json; do + [ -f "$sbom" ] || continue + echo "::group::cyclonedx validate $sbom" + cyclonedx validate --input-file "$sbom" --fail-on-errors + echo "::endgroup::" + done + + - name: โœ… Summary + run: | + echo "All supply-chain artifacts for ${{ steps.tag.outputs.tag }} verified:" + echo " - cosign keyless signatures" + echo " - SLSA L3 provenance" + echo " - CycloneDX SBOM schemas" diff --git a/docs/supply-chain.md b/docs/supply-chain.md new file mode 100644 index 0000000..cf0a371 --- /dev/null +++ b/docs/supply-chain.md @@ -0,0 +1,187 @@ +# ๐Ÿ›ก๏ธ Supply chain โ€” verify any `beeping-cli` release + +Every `beeping-cli` release ships with three sets of supply-chain +artifacts so downstream consumers can independently verify the +binaries they download. This document is the canonical recipe. + +> **TL;DR** โ€” once you have `cosign`, `slsa-verifier`, and +> `cyclonedx-cli` installed, three commands prove (1) Sigstore signed +> the binary from this repo's release workflow, (2) SLSA L3 provenance +> ties it to a specific GitHub Actions run, (3) the CycloneDX SBOM is +> well-formed. + +--- + +## Why each layer exists + +| Layer | What it proves | What it does NOT prove | +|---|---|---| +| ๐Ÿ”ข **`SHA256SUMS`** + `shasum -c` | Bits weren't corrupted in transit. | Anything about who built them. | +| ๐Ÿ” **cosign keyless** (`.sig` + `.pem`) | A specific GitHub Actions workflow at a specific commit signed this exact byte sequence; the signing identity is recorded immutably in the Sigstore Rekor transparency log. | Nothing about the _build process_ itself โ€” only that the workflow that ran was the signer. | +| ๐Ÿ›ก๏ธ **SLSA L3 provenance** (`.intoto.jsonl`) | The artifact was built by an isolated, hermetic GitHub Actions builder (the SLSA reusable workflow). Builder identity is non-forgeable. | Whether the build inputs (source code) themselves are trustworthy โ€” that is on you to inspect. | +| ๐Ÿ“œ **CycloneDX SBOM** (`.cdx.json`) | What components went into the binary, with their licenses + versions. | Anything cryptographic โ€” the SBOM is informational, not a trust anchor. | + +The four layers are complementary; verify all of them for production +use cases. + +--- + +## 1. Install the verifier toolchain + +### macOS + +```sh +brew install cosign +brew install slsa-verifier +brew install cyclonedx/cyclonedx/cyclonedx-cli +``` + +### Linux (Debian/Ubuntu) + +```sh +# cosign +curl -sSfL -o /usr/local/bin/cosign \ + https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64 +chmod +x /usr/local/bin/cosign + +# slsa-verifier +curl -sSfL -o /usr/local/bin/slsa-verifier \ + https://github.com/slsa-framework/slsa-verifier/releases/download/v2.6.0/slsa-verifier-linux-amd64 +chmod +x /usr/local/bin/slsa-verifier + +# cyclonedx-cli +curl -sSfL -o /usr/local/bin/cyclonedx \ + https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.27.2/cyclonedx-linux-x64 +chmod +x /usr/local/bin/cyclonedx +``` + +### Windows (PowerShell) + +```powershell +winget install sigstore.cosign +winget install slsa-framework.slsa-verifier +# cyclonedx-cli: download .exe from https://github.com/CycloneDX/cyclonedx-cli/releases +``` + +--- + +## 2. Download a release + +Pick the artifact matching your platform from + together +with its `.sig`, `.pem`, and `.cdx.json` siblings, plus the +release-wide `beeping-cli.intoto.jsonl`. + +Example (macOS Apple Silicon, replace ``): + +```sh +TAG=v0.1.0 +TARGET=aarch64-apple-darwin +ART=beeping-cli-${TARGET}.tar.xz +BASE=https://github.com/beeping-io/beeping-cli/releases/download/${TAG} + +curl -sSfLO ${BASE}/${ART} +curl -sSfLO ${BASE}/${ART}.sig +curl -sSfLO ${BASE}/${ART}.pem +curl -sSfLO ${BASE}/${ART}.cdx.json +curl -sSfLO ${BASE}/beeping-cli.intoto.jsonl +curl -sSfLO ${BASE}/SHA256SUMS +``` + +--- + +## 3. Verify + +### 3.1 SHA256 integrity (existing, unchanged) + +```sh +shasum -a 256 -c SHA256SUMS # macOS / BSD +sha256sum -c SHA256SUMS # Linux +``` + +### 3.2 cosign keyless + +```sh +cosign verify-blob \ + --certificate ${ART}.pem \ + --signature ${ART}.sig \ + --certificate-identity-regexp '^https://github.com/beeping-io/beeping-cli/.github/workflows/release.yml@.+$' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + ${ART} +``` + +A successful run prints `Verified OK`. The cert's `Subject` field +must reference `release.yml` from this repo and the `Issuer` must be +`token.actions.githubusercontent.com` (proves GitHub OIDC, not a +forged token). + +### 3.3 SLSA L3 provenance + +```sh +slsa-verifier verify-artifact ${ART} \ + --provenance-path beeping-cli.intoto.jsonl \ + --source-uri github.com/beeping-io/beeping-cli +``` + +Optional pin to an exact tag (refuses provenance from any other tag): + +```sh +slsa-verifier verify-artifact ${ART} \ + --provenance-path beeping-cli.intoto.jsonl \ + --source-uri github.com/beeping-io/beeping-cli \ + --source-tag ${TAG} +``` + +### 3.4 CycloneDX SBOM schema + +```sh +cyclonedx validate --input-file ${ART}.cdx.json --fail-on-errors +``` + +Inspect components manually: + +```sh +jq '.components[] | {name, version, licenses}' ${ART}.cdx.json +``` + +--- + +## 4. Automated verification + +`.github/workflows/verify-supply-chain.yml` runs the same recipe on +every published release in CI. If you maintain a downstream +distribution (Homebrew tap, Scoop bucket, container image), copy that +workflow into your own pipeline so a regression in our signing +pipeline surfaces in your CI rather than in users' machines. + +--- + +## 5. Trust roots reference + +| Component | Trust root | Operator | +|---|---|---| +| cosign keyless | Sigstore Fulcio CA + Rekor transparency log | Linux Foundation / OpenSSF | +| SLSA L3 builder | `slsa-framework/slsa-github-generator` reusable workflow | SLSA Framework / OpenSSF | +| GitHub OIDC issuer | `token.actions.githubusercontent.com` | GitHub | + +Compromise of any single trust root is detectable via the others +(transparency log queries, provenance subject mismatch). + +--- + +## 6. Threats this addresses + +โœ… Tampered binary served from a hijacked CDN / mirror (cosign + SLSA detect) +โœ… Forged release using a copycat repo or workflow (cosign identity check rejects) +โœ… Build-time supply chain injection by a malicious dep (SBOM aids forensics) +โœ… Insider attack rebuilding artifacts off-pipeline (SLSA provenance fails) + +## 7. Threats this does NOT address + +โŒ Source code itself being malicious โ€” review `git log` + `Cargo.lock` +โŒ Compromise of `beeping-core` upstream pre-built binary (BEE-1883 verifies its SHA256 at build time, but trust still chains to upstream) +โŒ Runtime dynamic-library substitution โ€” out of scope; OS-level concern + +--- + +**BEE-1781** โ€” implemented 2026-05-10. Maintainer: Alfred Rivas. diff --git a/external/README.md b/external/README.md index 1a705dc..3754965 100644 --- a/external/README.md +++ b/external/README.md @@ -33,11 +33,22 @@ The plan is: ## What's NOT here yet -- `cosign` signature URLs (BEE-1781) -- SBOM CycloneDX URLs (BEE-1781) -- SLSA provenance attestation (BEE-1781) - Auto-updating SHAs (BEE-1782 / BEE-1783) - Smoke tests post-release (BEE-1786) +## What's now present (BEE-1781 โ€” implemented 2026-05-11) + +- `cosign` keyless signatures (`.sig` + `.pem`) shipped alongside every + release artifact. Verification recipe in `docs/supply-chain.md`. +- CycloneDX SBOM (`.cdx.json`) per artifact. +- SLSA L3 provenance (`beeping-cli.intoto.jsonl`) covering the whole + release, generated by the `slsa-framework/slsa-github-generator` + reusable workflow. + +Homebrew + Scoop only check the SHA256 hash (their schema can't +encode cosign / SLSA today). The cosign + SLSA layer is opt-in via +`docs/supply-chain.md` and exercised by +`.github/workflows/verify-supply-chain.yml` on every release. + Until those land, every release requires a manual SHA256 update in this directory. Documented as a known limitation in `docs/installation.md`. diff --git a/external/scoop-bucket/bucket/beeping-cli.json b/external/scoop-bucket/bucket/beeping-cli.json index 16065b1..19e026c 100644 --- a/external/scoop-bucket/bucket/beeping-cli.json +++ b/external/scoop-bucket/bucket/beeping-cli.json @@ -29,5 +29,5 @@ } } }, - "_comment": "BEE-151 bootstrap. SHA256 hash is a placeholder; BEE-1783 will rewrite it on every release via scoop's autoupdate. Until then, regenerate manually post-release." + "_comment": "BEE-151 bootstrap. SHA256 hash is a placeholder; BEE-1783 will rewrite it on every release via scoop's autoupdate. Until then, regenerate manually post-release. BEE-1781: every release also ships cosign keyless signatures (.sig + .pem) and SLSA L3 provenance (beeping-cli.intoto.jsonl); see docs/supply-chain.md for opt-in verification." } diff --git a/external/tap/Formula/beeping-cli.rb b/external/tap/Formula/beeping-cli.rb index a02ebc2..d8da368 100644 --- a/external/tap/Formula/beeping-cli.rb +++ b/external/tap/Formula/beeping-cli.rb @@ -6,6 +6,12 @@ # Until BEE-1782 lands, post-release the maintainer regenerates this # file with `shasum -a 256` against each tarball + commits the result # (manual cycle; documented in `external/README.md`). +# +# Supply chain (BEE-1781): every release also ships cosign keyless +# signatures (`.sig` + `.pem`) and SLSA L3 provenance +# (`beeping-cli.intoto.jsonl`). Power users may verify before install +# per `docs/supply-chain.md` upstream. Homebrew itself only checks the +# SHA256 below; the cosign + SLSA layer is opt-in for now. class BeepingCli < Formula desc "Official Rust CLI for the Beeping Platform โ€” data over sound" homepage "https://github.com/beeping-io/beeping-cli" From 61913642876c2856b6fcdb83fc13bf5a2e016838 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Mon, 11 May 2026 13:35:04 +0200 Subject: [PATCH 02/10] docs(roadmap): BEE-1781 recompute timeline + changelog - Move BEE-1781 from Phase 15 shared scope to beeping-cli specific (+5 SP to Phase 15 specific). Same precedent as BEE-1780 on 2026-05-06: entire implementation lives in this repo's release pipeline + docs, no beepbox-side work. - Phase 15 specific now 54 SP; 49/54 done (91 %), 1 remaining (BEE-2222). - Append History entry covering: pipeline jobs added (combine-hashes, provenance), cosign + SBOM steps, verify-supply-chain.yml + docs; end-to-end verification on test tag v0.0.0-test3 across all four layers (SHA256, cosign keyless, SLSA L3, CycloneDX schema). - No timeline impact; estimated end stays 2026-05-19. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ROADMAP.md | 25 ++++++++----- docs/ROADMAP_CHANGELOG.md | 75 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index fca4b52..e7f25b7 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,11 +14,11 @@ | **Estimated end (with 20 % risk margin)** | 2026-05-15 (was 2026-05-30, advanced 15 days; scope-change absorbed into buffer) | | **Initial velocity assumed** | 5 SP / work-day (solo developer, multi-repo context) | | **Risk margin** | 20 % over raw work-day estimate | -| **Total story points scoped to this repo** | 126 SP (Phase 14: 77 ยท Phase 15: 49) | -| **Story points completed** | 121 SP (32 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888**) | +| **Total story points scoped to this repo** | 131 SP (Phase 14: 77 ยท Phase 15: 54) | +| **Story points completed** | 126 SP (33 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781**) | | **Story points remaining** | 5 SP (Phase 15: BEE-2222 โ€” 1 task) | -| **Global status** | โœ… On time โ€” Phase 15 in flight (90 % done), Phase 14 done | -| **Last update** | 2026-05-10 โ€” closed BEE-1888 (Codecov account + token + 5 follow-ups for cpal-introduced regressions, 1 SP) | +| **Global status** | โœ… On time โ€” Phase 15 in flight (91 % done), Phase 14 done | +| **Last update** | 2026-05-11 โ€” closed BEE-1781 (cosign keyless + CycloneDX SBOM + SLSA L3 provenance per artifact, 5 SP); moved from shared to `beeping-cli`-specific scope (+5 SP to Phase 15 specific) | --- @@ -27,7 +27,7 @@ | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 49 | 2026-05-04 | 2026-05-19 | โณ in flight (44/49 SP done, 90 %) | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 54 | 2026-05-04 | 2026-05-19 | โณ in flight (49/54 SP done, 91 %) | > **Note**: Phase 15 also contains 15 additional tasks (~60 SP) shared with > `beepbox-cli` (the C++ CLI). Those are not counted in this repo's SP total โ€” @@ -83,7 +83,7 @@ else; tests close out the milestone). --- -## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 49 SP) +## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 54 SP) **Goal**: Public installable binaries for `beeping-cli` on 6+ channels with signing, SBOM, and SLSA L3 provenance. Smoke tests validate every channel @@ -114,8 +114,9 @@ ecosystem level. | 9 | [BEE-1887](https://linear.app/me8/issue/BEE-1887) โ€” ๐Ÿงซ cargo-mutants full-workspace + scheduled CI | 2 | โœ… **Done** 2026-05-09 (weekly workflow + 0.85 score floor + self-validation; first run 1.00 on server_url.rs) | | 10 | [BEE-1888](https://linear.app/me8/issue/BEE-1888) โ€” ๐Ÿ“ˆ Codecov account + CODECOV_TOKEN secret | 1 | โœ… **Done** 2026-05-10 (Codecov dashboard linked, GitHub `alfredrc`; 5 cpal regressions caught + fixed) | | 11 | [BEE-1897](https://linear.app/me8/issue/BEE-1897) โ€” ๐Ÿ”ง CI matrix hardening (BEE-150 follow-up) | 5 | โœ… **Done** 2026-05-07 (3 blockers resolved; Windows runtime FFI crash spun off to BEE-2222) | -| 12 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | -| | **Total** | **49** | 44 done ยท 5 remaining | +| 12 | [BEE-1781](https://linear.app/me8/issue/BEE-1781) โ€” ๐Ÿ” cosign keyless + CycloneDX SBOM + SLSA L3 provenance | 5 | โœ… **Done** 2026-05-11 (every release ships .sig + .pem + .cdx.json + intoto.jsonl; end-to-end verified on test tag) | +| 13 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | +| | **Total** | **54** | 49 done ยท 5 remaining | ### Phase 15 shared scope (NOT counted here) @@ -124,7 +125,7 @@ C++ standalone CLI in the `beepbox` repo) or are shared distribution work that runs from `beepbox`'s side. They're not included in this repo's SP total to avoid double-counting: -BEE-1778 (ADR), BEE-1779 (CI release matrix), BEE-1781 (cosign + SBOM + SLSA), +BEE-1778 (ADR), BEE-1779 (CI release matrix), BEE-1782 (Homebrew formula auto-update), BEE-1783 (Scoop manifest auto-update), BEE-1784 (AppImage), BEE-1785 (Install docs), BEE-1786 (smoke tests), BEE-1787 (winget), BEE-1788 (Chocolatey), BEE-1789 (Homebrew core), @@ -135,6 +136,12 @@ budget), BEE-1792 (Authenticode, pending budget). > implementation lives entirely in `beeping-cli`'s `release.yml` โ€” moved to > the specific table on 2026-05-06 when it closed (+3 SP to Phase 15 specific, > recorded as a scope clarification in `ROADMAP_CHANGELOG.md`). +> +> Note: BEE-1781 (cosign + SBOM + SLSA L3) was originally listed here but its +> implementation lives entirely in `beeping-cli`'s `release.yml` + +> `verify-supply-chain.yml` + `docs/supply-chain.md` โ€” moved to the specific +> table on 2026-05-11 when it closed (+5 SP to Phase 15 specific, recorded +> as a scope clarification in `ROADMAP_CHANGELOG.md`). --- diff --git a/docs/ROADMAP_CHANGELOG.md b/docs/ROADMAP_CHANGELOG.md index b896b36..1313997 100644 --- a/docs/ROADMAP_CHANGELOG.md +++ b/docs/ROADMAP_CHANGELOG.md @@ -15,21 +15,86 @@ - **Project start**: 2026-04-28 - **Estimated end (with 20 % margin)**: 2026-05-19 (unchanged; within velocity) - **Velocity assumed**: 5 story points / work-day (actual sustained ~6 SP / work-day) -- **Total SP scoped to this repo**: 126 (Phase 14: 77 ยท Phase 15: 49) -- **SP completed**: 121 (32 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888) +- **Total SP scoped to this repo**: 131 (Phase 14: 77 ยท Phase 15: 54) +- **SP completed**: 126 (33 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781) - **SP remaining**: 5 (Phase 15: BEE-2222 = 1 task) -- **Global status**: โœ… On time โ€” Phase 15 in flight (44/49 SP done, 90 %) -- **Last update**: 2026-05-10 โ€” closed BEE-1888 (Codecov dashboard + token + 5 cpal-introduced regressions caught & fixed, 1 SP) +- **Global status**: โœ… On time โ€” Phase 15 in flight (49/54 SP done, 91 %) +- **Last update**: 2026-05-11 โ€” closed BEE-1781 (cosign keyless + CycloneDX SBOM + SLSA L3 provenance per artifact, 5 SP); moved from shared to `beeping-cli`-specific scope (+5 SP to Phase 15 specific) | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 49 | 2026-05-04 | 2026-05-19 | โณ in flight | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 54 | 2026-05-04 | 2026-05-19 | โณ in flight | --- ## ๐Ÿ“œ History +### [2026-05-11] โ€” Closed BEE-1781 (5 SP, cosign + CycloneDX SBOM + SLSA L3 provenance) + scope clarification + +**Trigger**: closure of BEE-1781, plus a "Scope clarification" entry โ€” BEE-1781 was originally listed in Phase 15's _shared scope (NOT counted here)_ because the supply-chain layer was assumed to be cross-repo. In practice the entire implementation lives in `beeping-cli`'s `release.yml` + new `verify-supply-chain.yml` + `docs/supply-chain.md`, so it moves to the `beeping-cli`-specific table (+5 SP to Phase 15 specific). Same pattern as BEE-1780's move on 2026-05-06. + +**Delivered**: + +Every release artifact now ships with a complete supply-chain attestation: + +- **cosign keyless** (`.sig` + `.pem` per archive + `SHA256SUMS`): GH Actions OIDC identity โ†’ Sigstore Fulcio short-lived cert โ†’ Rekor transparency log. `sigstore/cosign-installer@v3` (cosign v2.4.1) + a `sign-blob` loop over every artifact. `COSIGN_YES=true` env to bypass the interactive prompt. +- **CycloneDX SBOM** (`.cdx.json` per archive): `syft` install + per-artifact CycloneDX 1.6 JSON. +- **SLSA L3 build provenance** (single `beeping-cli.intoto.jsonl` covering every artifact in the release): + - New `combine-hashes` job aggregates per-target SHA256 lines into a single newline-separated blob, base64-encoded โ†’ the `base64-subjects` format expected by `slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0`. + - New `provenance` job consumes the blob via the reusable workflow with `permissions: id-token: write, contents: write, actions: read`. `upload-assets: true` uploads the `.intoto.jsonl` to the release directly. +- Release body composition gains a `## ๐Ÿ›ก๏ธ Supply chain (BEE-1781)` section with the 3-command verify recipe (cosign + slsa-verifier + cyclonedx-cli) and a cross-link to `docs/supply-chain.md`. + +New supporting files: + +- `.github/workflows/verify-supply-chain.yml` โ€” runs on every published release + manual dispatch. Downloads every asset, exercises the full 3-layer verification recipe end-to-end against the published release. Catches drift between signing pipeline and documented verify steps. +- `docs/supply-chain.md` โ€” canonical install + verify recipe per OS (macOS / Linux / Windows), trust-root reference table, threat model section. Distinguishes what each layer proves vs does not prove. + +External scaffolding comments updated (Tap formula + Scoop manifest + `external/README.md`) to mention cosign + SLSA opt-in verification alongside the existing SHA256 check. + +**Tests**: + +- `actionlint` clean (only pre-existing SC2193 warnings from BEE-150's matrix include-list logic remain; nothing introduced by BEE-1781). +- `ruby -c` + `python3 -m json.tool` + `markdownlint` all pass. +- End-to-end verified on test tag `v0.0.0-test3`: pipeline produced 23 assets across 5 platforms ร— (binary + .sig + .pem + .cdx.json) + SHA256SUMS triplet + 1 SLSA `.intoto.jsonl`. Downloaded `aarch64-apple-darwin` triplet locally: + +| Verification | Result | +|---|---| +| ๐Ÿ”ข `shasum -a 256 -c SHA256SUMS` | โœ… `Verified OK` | +| ๐Ÿ” `cosign verify-blob` | โœ… `Verified OK` (cert identity = `release.yml@refs/tags/v0.0.0-test3`, issuer = `token.actions.githubusercontent.com`) | +| ๐Ÿ›ก๏ธ `slsa-verifier verify-artifact` | โœ… `PASSED` โ€” Rekor log entry 1502790677, builder pinned to `slsa-github-generator@v2.0.0`, commit `4bed04a` | +| ๐Ÿ“œ CycloneDX schema | โœ… `bomFormat=CycloneDX specVersion=1.6` (syft 1.44.0) | + +Test tag + release deleted after QA. Founder approval "Dale" 2026-05-11 07:08 local. + +Run conclusion was marked `failure` overall only because of the pre-existing Windows test-step issue (BEE-1897 โ†’ BEE-2222 follow-up). All BEE-1781-specific jobs (combine-hashes, SLSA L3 detect-env/generator/upload-assets/final, Release publish) are green. The Windows ZIP is still present in the release thanks to the partial-matrix mechanism inherited from BEE-1780. + +**Net delta global**: 0 days. The 5 SP fits within current sustained velocity; the implementation was a single closure session because the existing BEE-1780 partial-matrix release infrastructure was reused. + +**New estimated end date**: 2026-05-19 (no change). + +**New global status**: โœ… On time, Phase 15 at 91 % (49/54 SP). + +#### Advanced (negative = earlier) + +- (none โ€” within velocity) + +#### Delayed + +- (none) + +#### Scope changes + +- **Scope clarification**: BEE-1781 (5 SP) moves from Phase 15 shared scope to `beeping-cli`-specific scope. Reason: full implementation lives in this repo's release pipeline + docs; no `beepbox`-side work needed. Same precedent as BEE-1780 on 2026-05-06. + +#### Notes + +- Cumulative SP closed: 126 / 131 = 96 % of total scope, 91 % of Phase 15. +- The `verify-supply-chain.yml` workflow is the long-tail value: it runs on every future release publish and exercises the same recipe a downstream consumer would, so if cosign upgrades break the `--certificate-identity-regexp` flag or if the SLSA reusable workflow changes its `base64-subjects` format, we discover the drift in CI before users do. +- Phase 15 specific scope: 12 tasks done (BEE-150, BEE-152, BEE-151, BEE-1780, BEE-1883, BEE-1884, BEE-1885, BEE-1886, BEE-1887, BEE-1888, BEE-1897, BEE-1781) ยท 1 remaining (BEE-2222). + +--- + ### [2026-05-10] โ€” Closed BEE-1888 (1 SP, Codecov dashboard + 5 cpal-induced regression fixes) **Trigger**: closure of BEE-1888 (originally `pending-007` in `docs/PENDING.md`, promoted at Phase 14 close). From 713f9822f646839e6f3abed45c225be8a66bf151 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Mon, 11 May 2026 17:44:20 +0200 Subject: [PATCH 03/10] docs(install): BEE-1785 polish install docs + add README install section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrite docs/installation.md: quick install table, supply-chain verify section (cross-link to docs/supply-chain.md), per-OS sections (macOS / Linux / Windows) with manual tarball recipes + Gatekeeper / SmartScreen workarounds (deferred BEE-1791 / BEE-1792), ALSA runtime prereq for Linux, BEE-2222 Windows runtime caveat, channel status matrix, troubleshooting table. - README.md: add a prominent ๐Ÿ“ฅ Install section right after the intro with 4 one-liners + cross-link to installation.md + supply-chain.md. - README.md: remove duplicate install commands from the "Target CLI" section now that they live in the Install section. - README.md: refresh "Distribution channels" table to reflect the channels that landed (BEE-150 / 151 / 152 / 1780 / 1781) and the ones still queued. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 62 +++++++--- docs/installation.md | 267 +++++++++++++++++++++++++++++++++---------- 2 files changed, 249 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 4c280ce..50708f8 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,38 @@ --- +## ๐Ÿ“ฅ Install + +```sh +# macOS / Linux โ€” Homebrew tap +brew install beeping-io/tap/beeping-cli + +# Windows โ€” Scoop bucket +scoop bucket add beeping https://github.com/beeping-io/scoop-bucket +scoop install beeping-cli + +# Any platform with Rust โ‰ฅ 1.88 +cargo install beeping-cli + +# Or grab a signed binary directly: +# https://github.com/beeping-io/beeping-cli/releases/latest +``` + +Every release ships with **SHA256 checksums**, **cosign keyless +signatures**, **CycloneDX SBOM**, and **SLSA L3 build provenance**. +Verify before running anything for production: + +```sh +shasum -a 256 -c SHA256SUMS # minimum integrity check +``` + +Full per-platform installer (incl. man page + completions), +verification recipe, and troubleshooting (macOS Gatekeeper, Windows +SmartScreen, ALSA on Linux): see [`docs/installation.md`](docs/installation.md) +and [`docs/supply-chain.md`](docs/supply-chain.md). + +--- + ## ๐Ÿšง Status **Early development โ€” repository bootstrapped on 2026-04-28.** @@ -35,17 +67,6 @@ implemented** โ€” track Phase 14 and Phase 15 progress for availability. ## ๐ŸŽฏ Target CLI (post-Phase 14) -```sh -# Install (channels wired in BEE-151; activate with the first v0.0.x tag) -brew install beeping-io/tap/beeping-cli # macOS / Linux Homebrew tap -scoop bucket add beeping https://github.com/beeping-io/scoop-bucket -scoop install beeping-cli # Windows Scoop bucket -cargo install beeping-cli # any platform with Rust โ‰ฅ 1.88 -``` - -See [`docs/installation.md`](docs/installation.md) for full per-platform -details + manual install + man page + shell completions setup. - ```sh # Local mode (no network) beeping init # create ~/.config/beeping/config.toml @@ -141,20 +162,23 @@ macOS arm64+x86_64 ยท Linux amd64+arm64 ยท Windows x86_64. | Channel | Install command | Status | |---|---|---| -| Homebrew tap | `brew install beeping-io/tap/beeping-cli` | ๐ŸŸก BEE-151 bootstrap (manual SHA256 until BEE-1782) | -| Scoop bucket | `scoop install beeping-cli` (after `bucket add`) | ๐ŸŸก BEE-151 bootstrap (manual SHA256 until BEE-1783) | -| `cargo` | `cargo install beeping-cli` | ๐ŸŸก BEE-151 publish wired; activates with first tag | -| GitHub Releases | direct binary + man + completions tarball | โœ… BEE-150 (5-target matrix) + BEE-152 (man + completions bundled) | +| Homebrew tap | `brew install beeping-io/tap/beeping-cli` | ๐ŸŸข live (manual SHA256 until BEE-1782 auto-updates per release) | +| Scoop bucket | `scoop install beeping-cli` (after `bucket add`) | ๐ŸŸข live (manual SHA256 until BEE-1783 auto-updates per release) | +| `cargo` | `cargo install beeping-cli` | ๐ŸŸข live (publishes per release via crates.io) | +| GitHub Releases | direct binary + man + completions tarball | ๐ŸŸข live (BEE-150 5-target matrix + BEE-152 man/completions + BEE-1780 SHA256SUMS + BEE-1781 cosign + SBOM + SLSA L3) | | Homebrew core | `brew install beeping-cli` (after upstream review) | ๐Ÿ“‹ BEE-1789 | | AppImage | download from GitHub Releases + `chmod +x` | ๐Ÿ“‹ BEE-1784 | | winget | `winget install beeping-cli` | ๐Ÿ“‹ BEE-1787 | | Chocolatey | `choco install beeping-cli` | ๐Ÿ“‹ BEE-1788 | | Linux .deb / .rpm | `apt install beeping-cli` / `dnf install beeping-cli` | ๐Ÿ“‹ BEE-1790 (Cloudsmith) | -All artifacts will ship with **cosign keyless** signature, **CycloneDX SBOM**, -and **SLSA L3 provenance**. macOS notarization and Authenticode signing are -pending budget approval (BEE-1791 / BEE-1792); until then, releases are -unsigned with a documented disclaimer. +All released artifacts ship with **cosign keyless** signature, +**CycloneDX SBOM**, and **SLSA L3 build provenance** since BEE-1781 โ€” +see [`docs/supply-chain.md`](docs/supply-chain.md) for the verification +recipe. macOS notarization (Developer ID) and Windows Authenticode +signing are pending budget approval (BEE-1791 / BEE-1792); until they +land, manual installs hit Gatekeeper / SmartScreen warnings that are +documented in [`docs/installation.md`](docs/installation.md). --- diff --git a/docs/installation.md b/docs/installation.md index e034a71..f59fec4 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,16 +1,18 @@ # ๐Ÿ“ฅ Install โ€” `beeping` -> ๐Ÿšง **Phase 15 work in progress** (BEE-1785 polishes this). BEE-151 has -> landed the channel bootstrap: `cargo install`, Homebrew tap, Scoop -> bucket, and direct GitHub Releases tarballs. Channels activate once -> the first `v0.0.x` tag is published. Expect copy + per-platform polish -> to grow as BEE-1785, BEE-1781 (cosign + SBOM), BEE-1782 (tap -> auto-update), BEE-1783 (bucket auto-update), and BEE-1786 (post-release -> smoke matrix) close. +> One-liners per platform ยท supply-chain verification recipe ยท +> troubleshooting. + +The CLI ships on 4 channels today (Homebrew tap, Scoop bucket, `cargo +install`, GitHub Releases tarball) and 5 more are queued (Homebrew core, +winget, Chocolatey, AppImage, `.deb`/`.rpm`). Every published release +ships with **SHA256 checksums**, **cosign keyless signatures**, +**CycloneDX SBOM**, and **SLSA L3 build provenance** so you can verify +authenticity before running anything (BEE-1781). --- -## โšก Quick install (post-first-tag) +## โšก Quick install | Platform | Channel | Command | |---|---|---| @@ -19,24 +21,72 @@ | any | crates.io (Rust โ‰ฅ 1.88) | `cargo install beeping-cli` | | any | direct binary | download from | -**Until BEE-1782 / BEE-1783 land**, the Homebrew formula and Scoop -manifest carry **placeholder SHA256 hashes**. The maintainer regenerates -them post-release manually (one-line `shasum` + commit). If you hit a -"resource hash mismatch" error, file an issue and we'll regenerate. +> โš ๏ธ **Until BEE-1782 / BEE-1783 land**, the Homebrew formula and Scoop +> manifest carry **placeholder SHA256 hashes** that the maintainer +> regenerates manually post-release. If you hit a _resource hash +> mismatch_ error, file an issue and we'll regenerate. Real +> integrity verification still works via `SHA256SUMS` (see ยง ๐Ÿ›ก๏ธ Verify). + +--- + +## ๐Ÿ›ก๏ธ Verify a downloaded artifact + +Every release at +ships with three sets of supply-chain artifacts: + +| Layer | Artifact | What it proves | +|---|---|---| +| ๐Ÿ”ข Integrity | `SHA256SUMS` + `.sig` + `.pem` | The bytes you downloaded match the bytes the workflow produced | +| ๐Ÿ” Authenticity | `.sig` + `.pem` (cosign keyless) | The Beeping CI workflow at a specific commit signed this binary | +| ๐Ÿ›ก๏ธ Provenance | `beeping-cli.intoto.jsonl` (SLSA L3) | An isolated GitHub Actions builder produced this artifact from the published source | +| ๐Ÿ“œ Inventory | `.cdx.json` (CycloneDX SBOM) | Component + license metadata | + +### Minimum (recommended) + +```sh +shasum -a 256 -c SHA256SUMS # macOS / BSD +sha256sum -c SHA256SUMS # Linux +``` + +### Strong (production deployments) + +```sh +# Install verifier toolchain +brew install cosign slsa-verifier + +# 1. cosign keyless +cosign verify-blob \ + --certificate .pem \ + --signature .sig \ + --certificate-identity-regexp '^https://github.com/beeping-io/beeping-cli/.github/workflows/release.yml@.+$' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + + +# 2. SLSA L3 provenance +slsa-verifier verify-artifact \ + --provenance-path beeping-cli.intoto.jsonl \ + --source-uri github.com/beeping-io/beeping-cli +``` + +Full per-OS installer for `cosign` / `slsa-verifier` / `cyclonedx-cli`, +threat model, and trust-root reference: [`docs/supply-chain.md`](supply-chain.md). --- -## ๐Ÿ“œ Man page + shell completions (BEE-152) +## ๐Ÿ“œ Man page + shell completions Every release artifact bundles the man page (`man/beeping.1`) and four shell completions (`completions/beeping.bash`, `completions/_beeping`, `completions/beeping.fish`, `completions/_beeping.ps1`) generated from the same `clap` derive that produces `beeping --help`, so they always -match the binary. +match the binary (BEE-152). + +When installed via Homebrew tap or Scoop bucket, these go to the +standard locations automatically. From a manual tarball, copy them +yourself โ€” examples per platform below. -You can also generate them locally from any installed `beeping` binary -via the hidden `__generate-*` subcommands โ€” useful when packaging from -source: +You can also regenerate them locally from any installed `beeping` +binary via the hidden `__generate-*` subcommands: ```sh beeping __generate-man-page --out-dir /usr/local/share/man/man1/ @@ -45,75 +95,170 @@ beeping __generate-completions --shell zsh --out-dir /usr/local/share/zsh/site- beeping __generate-completions --shell fish --out-dir ~/.config/fish/completions/ ``` -### macOS (Homebrew tap, post-BEE-151) +--- + +## ๐ŸŽ macOS -When the Homebrew tap is wired (BEE-151) the formula will install all -of the above to the standard locations automatically. Until then, -extract the release artifact and copy the files manually: +### Recommended โ€” Homebrew tap ```sh -tar -xJf beeping-cli-aarch64-apple-darwin.tar.xz -cd beeping-cli-aarch64-apple-darwin -sudo cp beeping /usr/local/bin/ -sudo cp man/beeping.1 /usr/local/share/man/man1/ -cp completions/_beeping /usr/local/share/zsh/site-functions/ # zsh -cp completions/beeping.bash /usr/local/etc/bash_completion.d/ # bash (via brew install bash-completion) +brew install beeping-io/tap/beeping-cli +beeping --version +man beeping ``` -Verify: +The tap formula handles binary placement (`/usr/local/bin/beeping` on +Intel, `/opt/homebrew/bin/beeping` on Apple Silicon), man page, and zsh +/ bash / fish completions. + +### Manual tarball ```sh -beeping --version -man beeping -beeping # zsh / bash should now complete subcommands +# Pick the matching arch +TARGET=aarch64-apple-darwin # M1 / M2 / M3 +# TARGET=x86_64-apple-darwin # Intel +curl -sSfLO https://github.com/beeping-io/beeping-cli/releases/latest/download/beeping-cli-${TARGET}.tar.xz +tar -xJf beeping-cli-${TARGET}.tar.xz +sudo install -m 0755 beeping-cli-${TARGET}/beeping /usr/local/bin/ +sudo install -m 0644 beeping-cli-${TARGET}/man/beeping.1 /usr/local/share/man/man1/ +install -m 0644 beeping-cli-${TARGET}/completions/_beeping /usr/local/share/zsh/site-functions/ ``` -### Linux (.deb / .rpm / AppImage, post-BEE-151) +### macOS Gatekeeper workaround + +Until BEE-1791 (Apple Developer ID notarization) closes, binaries +downloaded from GitHub Releases are flagged as _unidentified developer_ +by Gatekeeper. Two options: + +1. **One-off**: right-click the extracted `beeping` binary in Finder โ†’ + _Open_ โ†’ _Open_ again to add a permanent allowlist exception. +2. **CLI**: `xattr -d com.apple.quarantine /usr/local/bin/beeping` + +The Homebrew tap install path does not hit this because Homebrew +strips the quarantine attribute itself. Once BEE-1791 lands, this +workaround becomes unnecessary. + +--- + +## ๐Ÿง Linux + +### Recommended โ€” Homebrew on Linux + +Homebrew works on Linux (`brew install beeping-io/tap/beeping-cli`). +For distro-native packaging, wait for BEE-1790 (`.deb` / `.rpm`) and +BEE-1784 (AppImage). + +### Manual tarball ```sh -# Same pattern as macOS, with package-manager-managed paths once -# BEE-151 + BEE-1790 land. For now, the tarball ships the same -# layout as the macOS release artifact. -tar -xJf beeping-cli-x86_64-unknown-linux-gnu.tar.xz -sudo install -m 0755 beeping-cli-*/beeping /usr/local/bin/ -sudo install -m 0644 beeping-cli-*/man/beeping.1 /usr/local/share/man/man1/ -install -m 0644 beeping-cli-*/completions/beeping.bash ~/.local/share/bash-completion/completions/beeping -install -m 0644 beeping-cli-*/completions/_beeping ~/.zfunc/_beeping -install -m 0644 beeping-cli-*/completions/beeping.fish ~/.config/fish/completions/beeping.fish +# Pick arch +TARGET=x86_64-unknown-linux-gnu # most x86_64 servers + desktops +# TARGET=aarch64-unknown-linux-gnu # Raspberry Pi 4+ / Apple Silicon Linux VMs +curl -sSfLO https://github.com/beeping-io/beeping-cli/releases/latest/download/beeping-cli-${TARGET}.tar.xz +tar -xJf beeping-cli-${TARGET}.tar.xz +sudo install -m 0755 beeping-cli-${TARGET}/beeping /usr/local/bin/ +sudo install -m 0644 beeping-cli-${TARGET}/man/beeping.1 /usr/local/share/man/man1/ +install -m 0644 beeping-cli-${TARGET}/completions/beeping.bash ~/.local/share/bash-completion/completions/beeping +install -m 0644 beeping-cli-${TARGET}/completions/beeping.fish ~/.config/fish/completions/beeping.fish ``` -For `_beeping` placed in `~/.zfunc/`, ensure `fpath+=~/.zfunc` is in -your `.zshrc` before `compinit`. +For zsh completions placed in `~/.zfunc/`, ensure `fpath+=~/.zfunc` +is in your `.zshrc` before `compinit`. + +### Audio capture prerequisite -### Windows (Scoop bucket, post-BEE-151) +`beeping decode --listen` and `beeping encode` (no `--out`) use ALSA +via `cpal`. Install the runtime library: -Once the Scoop bucket is wired: +```sh +sudo apt install libasound2 # Debian / Ubuntu +sudo dnf install alsa-lib # Fedora / RHEL / CentOS +``` + +(Headless servers without audio hardware still work for file-based +encode/decode โ€” pass `--out FILE` / `--file FILE` to skip live audio.) + +--- + +## ๐ŸชŸ Windows + +### Recommended โ€” Scoop bucket ```powershell scoop bucket add beeping https://github.com/beeping-io/scoop-bucket -scoop install beeping +scoop install beeping-cli +beeping --version ``` -Until then, download the `.zip` artifact and extract โ€” the binary + -`completions/_beeping.ps1` are inside. Source the completions in your -PowerShell profile: +### Manual zip ```powershell -. "C:\path\to\beeping-cli-x86_64-pc-windows-msvc\completions\_beeping.ps1" +$url = "https://github.com/beeping-io/beeping-cli/releases/latest/download/beeping-cli-x86_64-pc-windows-msvc.zip" +Invoke-WebRequest -Uri $url -OutFile beeping-cli.zip +Expand-Archive -Path beeping-cli.zip -DestinationPath . +Move-Item .\beeping-cli-x86_64-pc-windows-msvc\beeping.exe $env:USERPROFILE\bin\ +. ".\beeping-cli-x86_64-pc-windows-msvc\completions\_beeping.ps1" ``` +Add a line to your PowerShell `$PROFILE` to source the completions +script on shell startup. + +### Windows SmartScreen workaround + +Until BEE-1792 (Authenticode code-signing) closes, `beeping.exe` is +unsigned. On first run SmartScreen will warn _Windows protected your +PC_. Click _More info_ โ†’ _Run anyway_ to whitelist the binary. + +Scoop bucket installs bypass this because they install to a +Scoop-managed path, which inherits Scoop's reputation. Once BEE-1792 +lands, this workaround becomes unnecessary. + +### โš ๏ธ Known issue: FFI runtime crash + +`beeping decode --file ` is currently affected by a Windows-only +FFI runtime crash (`STATUS_ACCESS_VIOLATION 0xC0000005`) tracked as +BEE-2222. The build itself is healthy; only the runtime decode path is +affected. Workaround: until BEE-2222 closes, run `beeping decode` +under WSL2 (Ubuntu) where the binary is fully functional. + +--- + +## ๐Ÿ“ฆ Channel status + +| Channel | Status | Tracker | +|---|---|---| +| Homebrew tap (`beeping-io/tap`) | ๐ŸŸข live | BEE-151 โœ… ยท BEE-1782 (auto-update) ๐Ÿ“‹ | +| Scoop bucket (`beeping-io/scoop-bucket`) | ๐ŸŸข live | BEE-151 โœ… ยท BEE-1783 (auto-update) ๐Ÿ“‹ | +| `cargo install` (crates.io) | ๐ŸŸข live | BEE-151 โœ… | +| GitHub Releases | ๐ŸŸข live | BEE-150 + BEE-152 + BEE-1780 + BEE-1781 โœ… | +| Homebrew core (`brew install beeping-cli`) | ๐Ÿ“‹ queued | BEE-1789 (~2-4 week external review after submit) | +| AppImage | ๐Ÿ“‹ queued | BEE-1784 | +| winget | ๐Ÿ“‹ queued | BEE-1787 | +| Chocolatey | ๐Ÿ“‹ queued | BEE-1788 | +| `.deb` / `.rpm` (Cloudsmith) | ๐Ÿ“‹ queued | BEE-1790 | +| macOS notarization (Developer ID) | ๐Ÿ“‹ budget-blocked | BEE-1791 | +| Windows Authenticode | ๐Ÿ“‹ budget-blocked | BEE-1792 | + --- -## ๐Ÿšง Coming in Phase 15 follow-ups +## ๐Ÿค” Troubleshooting + +| Symptom | Cause | Fix | +|---|---|---| +| `beeping: command not found` after manual install | Binary not on `$PATH` | Check `echo $PATH` includes `/usr/local/bin` (macOS/Linux) or `$env:USERPROFILE\bin` (Windows) | +| `cannot be opened because the developer cannot be verified` (macOS) | Gatekeeper quarantine | See ยง macOS Gatekeeper workaround | +| `Windows protected your PC` (Windows) | SmartScreen unsigned-binary check | See ยง Windows SmartScreen workaround | +| `error while loading shared libraries: libasound.so.2` (Linux) | ALSA runtime missing | `sudo apt install libasound2` or `sudo dnf install alsa-lib` | +| `resource hash mismatch` (Homebrew/Scoop) | Placeholder SHA256 not yet refreshed for this release | File an issue; will be auto-fixed by BEE-1782/BEE-1783 | +| `STATUS_ACCESS_VIOLATION 0xC0000005` (Windows) | BEE-2222 FFI runtime crash | Run under WSL2 until BEE-2222 closes | +| `cargo install beeping-cli` fails to compile | Rust toolchain < 1.88 | `rustup update stable` | + +--- -- BEE-1782 โ€” Homebrew tap **auto-update** (post-release SHA256 sync) -- BEE-1783 โ€” Scoop bucket **auto-update** (post-release SHA256 sync) -- BEE-1781 โ€” cosign keyless signature + CycloneDX SBOM + SLSA L3 provenance per artifact -- BEE-1786 โ€” post-release smoke matrix (real `brew install` / `scoop install` / `cargo install` on clean runners) -- BEE-1785 โ€” full polish of this page + README install section -- BEE-1790 โ€” `.deb` / `.rpm` packages on Cloudsmith -- BEE-1789 โ€” Homebrew core (PR queued, ~2-4 week external review) -- BEE-1787 โ€” winget submission -- BEE-1788 โ€” Chocolatey submission +## ๐Ÿ”— Related -Track Phase 15 progress in `docs/ROADMAP.md`. +- [`docs/supply-chain.md`](supply-chain.md) โ€” full cosign + SLSA + SBOM verify recipe + threat model +- [`docs/dual-mode.md`](dual-mode.md) โ€” offline (FFI) vs online (cloud) modes +- [`docs/PRODUCTO.md`](PRODUCTO.md) โ€” full product spec +- [`docs/ROADMAP.md`](ROADMAP.md) โ€” live timeline of Phase 15 distribution work +- [GitHub Releases](https://github.com/beeping-io/beeping-cli/releases) โ€” every tagged binary + checksums + supply-chain artifacts From 30a68bc56e8068b32c057cca93aa9b730c878b46 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Mon, 11 May 2026 17:48:02 +0200 Subject: [PATCH 04/10] docs(roadmap): BEE-1785 recompute timeline + changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move BEE-1785 from Phase 15 shared scope to beeping-cli specific (+2 SP to Phase 15 specific). Third closure of this shape this milestone (BEE-1780 + BEE-1781 + BEE-1785) โ€” pattern is now well-established. - Phase 15 specific now 56 SP; 51/56 done (91 %), 1 remaining (BEE-2222). - Append History entry covering install.md rewrite + README Install section + per-OS workarounds (Gatekeeper / SmartScreen / ALSA / BEE-2222 caveat) + lychee 32 OK link check. - No timeline impact; estimated end stays 2026-05-19. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ROADMAP.md | 23 ++++++++++------ docs/ROADMAP_CHANGELOG.md | 56 +++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index e7f25b7..0bf2104 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,11 +14,11 @@ | **Estimated end (with 20 % risk margin)** | 2026-05-15 (was 2026-05-30, advanced 15 days; scope-change absorbed into buffer) | | **Initial velocity assumed** | 5 SP / work-day (solo developer, multi-repo context) | | **Risk margin** | 20 % over raw work-day estimate | -| **Total story points scoped to this repo** | 131 SP (Phase 14: 77 ยท Phase 15: 54) | -| **Story points completed** | 126 SP (33 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781**) | +| **Total story points scoped to this repo** | 133 SP (Phase 14: 77 ยท Phase 15: 56) | +| **Story points completed** | 128 SP (34 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785**) | | **Story points remaining** | 5 SP (Phase 15: BEE-2222 โ€” 1 task) | | **Global status** | โœ… On time โ€” Phase 15 in flight (91 % done), Phase 14 done | -| **Last update** | 2026-05-11 โ€” closed BEE-1781 (cosign keyless + CycloneDX SBOM + SLSA L3 provenance per artifact, 5 SP); moved from shared to `beeping-cli`-specific scope (+5 SP to Phase 15 specific) | +| **Last update** | 2026-05-11 โ€” closed BEE-1785 (install docs polish + README install section, 2 SP); moved from shared to `beeping-cli`-specific scope (+2 SP to Phase 15 specific) | --- @@ -27,7 +27,7 @@ | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 54 | 2026-05-04 | 2026-05-19 | โณ in flight (49/54 SP done, 91 %) | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 56 | 2026-05-04 | 2026-05-19 | โณ in flight (51/56 SP done, 91 %) | > **Note**: Phase 15 also contains 15 additional tasks (~60 SP) shared with > `beepbox-cli` (the C++ CLI). Those are not counted in this repo's SP total โ€” @@ -83,7 +83,7 @@ else; tests close out the milestone). --- -## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 54 SP) +## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 56 SP) **Goal**: Public installable binaries for `beeping-cli` on 6+ channels with signing, SBOM, and SLSA L3 provenance. Smoke tests validate every channel @@ -115,8 +115,9 @@ ecosystem level. | 10 | [BEE-1888](https://linear.app/me8/issue/BEE-1888) โ€” ๐Ÿ“ˆ Codecov account + CODECOV_TOKEN secret | 1 | โœ… **Done** 2026-05-10 (Codecov dashboard linked, GitHub `alfredrc`; 5 cpal regressions caught + fixed) | | 11 | [BEE-1897](https://linear.app/me8/issue/BEE-1897) โ€” ๐Ÿ”ง CI matrix hardening (BEE-150 follow-up) | 5 | โœ… **Done** 2026-05-07 (3 blockers resolved; Windows runtime FFI crash spun off to BEE-2222) | | 12 | [BEE-1781](https://linear.app/me8/issue/BEE-1781) โ€” ๐Ÿ” cosign keyless + CycloneDX SBOM + SLSA L3 provenance | 5 | โœ… **Done** 2026-05-11 (every release ships .sig + .pem + .cdx.json + intoto.jsonl; end-to-end verified on test tag) | -| 13 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | -| | **Total** | **54** | 49 done ยท 5 remaining | +| 13 | [BEE-1785](https://linear.app/me8/issue/BEE-1785) โ€” ๐Ÿ“š Install section in README + `docs/installation.md` polish | 2 | โœ… **Done** 2026-05-11 (per-OS one-liners + supply-chain verify recipe + Gatekeeper/SmartScreen workarounds + BEE-2222 caveat + troubleshooting matrix) | +| 14 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | +| | **Total** | **56** | 51 done ยท 5 remaining | ### Phase 15 shared scope (NOT counted here) @@ -127,7 +128,7 @@ to avoid double-counting: BEE-1778 (ADR), BEE-1779 (CI release matrix), BEE-1782 (Homebrew formula auto-update), BEE-1783 (Scoop manifest auto-update), -BEE-1784 (AppImage), BEE-1785 (Install docs), BEE-1786 (smoke tests), +BEE-1784 (AppImage), BEE-1786 (smoke tests), BEE-1787 (winget), BEE-1788 (Chocolatey), BEE-1789 (Homebrew core), BEE-1790 (.deb + .rpm Cloudsmith), BEE-1791 (Apple Developer ID, pending budget), BEE-1792 (Authenticode, pending budget). @@ -142,6 +143,12 @@ budget), BEE-1792 (Authenticode, pending budget). > `verify-supply-chain.yml` + `docs/supply-chain.md` โ€” moved to the specific > table on 2026-05-11 when it closed (+5 SP to Phase 15 specific, recorded > as a scope clarification in `ROADMAP_CHANGELOG.md`). +> +> Note: BEE-1785 (Install docs) was originally listed here but its +> implementation lives entirely in `beeping-cli`'s `docs/installation.md` + +> `README.md` install section โ€” moved to the specific table on 2026-05-11 +> when it closed (+2 SP to Phase 15 specific, recorded as a scope +> clarification in `ROADMAP_CHANGELOG.md`). --- diff --git a/docs/ROADMAP_CHANGELOG.md b/docs/ROADMAP_CHANGELOG.md index 1313997..41c608d 100644 --- a/docs/ROADMAP_CHANGELOG.md +++ b/docs/ROADMAP_CHANGELOG.md @@ -15,21 +15,67 @@ - **Project start**: 2026-04-28 - **Estimated end (with 20 % margin)**: 2026-05-19 (unchanged; within velocity) - **Velocity assumed**: 5 story points / work-day (actual sustained ~6 SP / work-day) -- **Total SP scoped to this repo**: 131 (Phase 14: 77 ยท Phase 15: 54) -- **SP completed**: 126 (33 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781) +- **Total SP scoped to this repo**: 133 (Phase 14: 77 ยท Phase 15: 56) +- **SP completed**: 128 (34 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785) - **SP remaining**: 5 (Phase 15: BEE-2222 = 1 task) -- **Global status**: โœ… On time โ€” Phase 15 in flight (49/54 SP done, 91 %) -- **Last update**: 2026-05-11 โ€” closed BEE-1781 (cosign keyless + CycloneDX SBOM + SLSA L3 provenance per artifact, 5 SP); moved from shared to `beeping-cli`-specific scope (+5 SP to Phase 15 specific) +- **Global status**: โœ… On time โ€” Phase 15 in flight (51/56 SP done, 91 %) +- **Last update**: 2026-05-11 โ€” closed BEE-1785 (install docs polish + README install section, 2 SP); moved from shared to `beeping-cli`-specific scope (+2 SP to Phase 15 specific) | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 54 | 2026-05-04 | 2026-05-19 | โณ in flight | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 56 | 2026-05-04 | 2026-05-19 | โณ in flight | --- ## ๐Ÿ“œ History +### [2026-05-11] โ€” Closed BEE-1785 (2 SP, install docs polish + README install section) + scope clarification + +**Trigger**: closure of BEE-1785 plus a third "Scope clarification" entry of the same shape as BEE-1780 (2026-05-06) and BEE-1781 (this morning). BEE-1785 was originally in Phase 15's _shared scope (NOT counted here)_ on the assumption that install docs would be split across `beepbox-cli` and `beeping-cli`. In practice the entire deliverable lives in `beeping-cli`'s `docs/installation.md` + `README.md`, so it moves to the `beeping-cli`-specific table (+2 SP to Phase 15 specific). + +**Delivered**: + +- **`docs/installation.md`** rewritten from the BEE-151 bootstrap stub to a canonical install reference: Quick install table (4 one-liners), ๐Ÿ›ก๏ธ Verify section (cross-link to `docs/supply-chain.md` with minimum + strong recipes), man page + completions section, per-OS sections (๐ŸŽ macOS / ๐Ÿง Linux / ๐ŸชŸ Windows) each covering recommended channel + manual tarball recipes + platform-specific workarounds, Channel status matrix (9 channels with ๐ŸŸข / ๐Ÿ“‹ / pending-budget state), ๐Ÿค” Troubleshooting table (7 symptom/cause/fix rows), ๐Ÿ”— Related cross-links. +- **`README.md`** gains a prominent `## ๐Ÿ“ฅ Install` section right after the intro paragraph (above the Status block) with the 4 one-liners + a verify reminder + cross-links to `docs/installation.md` and `docs/supply-chain.md`. The pre-existing duplicate install snippet in `## ๐ŸŽฏ Target CLI` was removed (single source of truth). The `## ๐Ÿ“ฆ Distribution channels` table refreshed to reflect ๐ŸŸข live channels (BEE-150 / 151 / 152 / 1780 / 1781) and the supply-chain trailing paragraph rewritten to declare attestations now ship with every release. +- Workarounds captured explicitly: + - **macOS Gatekeeper** until BEE-1791 closes โ€” right-click Open or `xattr -d com.apple.quarantine /usr/local/bin/beeping`. + - **Windows SmartScreen** until BEE-1792 closes โ€” Run anyway flow. + - **Linux ALSA runtime prereq** for `cpal`-backed live audio โ€” `libasound2` / `alsa-lib`. Matches the BEE-1888 CI fix and is documented as a runtime prereq rather than a build-time one. + - **Windows BEE-2222 FFI runtime crash** โ€” run under WSL2 until that follow-up closes. + +**Tests**: + +- `markdownlint docs/installation.md README.md` โ†’ 0 errors. +- `lychee` online link-check โ†’ **32 OK, 0 errors** (2 informational redirects). All cross-doc links + GitHub repo refs + Linear issue refs resolve. +- BEE-X reference rot grep: 16 unique IDs in `installation.md`, 23 in `README.md` โ€” every ID maps to a real tracker entry (Phase 14 closed + Phase 15 mix + BEE-2222 follow-up). No rotted IDs. + +**Net delta global**: 0 days. 2 SP fits comfortably within sustained velocity; the implementation was a single closure session because the supply-chain layer landed earlier today (BEE-1781) so the verify recipe was already canonical. + +**New estimated end date**: 2026-05-19 (no change). + +**New global status**: โœ… On time, Phase 15 at 91 % (51/56 SP). + +#### Advanced (negative = earlier) + +- (none โ€” within velocity) + +#### Delayed + +- (none) + +#### Scope changes + +- **Scope clarification**: BEE-1785 (2 SP) moves from Phase 15 shared scope to `beeping-cli`-specific scope. Reason: full implementation lives in this repo's docs + README. Third move of this shape this milestone (after BEE-1780 on 2026-05-06 and BEE-1781 earlier today) โ€” the pattern is now well-established and worth a future ROADMAP cleanup to pre-classify shared vs specific based on which repo the artifact lives in rather than the task title. + +#### Notes + +- Cumulative SP closed: 128 / 133 = 96 % of total scope, 91 % of Phase 15. +- Phase 15 specific scope: 13 tasks done (BEE-150, BEE-152, BEE-151, BEE-1780, BEE-1883, BEE-1884, BEE-1885, BEE-1886, BEE-1887, BEE-1888, BEE-1897, BEE-1781, BEE-1785) ยท 1 remaining (BEE-2222). +- Remaining unblocked Phase 15 shared scope candidates ranked by next-likely-pick: BEE-1782 / BEE-1783 (auto-update tap + scoop on release tag โ€” direct continuation of today's release-pipeline work), BEE-1786 (post-release smoke matrix โ€” validates BEE-1782/1783 once they land), BEE-1784 (AppImage). The remaining external-registry submissions (BEE-1787 / 1788 / 1789) need a stable real release first. + +--- + ### [2026-05-11] โ€” Closed BEE-1781 (5 SP, cosign + CycloneDX SBOM + SLSA L3 provenance) + scope clarification **Trigger**: closure of BEE-1781, plus a "Scope clarification" entry โ€” BEE-1781 was originally listed in Phase 15's _shared scope (NOT counted here)_ because the supply-chain layer was assumed to be cross-repo. In practice the entire implementation lives in `beeping-cli`'s `release.yml` + new `verify-supply-chain.yml` + `docs/supply-chain.md`, so it moves to the `beeping-cli`-specific table (+5 SP to Phase 15 specific). Same pattern as BEE-1780's move on 2026-05-06. From 0f176d6dee5987df4772894df34725a222fda347 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Mon, 11 May 2026 20:26:16 +0200 Subject: [PATCH 05/10] feat(release): BEE-1782 fire tap auto-update dispatch on release publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new `notify-tap` job to release.yml that runs after the `release` job succeeds. On stable `v*` tags (pre-release tags `-rc`/`-test`/`-alpha` are excluded with the same predicate used by publish-crates), the job fires a `repository_dispatch` event of type `beeping-cli-released` to `beeping-io/tap` with the new tag as `client_payload.tag`. The tap repo's `.github/workflows/auto-update.yml` (committed in `beeping-io/tap@881db92`) listens for that dispatch, downloads SHA256SUMS, regenerates `Formula/beeping-cli.rb` via `scripts/regen-formula.py`, and commits to develop. Founder action required after this merges: create a fine-grained PAT scoped to `beeping-io/tap` with metadata:read + contents:write, then add it as the `TAP_DISPATCH_TOKEN` secret in this repo. Until that lands, the notify-tap step emits a warning and exits 0 โ€” release itself still publishes, and the tap can be updated manually via workflow_dispatch on the tap side. Also: - external/tap/Formula/beeping-cli.rb header rewritten to document that this in-repo copy is the canonical structure while the deployed copy in beeping-io/tap carries the real hashes. - external/README.md moves BEE-1782 from "What's NOT here yet" to "What's now present" + documents the TAP_DISPATCH_TOKEN founder action. - docs/installation.md drops the "until BEE-1782 lands" caveat for the Homebrew tap (Scoop still pending BEE-1783). - README.md distribution channels table flips Homebrew status to "live + auto-updated per release". Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 43 +++++++++++++++++++++++++++++ README.md | 2 +- docs/installation.md | 15 +++++----- external/README.md | 24 ++++++++++++++-- external/tap/Formula/beeping-cli.rb | 13 +++++---- 5 files changed, 82 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6827b39..5f2d092 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -485,6 +485,49 @@ jobs: gh release edit "$TAG" --notes-file /tmp/release-body.md + notify-tap: + name: ๐Ÿบ Notify Homebrew tap (BEE-1782) + needs: release + runs-on: ubuntu-latest + # Stable tags only โ€” pre-release tags don't update the Homebrew + # tap to avoid shipping `-rc`/`-test`/`-alpha` versions to brew + # users. Same predicate as `publish-crates` below. + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-') + steps: + - name: ๐Ÿบ Fire repository_dispatch to beeping-io/tap + # Sends a `beeping-cli-released` event with the new tag. + # `beeping-io/tap`'s `.github/workflows/auto-update.yml` + # listens for it, downloads SHA256SUMS, regenerates the + # formula, and commits to develop. + # + # Token: TAP_DISPATCH_TOKEN must be a fine-grained PAT with + # `metadata: read` + `contents: write` on `beeping-io/tap`. + # If the secret is absent the step exits non-zero and the + # founder gets a CI ping โ€” release itself is already + # published, so failure here is recoverable via the manual + # `workflow_dispatch` fallback on the tap side. + env: + GH_TOKEN: ${{ secrets.TAP_DISPATCH_TOKEN }} + TAG: ${{ github.ref_name }} + run: | + set -euo pipefail + if [ -z "${GH_TOKEN:-}" ]; then + echo "::warning::TAP_DISPATCH_TOKEN secret is empty โ€” skipping dispatch" + echo "::warning::Run the tap's auto-update.yml manually via workflow_dispatch with tag=$TAG" + exit 0 + fi + # `gh api -f` only supports flat key=value; the dispatch + # payload needs a nested `client_payload.tag`, so feed JSON + # via `--input -`. + jq -n --arg tag "$TAG" \ + '{event_type: "beeping-cli-released", client_payload: {tag: $tag}}' \ + | gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + --input - \ + /repos/beeping-io/tap/dispatches + echo "::notice::Dispatched beeping-cli-released event for $TAG to beeping-io/tap" + publish-crates: name: ๐Ÿ“ฆ Publish to crates.io needs: release diff --git a/README.md b/README.md index 50708f8..048d51a 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ macOS arm64+x86_64 ยท Linux amd64+arm64 ยท Windows x86_64. | Channel | Install command | Status | |---|---|---| -| Homebrew tap | `brew install beeping-io/tap/beeping-cli` | ๐ŸŸข live (manual SHA256 until BEE-1782 auto-updates per release) | +| Homebrew tap | `brew install beeping-io/tap/beeping-cli` | ๐ŸŸข live + auto-updated per release (BEE-1782) | | Scoop bucket | `scoop install beeping-cli` (after `bucket add`) | ๐ŸŸข live (manual SHA256 until BEE-1783 auto-updates per release) | | `cargo` | `cargo install beeping-cli` | ๐ŸŸข live (publishes per release via crates.io) | | GitHub Releases | direct binary + man + completions tarball | ๐ŸŸข live (BEE-150 5-target matrix + BEE-152 man/completions + BEE-1780 SHA256SUMS + BEE-1781 cosign + SBOM + SLSA L3) | diff --git a/docs/installation.md b/docs/installation.md index f59fec4..7fd6961 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,11 +21,12 @@ authenticity before running anything (BEE-1781). | any | crates.io (Rust โ‰ฅ 1.88) | `cargo install beeping-cli` | | any | direct binary | download from | -> โš ๏ธ **Until BEE-1782 / BEE-1783 land**, the Homebrew formula and Scoop -> manifest carry **placeholder SHA256 hashes** that the maintainer -> regenerates manually post-release. If you hit a _resource hash -> mismatch_ error, file an issue and we'll regenerate. Real -> integrity verification still works via `SHA256SUMS` (see ยง ๐Ÿ›ก๏ธ Verify). +> โš ๏ธ **The Homebrew tap auto-updates per release** (BEE-1782). The +> Scoop manifest still carries **placeholder SHA256 hashes** that the +> maintainer regenerates manually post-release until BEE-1783 lands. +> If you hit a _resource hash mismatch_ error on Scoop, file an issue +> and we'll regenerate. Real integrity verification still works via +> `SHA256SUMS` (see ยง ๐Ÿ›ก๏ธ Verify). --- @@ -227,7 +228,7 @@ under WSL2 (Ubuntu) where the binary is fully functional. | Channel | Status | Tracker | |---|---|---| -| Homebrew tap (`beeping-io/tap`) | ๐ŸŸข live | BEE-151 โœ… ยท BEE-1782 (auto-update) ๐Ÿ“‹ | +| Homebrew tap (`beeping-io/tap`) | ๐ŸŸข live + auto-updated per release | BEE-151 โœ… ยท BEE-1782 โœ… | | Scoop bucket (`beeping-io/scoop-bucket`) | ๐ŸŸข live | BEE-151 โœ… ยท BEE-1783 (auto-update) ๐Ÿ“‹ | | `cargo install` (crates.io) | ๐ŸŸข live | BEE-151 โœ… | | GitHub Releases | ๐ŸŸข live | BEE-150 + BEE-152 + BEE-1780 + BEE-1781 โœ… | @@ -249,7 +250,7 @@ under WSL2 (Ubuntu) where the binary is fully functional. | `cannot be opened because the developer cannot be verified` (macOS) | Gatekeeper quarantine | See ยง macOS Gatekeeper workaround | | `Windows protected your PC` (Windows) | SmartScreen unsigned-binary check | See ยง Windows SmartScreen workaround | | `error while loading shared libraries: libasound.so.2` (Linux) | ALSA runtime missing | `sudo apt install libasound2` or `sudo dnf install alsa-lib` | -| `resource hash mismatch` (Homebrew/Scoop) | Placeholder SHA256 not yet refreshed for this release | File an issue; will be auto-fixed by BEE-1782/BEE-1783 | +| `resource hash mismatch` on Scoop | Placeholder SHA256 not yet refreshed for this release | File an issue; will be auto-fixed by BEE-1783. Homebrew tap already auto-updates per release (BEE-1782). | | `STATUS_ACCESS_VIOLATION 0xC0000005` (Windows) | BEE-2222 FFI runtime crash | Run under WSL2 until BEE-2222 closes | | `cargo install beeping-cli` fails to compile | Rust toolchain < 1.88 | `rustup update stable` | diff --git a/external/README.md b/external/README.md index 3754965..9dd0c6f 100644 --- a/external/README.md +++ b/external/README.md @@ -33,10 +33,10 @@ The plan is: ## What's NOT here yet -- Auto-updating SHAs (BEE-1782 / BEE-1783) +- Scoop manifest auto-update (BEE-1783) - Smoke tests post-release (BEE-1786) -## What's now present (BEE-1781 โ€” implemented 2026-05-11) +## What's now present (BEE-1781 + BEE-1782 โ€” implemented 2026-05-11) - `cosign` keyless signatures (`.sig` + `.pem`) shipped alongside every release artifact. Verification recipe in `docs/supply-chain.md`. @@ -44,11 +44,31 @@ The plan is: - SLSA L3 provenance (`beeping-cli.intoto.jsonl`) covering the whole release, generated by the `slsa-framework/slsa-github-generator` reusable workflow. +- **Homebrew tap auto-update on release** (BEE-1782): `release.yml`'s + `notify-tap` job fires a `repository_dispatch` to `beeping-io/tap` + after a stable `v*` tag publishes. The tap's `auto-update.yml` + downloads `SHA256SUMS`, regenerates `Formula/beeping-cli.rb` with + real hashes + new version via `scripts/regen-formula.py`, and + commits to develop. Pre-release tags (`-rc`/`-test`/`-alpha`) + skip the dispatch (same predicate as `publish-crates`). Homebrew + Scoop only check the SHA256 hash (their schema can't encode cosign / SLSA today). The cosign + SLSA layer is opt-in via `docs/supply-chain.md` and exercised by `.github/workflows/verify-supply-chain.yml` on every release. +## Founder action required for BEE-1782 + +A fine-grained PAT scoped to `beeping-io/tap` must be added to +this repo's GitHub Actions secrets as `TAP_DISPATCH_TOKEN` with: + +- `metadata: read` +- `contents: write` + +Without it the `notify-tap` job emits a warning and exits 0 โ€” the +release itself still publishes, and the founder can manually fire +`auto-update.yml` from the tap repo via `workflow_dispatch` with +the tag as input. + Until those land, every release requires a manual SHA256 update in this directory. Documented as a known limitation in `docs/installation.md`. diff --git a/external/tap/Formula/beeping-cli.rb b/external/tap/Formula/beeping-cli.rb index d8da368..e0da93d 100644 --- a/external/tap/Formula/beeping-cli.rb +++ b/external/tap/Formula/beeping-cli.rb @@ -1,11 +1,14 @@ # typed: false # frozen_string_literal: true -# Homebrew formula for `beeping-cli`. Bootstrap version: SHA256 hashes are -# placeholders that BEE-1782 will rewrite automatically on every release. -# Until BEE-1782 lands, post-release the maintainer regenerates this -# file with `shasum -a 256` against each tarball + commits the result -# (manual cycle; documented in `external/README.md`). +# Homebrew formula for `beeping-cli`. SHA256 hashes are auto-maintained +# by `beeping-io/tap`'s `.github/workflows/auto-update.yml` (BEE-1782): +# every published release fires a `repository_dispatch` to the tap repo +# which downloads SHA256SUMS for the new tag, regenerates the formula +# in-place, and commits to develop. This in-repo copy at +# `external/tap/Formula/beeping-cli.rb` is the canonical *structure*; +# the SHA256s here remain placeholders, while the deployed copy in +# `beeping-io/tap` carries the real hashes. # # Supply chain (BEE-1781): every release also ships cosign keyless # signatures (`.sig` + `.pem`) and SLSA L3 provenance From 7e36640bf50c21b8c5f826a810caa648e17441a3 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Tue, 12 May 2026 06:08:18 +0200 Subject: [PATCH 06/10] docs(roadmap): BEE-1782 recompute timeline + changelog - Move BEE-1782 from Phase 15 shared scope to beeping-cli specific (+3 SP). Fourth move of this shape this milestone (after BEE-1780, BEE-1781, BEE-1785). - Phase 15 specific now 59 SP; 54/59 done (92 %), 1 remaining (BEE-2222). - Append History entry covering release.yml notify-tap job + tap repo auto-update.yml + regen-formula.py + end-to-end test cycle on v0.0.0-test4. - No timeline impact; estimated end stays 2026-05-19. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ROADMAP.md | 27 +++++++++++------ docs/ROADMAP_CHANGELOG.md | 62 +++++++++++++++++++++++++++++++++++---- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 0bf2104..140523c 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,11 +14,11 @@ | **Estimated end (with 20 % risk margin)** | 2026-05-15 (was 2026-05-30, advanced 15 days; scope-change absorbed into buffer) | | **Initial velocity assumed** | 5 SP / work-day (solo developer, multi-repo context) | | **Risk margin** | 20 % over raw work-day estimate | -| **Total story points scoped to this repo** | 133 SP (Phase 14: 77 ยท Phase 15: 56) | -| **Story points completed** | 128 SP (34 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785**) | +| **Total story points scoped to this repo** | 136 SP (Phase 14: 77 ยท Phase 15: 59) | +| **Story points completed** | 131 SP (35 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782**) | | **Story points remaining** | 5 SP (Phase 15: BEE-2222 โ€” 1 task) | -| **Global status** | โœ… On time โ€” Phase 15 in flight (91 % done), Phase 14 done | -| **Last update** | 2026-05-11 โ€” closed BEE-1785 (install docs polish + README install section, 2 SP); moved from shared to `beeping-cli`-specific scope (+2 SP to Phase 15 specific) | +| **Global status** | โœ… On time โ€” Phase 15 in flight (92 % done), Phase 14 done | +| **Last update** | 2026-05-12 โ€” closed BEE-1782 (Homebrew tap auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) | --- @@ -27,7 +27,7 @@ | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 56 | 2026-05-04 | 2026-05-19 | โณ in flight (51/56 SP done, 91 %) | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 59 | 2026-05-04 | 2026-05-19 | โณ in flight (54/59 SP done, 92 %) | > **Note**: Phase 15 also contains 15 additional tasks (~60 SP) shared with > `beepbox-cli` (the C++ CLI). Those are not counted in this repo's SP total โ€” @@ -83,7 +83,7 @@ else; tests close out the milestone). --- -## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 56 SP) +## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 59 SP) **Goal**: Public installable binaries for `beeping-cli` on 6+ channels with signing, SBOM, and SLSA L3 provenance. Smoke tests validate every channel @@ -116,8 +116,9 @@ ecosystem level. | 11 | [BEE-1897](https://linear.app/me8/issue/BEE-1897) โ€” ๐Ÿ”ง CI matrix hardening (BEE-150 follow-up) | 5 | โœ… **Done** 2026-05-07 (3 blockers resolved; Windows runtime FFI crash spun off to BEE-2222) | | 12 | [BEE-1781](https://linear.app/me8/issue/BEE-1781) โ€” ๐Ÿ” cosign keyless + CycloneDX SBOM + SLSA L3 provenance | 5 | โœ… **Done** 2026-05-11 (every release ships .sig + .pem + .cdx.json + intoto.jsonl; end-to-end verified on test tag) | | 13 | [BEE-1785](https://linear.app/me8/issue/BEE-1785) โ€” ๐Ÿ“š Install section in README + `docs/installation.md` polish | 2 | โœ… **Done** 2026-05-11 (per-OS one-liners + supply-chain verify recipe + Gatekeeper/SmartScreen workarounds + BEE-2222 caveat + troubleshooting matrix) | -| 14 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | -| | **Total** | **56** | 51 done ยท 5 remaining | +| 14 | [BEE-1782](https://linear.app/me8/issue/BEE-1782) โ€” ๐Ÿบ Homebrew tap auto-update on release | 3 | โœ… **Done** 2026-05-12 (release.yml dispatches โ†’ tap's auto-update.yml regenerates formula via regen-formula.py + commits to develop; e2e verified on v0.0.0-test4) | +| 15 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | +| | **Total** | **59** | 54 done ยท 5 remaining | ### Phase 15 shared scope (NOT counted here) @@ -127,7 +128,7 @@ that runs from `beepbox`'s side. They're not included in this repo's SP total to avoid double-counting: BEE-1778 (ADR), BEE-1779 (CI release matrix), -BEE-1782 (Homebrew formula auto-update), BEE-1783 (Scoop manifest auto-update), +BEE-1783 (Scoop manifest auto-update), BEE-1784 (AppImage), BEE-1786 (smoke tests), BEE-1787 (winget), BEE-1788 (Chocolatey), BEE-1789 (Homebrew core), BEE-1790 (.deb + .rpm Cloudsmith), BEE-1791 (Apple Developer ID, pending @@ -149,6 +150,14 @@ budget), BEE-1792 (Authenticode, pending budget). > `README.md` install section โ€” moved to the specific table on 2026-05-11 > when it closed (+2 SP to Phase 15 specific, recorded as a scope > clarification in `ROADMAP_CHANGELOG.md`). +> +> Note: BEE-1782 (Homebrew tap auto-update) was originally listed here +> because its task title references `beepbox-cli.rb`. The `beeping-cli` +> implementation lives entirely in this repo's `release.yml` (dispatch +> job) + the `beeping-io/tap` repo (`auto-update.yml` workflow + +> `regen-formula.py` script) โ€” moved to the specific table on +> 2026-05-12 when it closed (+3 SP to Phase 15 specific, recorded as a +> scope clarification in `ROADMAP_CHANGELOG.md`). --- diff --git a/docs/ROADMAP_CHANGELOG.md b/docs/ROADMAP_CHANGELOG.md index 41c608d..8c463ea 100644 --- a/docs/ROADMAP_CHANGELOG.md +++ b/docs/ROADMAP_CHANGELOG.md @@ -15,21 +15,73 @@ - **Project start**: 2026-04-28 - **Estimated end (with 20 % margin)**: 2026-05-19 (unchanged; within velocity) - **Velocity assumed**: 5 story points / work-day (actual sustained ~6 SP / work-day) -- **Total SP scoped to this repo**: 133 (Phase 14: 77 ยท Phase 15: 56) -- **SP completed**: 128 (34 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785) +- **Total SP scoped to this repo**: 136 (Phase 14: 77 ยท Phase 15: 59) +- **SP completed**: 131 (35 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782) - **SP remaining**: 5 (Phase 15: BEE-2222 = 1 task) -- **Global status**: โœ… On time โ€” Phase 15 in flight (51/56 SP done, 91 %) -- **Last update**: 2026-05-11 โ€” closed BEE-1785 (install docs polish + README install section, 2 SP); moved from shared to `beeping-cli`-specific scope (+2 SP to Phase 15 specific) +- **Global status**: โœ… On time โ€” Phase 15 in flight (54/59 SP done, 92 %) +- **Last update**: 2026-05-12 โ€” closed BEE-1782 (Homebrew tap auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 56 | 2026-05-04 | 2026-05-19 | โณ in flight | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 59 | 2026-05-04 | 2026-05-19 | โณ in flight | --- ## ๐Ÿ“œ History +### [2026-05-12] โ€” Closed BEE-1782 (3 SP, Homebrew tap auto-update on release) + scope clarification + +**Trigger**: closure of BEE-1782, plus the 4th _Scope clarification_ entry of this milestone (after BEE-1780 on 2026-05-06, BEE-1781 + BEE-1785 on 2026-05-11). The implementation for `beeping-cli` lives in this repo's `release.yml` + `beeping-io/tap`'s `auto-update.yml` + `scripts/regen-formula.py`. Moves to the `beeping-cli`-specific table (+3 SP to Phase 15 specific). + +**Delivered**: + +The release pipeline now auto-publishes formula updates to the Homebrew tap end-to-end: + +- **In `beeping-cli`** โ€” new `notify-tap` job in `release.yml` runs after `release` succeeds. Predicate matches `publish-crates`: stable `v*` tags only, pre-release `-rc`/`-test`/`-alpha` skip. The step builds a JSON body via `jq -n --arg tag "$TAG"` (nested `client_payload.tag` needs `--input -`, not `gh api -f`) and pipes to `gh api POST /repos/beeping-io/tap/dispatches`. Token: new `TAP_DISPATCH_TOKEN` secret (founder-action: fine-grained PAT scoped to `beeping-io/tap` with metadata:read + contents:write). When the secret is absent the step emits a warning and exits 0 โ€” release itself still publishes; founder fallback is manual `workflow_dispatch` on the tap. +- **In `beeping-io/tap`** โ€” three new files: + - `.github/workflows/auto-update.yml` (commit `881db92`) โ€” listens on `repository_dispatch` event_type=`beeping-cli-released` + `workflow_dispatch` with a `tag` input. Steps: resolve tag/version โ†’ download `SHA256SUMS` for the tag โ†’ run `scripts/regen-formula.py` โ†’ `ruby -c` syntax gate โ†’ optional `brew style` (best-effort) โ†’ commit + push if changed. Permissions: `contents: write` via default `GITHUB_TOKEN`. + - `scripts/regen-formula.py` โ€” deterministic Python script. Accepts both GNU and BSD shasum formats. Parses out the 4 Homebrew-supported targets (macOS arm64 + intel, Linux arm64 + intel), rewrites `version "..."` + 4 `sha256 "..."` fields. Exits non-zero if any target is missing โ€” refuses half-updated formula state. Skips Windows .zip + supply-chain artifacts. + - `.markdownlint.json` โ€” disables MD013 + MD060 to match upstream conventions. + - `README.md` rewrite + `Formula/beeping-cli.rb` header comment sync (commit `2a5c4a2`). +- **Doc updates in `beeping-cli`** โ€” `external/tap/Formula/beeping-cli.rb` header rewritten (canonical structure here, real hashes deployed downstream); `external/README.md` flips BEE-1782 from "NOT here yet" โ†’ "now present" + documents the `TAP_DISPATCH_TOKEN` founder action; `docs/installation.md` drops the "until BEE-1782" caveat for Homebrew (Scoop still pending BEE-1783); `README.md` distribution channels table flips Homebrew status to "๐ŸŸข live + auto-updated per release". + +**Tests**: + +- Local dry-run of `regen-formula.py` against a fixture SHA256SUMS file โ†’ version rewritten cleanly + 4 sha256 fields filled in + `ruby -c` Syntax OK. +- `actionlint` on both workflow files โ†’ 0 new errors (only the pre-existing SC2193/SC2016 warnings inherited from BEE-150 + BEE-1780). +- `markdownlint` on all touched markdown files โ†’ clean. +- **End-to-end on tag `v0.0.0-test4`**: release pipeline ran (run [25689203685](https://github.com/beeping-io/beeping-cli/actions/runs/25689203685), 23 assets published) โ†’ `notify-tap` correctly **skipped** (pre-release predicate) โ†’ manually fired tap's `auto-update.yml` via `workflow_dispatch` with `tag=v0.0.0-test4` (run [25689660696](https://github.com/beeping-io/tap/actions/runs/25689660696), green in ~30s) โ†’ workflow downloaded SHA256SUMS โ†’ regen rewrote formula โ†’ committed `501346e` to develop with the real test-release hashes + version `0.0.0-test4` โ†’ cleanup: reverted to bootstrap state (`a6030af`), deleted test release + tag, followed up with header-comment sync `2a5c4a2`. + +**Not tested end-to-end**: the cross-repo `repository_dispatch` from `beeping-cli` โ†’ `beeping-io/tap` (gated on founder creating `TAP_DISPATCH_TOKEN`). Mechanical single `gh api` POST; the manual fallback path (`workflow_dispatch` on the tap repo) is verified green. + +**Net delta global**: 0 days. 3 SP fits sustained velocity; the implementation leveraged the now-stable BEE-1781 release pipeline. + +**New estimated end date**: 2026-05-19 (no change). + +**New global status**: โœ… On time, Phase 15 at 92 % (54/59 SP). + +#### Advanced (negative = earlier) + +- (none โ€” within velocity) + +#### Delayed + +- (none) + +#### Scope changes + +- **Scope clarification**: BEE-1782 (3 SP) moves from Phase 15 shared scope to `beeping-cli`-specific scope. Reason: implementation lives entirely in this repo's `release.yml` + `beeping-io/tap`. Fourth move of this shape this milestone (BEE-1780 โ†’ 1781 โ†’ 1785 โ†’ 1782). + +#### Notes + +- Cumulative SP closed: 131 / 136 = 96 % of total scope, 92 % of Phase 15. +- Phase 15 specific scope: 14 tasks done (BEE-150, BEE-152, BEE-151, BEE-1780, BEE-1883, BEE-1884, BEE-1885, BEE-1886, BEE-1887, BEE-1888, BEE-1897, BEE-1781, BEE-1785, BEE-1782) ยท 1 remaining (BEE-2222). +- The 4-task scope-clarification pattern (BEE-1780/1781/1785/1782) means the ROADMAP's "Phase 15 shared scope" list now has 11 entries down from the original 14. The natural cleanup after BEE-2222 closes is to either rename the section header or pre-classify tasks by source repo on creation rather than at closure. +- Next-likely-pick remaining: BEE-1783 (Scoop manifest auto-update โ€” direct symmetric continuation of today's BEE-1782 pattern, including a `regen-manifest.py` for the JSON schema), BEE-1786 (post-release smoke matrix โ€” gains real value now that BEE-1782 is live and BEE-1783 lands). + +--- + ### [2026-05-11] โ€” Closed BEE-1785 (2 SP, install docs polish + README install section) + scope clarification **Trigger**: closure of BEE-1785 plus a third "Scope clarification" entry of the same shape as BEE-1780 (2026-05-06) and BEE-1781 (this morning). BEE-1785 was originally in Phase 15's _shared scope (NOT counted here)_ on the assumption that install docs would be split across `beepbox-cli` and `beeping-cli`. In practice the entire deliverable lives in `beeping-cli`'s `docs/installation.md` + `README.md`, so it moves to the `beeping-cli`-specific table (+2 SP to Phase 15 specific). From 782c85b9deb245832a7f45e2b52cac952ccff117 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Tue, 12 May 2026 07:24:44 +0200 Subject: [PATCH 07/10] feat(release): BEE-1783 fire scoop-bucket auto-update dispatch on release Add `notify-scoop` job to release.yml, symmetric to `notify-tap` from BEE-1782. Same predicate (stable v* tags only, pre-release skip), same dispatch pattern (gh api POST .../dispatches with jq-built JSON body), same fall-through behaviour when the secret is missing (warning + exit 0). Per-repo least-privilege: SCOOP_DISPATCH_TOKEN is a separate fine-grained PAT scoped to beeping-io/scoop-bucket. The matching scoop-bucket-side workflow + regen script were committed at beeping-io/scoop-bucket@3b29f7f. Also: - external/scoop-bucket/bucket/beeping-cli.json _comment rewritten to document the auto-update flow. - external/README.md moves BEE-1783 from "What's NOT here yet" to "What's now present" + adds the SCOOP_DISPATCH_TOKEN founder action alongside TAP_DISPATCH_TOKEN. - docs/installation.md drops the "until BEE-1783 lands" caveat for Scoop (both Homebrew + Scoop now auto-update); Channel status row flipped; Troubleshooting row simplified. - README.md distribution channels table flips Scoop status to "live + auto-updated per release". Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 42 +++++++++++++++++++ README.md | 2 +- docs/installation.md | 13 +++--- external/README.md | 30 ++++++++----- external/scoop-bucket/bucket/beeping-cli.json | 2 +- 5 files changed, 68 insertions(+), 21 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5f2d092..ad38643 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -528,6 +528,48 @@ jobs: /repos/beeping-io/tap/dispatches echo "::notice::Dispatched beeping-cli-released event for $TAG to beeping-io/tap" + notify-scoop: + name: ๐Ÿฅ„ Notify Scoop bucket (BEE-1783) + needs: release + runs-on: ubuntu-latest + # Stable tags only โ€” same predicate as `notify-tap` + `publish-crates`. + # Pre-release tags don't update the Scoop bucket to avoid shipping + # `-rc`/`-test`/`-alpha` versions to Scoop users. + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-') + steps: + - name: ๐Ÿฅ„ Fire repository_dispatch to beeping-io/scoop-bucket + # Sends a `beeping-cli-released` event with the new tag. + # `beeping-io/scoop-bucket`'s `.github/workflows/auto-update.yml` + # listens for it, downloads SHA256SUMS, regenerates the + # manifest, and commits to develop. + # + # Token: SCOOP_DISPATCH_TOKEN must be a fine-grained PAT with + # `metadata: read` + `contents: write` on + # `beeping-io/scoop-bucket`. Kept separate from + # TAP_DISPATCH_TOKEN for per-repo least privilege. If the + # secret is absent the step emits a warning and exits 0 โ€” + # release itself is already published, so failure here is + # recoverable via the manual `workflow_dispatch` fallback on + # the bucket side. + env: + GH_TOKEN: ${{ secrets.SCOOP_DISPATCH_TOKEN }} + TAG: ${{ github.ref_name }} + run: | + set -euo pipefail + if [ -z "${GH_TOKEN:-}" ]; then + echo "::warning::SCOOP_DISPATCH_TOKEN secret is empty โ€” skipping dispatch" + echo "::warning::Run the bucket's auto-update.yml manually via workflow_dispatch with tag=$TAG" + exit 0 + fi + jq -n --arg tag "$TAG" \ + '{event_type: "beeping-cli-released", client_payload: {tag: $tag}}' \ + | gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + --input - \ + /repos/beeping-io/scoop-bucket/dispatches + echo "::notice::Dispatched beeping-cli-released event for $TAG to beeping-io/scoop-bucket" + publish-crates: name: ๐Ÿ“ฆ Publish to crates.io needs: release diff --git a/README.md b/README.md index 048d51a..c181d30 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ macOS arm64+x86_64 ยท Linux amd64+arm64 ยท Windows x86_64. | Channel | Install command | Status | |---|---|---| | Homebrew tap | `brew install beeping-io/tap/beeping-cli` | ๐ŸŸข live + auto-updated per release (BEE-1782) | -| Scoop bucket | `scoop install beeping-cli` (after `bucket add`) | ๐ŸŸข live (manual SHA256 until BEE-1783 auto-updates per release) | +| Scoop bucket | `scoop install beeping-cli` (after `bucket add`) | ๐ŸŸข live + auto-updated per release (BEE-1783) | | `cargo` | `cargo install beeping-cli` | ๐ŸŸข live (publishes per release via crates.io) | | GitHub Releases | direct binary + man + completions tarball | ๐ŸŸข live (BEE-150 5-target matrix + BEE-152 man/completions + BEE-1780 SHA256SUMS + BEE-1781 cosign + SBOM + SLSA L3) | | Homebrew core | `brew install beeping-cli` (after upstream review) | ๐Ÿ“‹ BEE-1789 | diff --git a/docs/installation.md b/docs/installation.md index 7fd6961..ddd7789 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,12 +21,9 @@ authenticity before running anything (BEE-1781). | any | crates.io (Rust โ‰ฅ 1.88) | `cargo install beeping-cli` | | any | direct binary | download from | -> โš ๏ธ **The Homebrew tap auto-updates per release** (BEE-1782). The -> Scoop manifest still carries **placeholder SHA256 hashes** that the -> maintainer regenerates manually post-release until BEE-1783 lands. -> If you hit a _resource hash mismatch_ error on Scoop, file an issue -> and we'll regenerate. Real integrity verification still works via -> `SHA256SUMS` (see ยง ๐Ÿ›ก๏ธ Verify). +> โœ… Both the Homebrew tap (BEE-1782) and the Scoop bucket (BEE-1783) +> auto-update per release. Real integrity verification still works +> via `SHA256SUMS` (see ยง ๐Ÿ›ก๏ธ Verify). --- @@ -229,7 +226,7 @@ under WSL2 (Ubuntu) where the binary is fully functional. | Channel | Status | Tracker | |---|---|---| | Homebrew tap (`beeping-io/tap`) | ๐ŸŸข live + auto-updated per release | BEE-151 โœ… ยท BEE-1782 โœ… | -| Scoop bucket (`beeping-io/scoop-bucket`) | ๐ŸŸข live | BEE-151 โœ… ยท BEE-1783 (auto-update) ๐Ÿ“‹ | +| Scoop bucket (`beeping-io/scoop-bucket`) | ๐ŸŸข live + auto-updated per release | BEE-151 โœ… ยท BEE-1783 โœ… | | `cargo install` (crates.io) | ๐ŸŸข live | BEE-151 โœ… | | GitHub Releases | ๐ŸŸข live | BEE-150 + BEE-152 + BEE-1780 + BEE-1781 โœ… | | Homebrew core (`brew install beeping-cli`) | ๐Ÿ“‹ queued | BEE-1789 (~2-4 week external review after submit) | @@ -250,7 +247,7 @@ under WSL2 (Ubuntu) where the binary is fully functional. | `cannot be opened because the developer cannot be verified` (macOS) | Gatekeeper quarantine | See ยง macOS Gatekeeper workaround | | `Windows protected your PC` (Windows) | SmartScreen unsigned-binary check | See ยง Windows SmartScreen workaround | | `error while loading shared libraries: libasound.so.2` (Linux) | ALSA runtime missing | `sudo apt install libasound2` or `sudo dnf install alsa-lib` | -| `resource hash mismatch` on Scoop | Placeholder SHA256 not yet refreshed for this release | File an issue; will be auto-fixed by BEE-1783. Homebrew tap already auto-updates per release (BEE-1782). | +| `resource hash mismatch` on Homebrew/Scoop | Auto-update workflow failed for this release (rare) | File an issue with the tag; founder fires the manual `workflow_dispatch` on the relevant downstream repo. | | `STATUS_ACCESS_VIOLATION 0xC0000005` (Windows) | BEE-2222 FFI runtime crash | Run under WSL2 until BEE-2222 closes | | `cargo install beeping-cli` fails to compile | Rust toolchain < 1.88 | `rustup update stable` | diff --git a/external/README.md b/external/README.md index 9dd0c6f..add8670 100644 --- a/external/README.md +++ b/external/README.md @@ -33,10 +33,9 @@ The plan is: ## What's NOT here yet -- Scoop manifest auto-update (BEE-1783) - Smoke tests post-release (BEE-1786) -## What's now present (BEE-1781 + BEE-1782 โ€” implemented 2026-05-11) +## What's now present (BEE-1781 + BEE-1782 + BEE-1783 โ€” implemented 2026-05-11 / 2026-05-12) - `cosign` keyless signatures (`.sig` + `.pem`) shipped alongside every release artifact. Verification recipe in `docs/supply-chain.md`. @@ -51,24 +50,33 @@ The plan is: real hashes + new version via `scripts/regen-formula.py`, and commits to develop. Pre-release tags (`-rc`/`-test`/`-alpha`) skip the dispatch (same predicate as `publish-crates`). +- **Scoop bucket auto-update on release** (BEE-1783): symmetric + `notify-scoop` job parallel to `notify-tap`. Fires the same + `repository_dispatch` event_type to `beeping-io/scoop-bucket`. + That repo's `auto-update.yml` regenerates `bucket/beeping-cli.json` + via `scripts/regen-manifest.py` (rewrites `version` + Windows ZIP + URL + hash + `extract_dir`) and commits to develop. Homebrew + Scoop only check the SHA256 hash (their schema can't encode cosign / SLSA today). The cosign + SLSA layer is opt-in via `docs/supply-chain.md` and exercised by `.github/workflows/verify-supply-chain.yml` on every release. -## Founder action required for BEE-1782 +## Founder actions required for BEE-1782 + BEE-1783 -A fine-grained PAT scoped to `beeping-io/tap` must be added to -this repo's GitHub Actions secrets as `TAP_DISPATCH_TOKEN` with: +Two fine-grained PATs must be added to this repo's GitHub Actions +secrets โ€” one per downstream repo, kept separate for per-repo least +privilege: -- `metadata: read` -- `contents: write` +- `TAP_DISPATCH_TOKEN` โ€” scoped to `beeping-io/tap` with + `metadata: read` + `contents: write`. +- `SCOOP_DISPATCH_TOKEN` โ€” scoped to `beeping-io/scoop-bucket` with + `metadata: read` + `contents: write`. -Without it the `notify-tap` job emits a warning and exits 0 โ€” the -release itself still publishes, and the founder can manually fire -`auto-update.yml` from the tap repo via `workflow_dispatch` with -the tag as input. +Without either secret the corresponding `notify-*` job emits a +warning and exits 0 โ€” the release itself still publishes, and the +founder can manually fire `auto-update.yml` from the relevant +downstream repo via `workflow_dispatch` with the tag as input. Until those land, every release requires a manual SHA256 update in this directory. Documented as a known limitation in `docs/installation.md`. diff --git a/external/scoop-bucket/bucket/beeping-cli.json b/external/scoop-bucket/bucket/beeping-cli.json index 19e026c..6e917e8 100644 --- a/external/scoop-bucket/bucket/beeping-cli.json +++ b/external/scoop-bucket/bucket/beeping-cli.json @@ -29,5 +29,5 @@ } } }, - "_comment": "BEE-151 bootstrap. SHA256 hash is a placeholder; BEE-1783 will rewrite it on every release via scoop's autoupdate. Until then, regenerate manually post-release. BEE-1781: every release also ships cosign keyless signatures (.sig + .pem) and SLSA L3 provenance (beeping-cli.intoto.jsonl); see docs/supply-chain.md for opt-in verification." + "_comment": "Canonical manifest structure. The deployed copy in beeping-io/scoop-bucket carries the real auto-generated hash + version + URL โ€” auto-maintained by that repo's .github/workflows/auto-update.yml (BEE-1783) on every release, triggered by a repository_dispatch from beeping-cli's release.yml. Structural changes here transplant downstream on the next release. BEE-1781: every release also ships cosign keyless signatures (.sig + .pem) and SLSA L3 provenance (beeping-cli.intoto.jsonl); see docs/supply-chain.md for opt-in verification." } From e622c8a7babf7063565a99c1c519faf85c2d2639 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Tue, 12 May 2026 09:06:37 +0200 Subject: [PATCH 08/10] docs(roadmap): BEE-1783 recompute timeline + changelog - Move BEE-1783 from Phase 15 shared scope to beeping-cli specific (+3 SP). Fifth consecutive move of this shape this milestone (after BEE-1780, BEE-1781, BEE-1785, BEE-1782). - Phase 15 specific now 62 SP; 57/62 done (92 %), 1 remaining (BEE-2222). - Append History entry covering release.yml notify-scoop job + scoop-bucket auto-update.yml + regen-manifest.py + end-to-end test cycle on v0.0.0-test5. - No timeline impact; estimated end stays 2026-05-19. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ROADMAP.md | 25 ++++++++++------ docs/ROADMAP_CHANGELOG.md | 60 +++++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 140523c..910c7d1 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,11 +14,11 @@ | **Estimated end (with 20 % risk margin)** | 2026-05-15 (was 2026-05-30, advanced 15 days; scope-change absorbed into buffer) | | **Initial velocity assumed** | 5 SP / work-day (solo developer, multi-repo context) | | **Risk margin** | 20 % over raw work-day estimate | -| **Total story points scoped to this repo** | 136 SP (Phase 14: 77 ยท Phase 15: 59) | -| **Story points completed** | 131 SP (35 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782**) | +| **Total story points scoped to this repo** | 139 SP (Phase 14: 77 ยท Phase 15: 62) | +| **Story points completed** | 134 SP (36 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782 + BEE-1783**) | | **Story points remaining** | 5 SP (Phase 15: BEE-2222 โ€” 1 task) | | **Global status** | โœ… On time โ€” Phase 15 in flight (92 % done), Phase 14 done | -| **Last update** | 2026-05-12 โ€” closed BEE-1782 (Homebrew tap auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) | +| **Last update** | 2026-05-12 โ€” closed BEE-1783 (Scoop bucket auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) | --- @@ -27,7 +27,7 @@ | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 59 | 2026-05-04 | 2026-05-19 | โณ in flight (54/59 SP done, 92 %) | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 62 | 2026-05-04 | 2026-05-19 | โณ in flight (57/62 SP done, 92 %) | > **Note**: Phase 15 also contains 15 additional tasks (~60 SP) shared with > `beepbox-cli` (the C++ CLI). Those are not counted in this repo's SP total โ€” @@ -83,7 +83,7 @@ else; tests close out the milestone). --- -## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 59 SP) +## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 62 SP) **Goal**: Public installable binaries for `beeping-cli` on 6+ channels with signing, SBOM, and SLSA L3 provenance. Smoke tests validate every channel @@ -117,8 +117,9 @@ ecosystem level. | 12 | [BEE-1781](https://linear.app/me8/issue/BEE-1781) โ€” ๐Ÿ” cosign keyless + CycloneDX SBOM + SLSA L3 provenance | 5 | โœ… **Done** 2026-05-11 (every release ships .sig + .pem + .cdx.json + intoto.jsonl; end-to-end verified on test tag) | | 13 | [BEE-1785](https://linear.app/me8/issue/BEE-1785) โ€” ๐Ÿ“š Install section in README + `docs/installation.md` polish | 2 | โœ… **Done** 2026-05-11 (per-OS one-liners + supply-chain verify recipe + Gatekeeper/SmartScreen workarounds + BEE-2222 caveat + troubleshooting matrix) | | 14 | [BEE-1782](https://linear.app/me8/issue/BEE-1782) โ€” ๐Ÿบ Homebrew tap auto-update on release | 3 | โœ… **Done** 2026-05-12 (release.yml dispatches โ†’ tap's auto-update.yml regenerates formula via regen-formula.py + commits to develop; e2e verified on v0.0.0-test4) | -| 15 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | -| | **Total** | **59** | 54 done ยท 5 remaining | +| 15 | [BEE-1783](https://linear.app/me8/issue/BEE-1783) โ€” ๐Ÿฅ„ Scoop bucket auto-update on release | 3 | โœ… **Done** 2026-05-12 (symmetric to BEE-1782 retargeted at JSON manifest schema; e2e verified on v0.0.0-test5) | +| 16 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | +| | **Total** | **62** | 57 done ยท 5 remaining | ### Phase 15 shared scope (NOT counted here) @@ -128,7 +129,6 @@ that runs from `beepbox`'s side. They're not included in this repo's SP total to avoid double-counting: BEE-1778 (ADR), BEE-1779 (CI release matrix), -BEE-1783 (Scoop manifest auto-update), BEE-1784 (AppImage), BEE-1786 (smoke tests), BEE-1787 (winget), BEE-1788 (Chocolatey), BEE-1789 (Homebrew core), BEE-1790 (.deb + .rpm Cloudsmith), BEE-1791 (Apple Developer ID, pending @@ -158,6 +158,15 @@ budget), BEE-1792 (Authenticode, pending budget). > `regen-formula.py` script) โ€” moved to the specific table on > 2026-05-12 when it closed (+3 SP to Phase 15 specific, recorded as a > scope clarification in `ROADMAP_CHANGELOG.md`). +> +> Note: BEE-1783 (Scoop bucket auto-update) was originally listed here +> for the same reason as BEE-1782 (task title references +> `beepbox-cli.json`). The `beeping-cli` implementation lives in this +> repo's `release.yml` (`notify-scoop` job) + the +> `beeping-io/scoop-bucket` repo (`auto-update.yml` + `regen-manifest.py`) +> โ€” moved to the specific table on 2026-05-12 when it closed (+3 SP +> to Phase 15 specific). Fifth consecutive sharedโ†’specific move this +> milestone after BEE-1780/1781/1785/1782. --- diff --git a/docs/ROADMAP_CHANGELOG.md b/docs/ROADMAP_CHANGELOG.md index 8c463ea..eebaeb8 100644 --- a/docs/ROADMAP_CHANGELOG.md +++ b/docs/ROADMAP_CHANGELOG.md @@ -15,21 +15,71 @@ - **Project start**: 2026-04-28 - **Estimated end (with 20 % margin)**: 2026-05-19 (unchanged; within velocity) - **Velocity assumed**: 5 story points / work-day (actual sustained ~6 SP / work-day) -- **Total SP scoped to this repo**: 136 (Phase 14: 77 ยท Phase 15: 59) -- **SP completed**: 131 (35 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782) +- **Total SP scoped to this repo**: 139 (Phase 14: 77 ยท Phase 15: 62) +- **SP completed**: 134 (36 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782 + BEE-1783) - **SP remaining**: 5 (Phase 15: BEE-2222 = 1 task) -- **Global status**: โœ… On time โ€” Phase 15 in flight (54/59 SP done, 92 %) -- **Last update**: 2026-05-12 โ€” closed BEE-1782 (Homebrew tap auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) +- **Global status**: โœ… On time โ€” Phase 15 in flight (57/62 SP done, 92 %) +- **Last update**: 2026-05-12 โ€” closed BEE-1783 (Scoop bucket auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 59 | 2026-05-04 | 2026-05-19 | โณ in flight | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 62 | 2026-05-04 | 2026-05-19 | โณ in flight | --- ## ๐Ÿ“œ History +### [2026-05-12] โ€” Closed BEE-1783 (3 SP, Scoop bucket auto-update on release) + scope clarification + +**Trigger**: closure of BEE-1783, plus a 5th _Scope clarification_ entry this milestone (BEE-1780 โ†’ 1781 โ†’ 1785 โ†’ 1782 โ†’ 1783 โ€” five consecutive sharedโ†’specific moves). Symmetric mirror of BEE-1782 retargeted from Homebrew tap โ†’ Scoop bucket, Ruby formula โ†’ JSON manifest. + +**Delivered**: + +- **In `beeping-cli`** โ€” new `notify-scoop` job in `release.yml` parallel to `notify-tap`. Identical structure: predicate `github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')` (stable tags only, pre-release skip), same `jq -n | gh api --input -` pattern, same `gh-token-empty โ†’ warn + exit 0` fallback. Token: `SCOOP_DISPATCH_TOKEN` (separate from `TAP_DISPATCH_TOKEN` for per-repo least privilege). +- **In `beeping-io/scoop-bucket`** โ€” three new files mirroring the tap repo: + - `.github/workflows/auto-update.yml` (commit `3b29f7f`) โ€” listens on `repository_dispatch` event_type=`beeping-cli-released` + `workflow_dispatch` with `tag` input. Steps: resolve tag/version โ†’ download `SHA256SUMS` โ†’ run `scripts/regen-manifest.py` โ†’ `python3 -m json.tool` syntax gate โ†’ commit + push if changed. + - `scripts/regen-manifest.py` โ€” deterministic Python script. Locates the `beeping-cli-x86_64-pc-windows-msvc.zip` line in `SHA256SUMS`, rewrites the manifest's `version`, `architecture.64bit.url` (which uses literal `version` not a template variable), `architecture.64bit.hash`, and `architecture.64bit.extract_dir`. Uses `ensure_ascii=False` so unicode characters stay literal (em dash in description) โ€” minimal diffs across regens. Exits non-zero if the Windows line is missing. + - `.markdownlint.json` matching tap conventions. + - `README.md` rewrite + manifest `_comment` sync. +- **Doc updates in `beeping-cli`** โ€” `external/scoop-bucket/bucket/beeping-cli.json` `_comment` rewritten; `external/README.md` adds BEE-1783 to "What's now present" + lists `SCOOP_DISPATCH_TOKEN` alongside `TAP_DISPATCH_TOKEN` in the founder-actions section; `docs/installation.md` drops the "until BEE-1783" caveat (both Homebrew + Scoop now auto-update); `README.md` distribution channels table flips Scoop status to "๐ŸŸข live + auto-updated per release". + +**Tests**: + +- Local dry-run of `regen-manifest.py` against a fixture SHA256SUMS file โ†’ version rewritten cleanly + URL + hash + extract_dir + valid JSON + unicode preserved. +- `actionlint` on both workflow files โ†’ 0 new errors. +- `markdownlint` on all touched markdown files โ†’ clean. +- **End-to-end on tag `v0.0.0-test5`**: release pipeline ran (run [25715227205](https://github.com/beeping-io/beeping-cli/actions/runs/25715227205), 23 assets published) โ†’ both `notify-tap` + `notify-scoop` correctly **skipped** (pre-release predicate) โ†’ manually fired scoop-bucket's `auto-update.yml` via `workflow_dispatch` with `tag=v0.0.0-test5` (run [25715524295](https://github.com/beeping-io/scoop-bucket/actions/runs/25715524295), green in ~30s) โ†’ downloaded SHA256SUMS โ†’ regen rewrote manifest โ†’ committed `29153a0` to develop with `version "0.0.0-test5"` + real Windows ZIP hash โ†’ cleanup: reverted (`0c18d7c`), deleted test release + tag. + +**Not tested end-to-end**: the cross-repo `repository_dispatch` from `beeping-cli` โ†’ `beeping-io/scoop-bucket` (gated on founder creating `SCOOP_DISPATCH_TOKEN`). Same mechanical `gh api` POST as BEE-1782; manual fallback path verified. + +**Net delta global**: 0 days. 3 SP within velocity; implementation leveraged the BEE-1782 pattern + the now-stable BEE-1781 release pipeline. + +**New estimated end date**: 2026-05-19 (no change). + +**New global status**: โœ… On time, Phase 15 at 92 % (57/62 SP). + +#### Advanced (negative = earlier) + +- (none โ€” within velocity) + +#### Delayed + +- (none) + +#### Scope changes + +- **Scope clarification**: BEE-1783 (3 SP) moves from Phase 15 shared scope to `beeping-cli`-specific scope. Reason: implementation lives in this repo's `release.yml` + `beeping-io/scoop-bucket`. Fifth move of this shape this milestone (BEE-1780/1781/1785/1782/1783). + +#### Notes + +- Cumulative SP closed: 134 / 139 = 96 % of total scope, 92 % of Phase 15. +- Phase 15 specific scope: 15 tasks done ยท 1 remaining (BEE-2222). +- The 5-task scope-clarification pattern is now firmly established. The remaining Phase 15 shared scope list is down to 10 entries (from original 14): BEE-1778 (ADR), BEE-1779 (CI matrix), BEE-1784 (AppImage), BEE-1786 (smoke tests), BEE-1787 (winget), BEE-1788 (Chocolatey), BEE-1789 (Homebrew core), BEE-1790 (Cloudsmith), BEE-1791 + BEE-1792 (budget-blocked). +- Next-likely-pick: **BEE-1786** (post-release smoke matrix) โ€” naturally validates today's BEE-1782 + BEE-1783 work end-to-end on real OS runners (`brew install` on macOS + `scoop install` on Windows + `cargo install` cross-platform + raw tarball extract on Linux). High value, moderate effort, prerequisites all green. + +--- + ### [2026-05-12] โ€” Closed BEE-1782 (3 SP, Homebrew tap auto-update on release) + scope clarification **Trigger**: closure of BEE-1782, plus the 4th _Scope clarification_ entry of this milestone (after BEE-1780 on 2026-05-06, BEE-1781 + BEE-1785 on 2026-05-11). The implementation for `beeping-cli` lives in this repo's `release.yml` + `beeping-io/tap`'s `auto-update.yml` + `scripts/regen-formula.py`. Moves to the `beeping-cli`-specific table (+3 SP to Phase 15 specific). From ade34cee1cf5bc9ed3817bdc8939b3de0f26c577 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Tue, 12 May 2026 09:25:06 +0200 Subject: [PATCH 09/10] feat(ci): BEE-1786 post-release smoke matrix across every distribution channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New `.github/workflows/post-release-smoke.yml` fires on `release.published` (and manual `workflow_dispatch` for testing). Exercises every distribution channel against its native OS: - ๐Ÿ“ฆ Direct tarball/zip per target (5 platforms, native runners including the new macos-15-intel + ubuntu-24.04-arm). Downloads the artifact from the release, extracts, runs --version assertion matching the release tag, `doctor --mode offline`, and an offline encodeโ†’WAVโ†’decode round-trip (skipped on Windows pending BEE-2222). - ๐Ÿ“ฆ `cargo install beeping-cli --version ` on ubuntu + macos + windows (skipped on pre-release per crates.io publish predicate). - ๐Ÿบ `brew install beeping-io/tap/beeping-cli` on macos-latest (arm64) + macos-15-intel + ubuntu-latest (Linuxbrew). Skipped on pre-release per BEE-1782 tap auto-update predicate. - ๐Ÿฅ„ `scoop install beeping-cli` on windows-latest after adding the bucket. Skipped on pre-release per BEE-1783 bucket auto-update predicate. Final `summary` job (always runs, gated on `!cancelled()`) reads `needs.*.result`, emits a markdown table to `$GITHUB_STEP_SUMMARY` mapping channelโ†’โœ…/โŒ/โญ๏ธ/๐Ÿšซ, and fails the workflow if any active channel failed. Skipped channels (pre-release path) don't fail. Pre-release runs (e.g. `v0.0.0-test*`) execute only the direct-tarball path โ€” the other three channels skip themselves because their feeder pipelines also skip pre-releases. This keeps the smoke matrix testable with throwaway tags while still representing the real release contract. Adds the post-release-smoke badge to README and links to it from docs/installation.md. external/README.md: BEE-1786 moves to "What's now present"; the distribution scaffolding `NOT here yet` list is now empty for `beeping-cli`-scope work โ€” remaining BEE-178x is external registry submissions + AppImage/.deb/.rpm packaging. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/post-release-smoke.yml | 337 +++++++++++++++++++++++ README.md | 1 + docs/installation.md | 6 +- external/README.md | 12 +- 4 files changed, 353 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/post-release-smoke.yml diff --git a/.github/workflows/post-release-smoke.yml b/.github/workflows/post-release-smoke.yml new file mode 100644 index 0000000..c2ad830 --- /dev/null +++ b/.github/workflows/post-release-smoke.yml @@ -0,0 +1,337 @@ +# ๐Ÿงช Post-release smoke matrix โ€” install from every channel + verify it works. +# +# BEE-1786 โ€” fires after each published release and exercises every +# distribution channel against its native OS: +# +# - Homebrew tap (macOS arm64 + intel, Linux) +# - Scoop bucket (Windows) +# - `cargo install` (Linux + macOS + Windows) +# - Direct GitHub Releases tarball/zip (all 5 native targets) +# +# Channels still queued (BEE-1784 AppImage / BEE-1787 winget / +# BEE-1788 Chocolatey / BEE-1789 Homebrew core / BEE-1790 .deb+.rpm) +# add their own matrix rows when they land. No "skipped because not +# yet implemented" rows here โ€” only test what exists. +# +# Pre-release tags (`-rc`/`-test`/`-alpha`) skip Homebrew + Scoop + +# crates.io smokes because BEE-1780/1782/1783 also skip those +# pipelines for pre-releases. The direct-tarball + manual install +# smoke runs against every tag โ€” that's the universal floor. +# +# The summary job aggregates `needs.*.result` into a GitHub Actions +# Job Summary table (channel ร— platform โ†’ โœ… / โŒ) and fails the +# workflow if any cell failed. GitHub's commit-status banner + +# workflow-level email (per user GH settings) are the notification +# surface; a richer Slack hook is a follow-up. + +name: ๐Ÿงช Post-release smoke + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: "Release tag to smoke-test (e.g. v0.1.0). Required for workflow_dispatch." + type: string + required: true + +permissions: + contents: read + +concurrency: + group: post-release-smoke-${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag }} + cancel-in-progress: false + +env: + TAG: ${{ github.event.release.tag_name || inputs.tag }} + SMOKE_PAYLOAD: "beep-smoke-payload" + +jobs: + resolve: + name: ๐Ÿ“‹ Resolve target + flags + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.r.outputs.tag }} + version: ${{ steps.r.outputs.version }} + prerelease: ${{ steps.r.outputs.prerelease }} + steps: + - id: r + run: | + set -euo pipefail + if [ -z "${TAG:-}" ]; then + echo "::error::no tag โ€” release event must carry a tag or workflow_dispatch must pass one" + exit 1 + fi + VERSION="${TAG#v}" + # Same heuristic as release.yml's `publish-crates`/`notify-*` + # predicates: tags containing `-` are pre-release. + if [[ "$TAG" == *-* ]]; then + PRE=true + else + PRE=false + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "prerelease=$PRE" >> "$GITHUB_OUTPUT" + echo "::notice::Smoke-testing $TAG (version=$VERSION, prerelease=$PRE)" + + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Direct tarball / zip (BEE-150 release artifacts) + # Runs unconditionally for every tag โ€” the universal floor. + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + direct-tarball: + name: ๐Ÿ“ฆ Direct ${{ matrix.target }} + needs: resolve + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - target: aarch64-apple-darwin + runner: macos-latest + archive: tar.xz + - target: x86_64-apple-darwin + runner: macos-15-intel + archive: tar.xz + - target: x86_64-unknown-linux-gnu + runner: ubuntu-latest + archive: tar.xz + - target: aarch64-unknown-linux-gnu + runner: ubuntu-24.04-arm + archive: tar.xz + - target: x86_64-pc-windows-msvc + runner: windows-latest + archive: zip + steps: + - name: ๐Ÿง Install ALSA runtime (Linux only) + if: runner.os == 'Linux' + run: sudo apt-get update -qq && sudo apt-get install -y libasound2 + + - name: โฌ‡๏ธ Download artifact + env: + TAG: ${{ needs.resolve.outputs.tag }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + set -euo pipefail + ART="beeping-cli-${{ matrix.target }}.${{ matrix.archive }}" + gh release download "$TAG" --repo "${GITHUB_REPOSITORY}" --pattern "$ART" --clobber + ls -lah "$ART" + + - name: ๐Ÿ“‚ Extract + install + shell: bash + env: + TARGET: ${{ matrix.target }} + run: | + set -euo pipefail + ART="beeping-cli-${TARGET}.${{ matrix.archive }}" + if [[ "$ART" == *.zip ]]; then + unzip -q "$ART" + else + tar -xJf "$ART" + fi + ls -lah "beeping-cli-${TARGET}/" + # macOS Gatekeeper quarantine workaround for tarballs + # downloaded via curl/gh (until BEE-1791 lands): + if [ "${RUNNER_OS}" = "macOS" ]; then + xattr -d com.apple.quarantine "beeping-cli-${TARGET}/beeping" 2>/dev/null || true + fi + echo "BIN=$PWD/beeping-cli-${TARGET}/beeping${{ runner.os == 'Windows' && '.exe' || '' }}" >> "$GITHUB_ENV" + + - name: ๐Ÿ”ข --version matches release tag + shell: bash + env: + EXPECTED_VERSION: ${{ needs.resolve.outputs.version }} + run: | + set -euo pipefail + "$BIN" --version + # `beeping --version` emits `beeping `; assert match. + got=$("$BIN" --version | awk '{print $2}') + if [ "$got" != "$EXPECTED_VERSION" ]; then + echo "::error::version mismatch: got '$got' expected '$EXPECTED_VERSION'" + exit 1 + fi + + - name: ๐Ÿฉบ Doctor offline + shell: bash + run: | + "$BIN" doctor --mode offline + + - name: ๐Ÿ” Offline round-trip (skip Windows until BEE-2222) + if: runner.os != 'Windows' + shell: bash + run: | + set -euo pipefail + # Offline-only encode (no live audio output, just write WAV) + # then decode it back. base32 alphabet only โ€” see BEE-1886. + "$BIN" encode "$SMOKE_PAYLOAD" --out /tmp/smoke.wav --mode offline + got=$("$BIN" decode --file /tmp/smoke.wav --mode offline) + echo "decoded: $got" + if ! echo "$got" | grep -qF "$SMOKE_PAYLOAD"; then + echo "::error::round-trip mismatch: decoded payload missing '$SMOKE_PAYLOAD'" + exit 1 + fi + + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # `cargo install beeping-cli` (BEE-151) + # Skipped on pre-release (crates.io publish also skipped per + # release.yml predicate). + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + cargo-install: + name: ๐Ÿ“ฆ cargo install on ${{ matrix.os }} + needs: resolve + if: needs.resolve.outputs.prerelease == 'false' + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - name: ๐Ÿง Install ALSA dev headers (Linux build dep) + if: runner.os == 'Linux' + run: sudo apt-get update -qq && sudo apt-get install -y libasound2-dev pkg-config + + - name: ๐Ÿฆ€ Setup Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: ๐Ÿ“ฆ cargo install beeping-cli + shell: bash + env: + VERSION: ${{ needs.resolve.outputs.version }} + run: cargo install beeping-cli --version "$VERSION" --locked + + - name: ๐Ÿ”ข --version + shell: bash + run: beeping --version + + - name: ๐Ÿฉบ Doctor offline + shell: bash + run: beeping doctor --mode offline + + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Homebrew tap (BEE-151 + BEE-1782 auto-update) + # Skipped on pre-release (tap auto-update also skipped). + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + homebrew-tap: + name: ๐Ÿบ brew on ${{ matrix.os }} + needs: resolve + if: needs.resolve.outputs.prerelease == 'false' + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # macOS arm64 (latest) + intel (macos-15-intel) + Linuxbrew + os: [macos-latest, macos-15-intel, ubuntu-latest] + steps: + - name: ๐Ÿบ brew install beeping-io/tap/beeping-cli + shell: bash + env: + # Homebrew on GH Actions sometimes pre-installs incompatible + # bottles; pass --verbose so failures surface. + HOMEBREW_NO_INSTALL_CLEANUP: "1" + HOMEBREW_NO_AUTO_UPDATE: "1" + run: | + set -euo pipefail + brew tap beeping-io/tap https://github.com/beeping-io/tap + brew install --verbose beeping-io/tap/beeping-cli + + - name: ๐Ÿ”ข --version + run: beeping --version + + - name: ๐Ÿฉบ Doctor offline + run: beeping doctor --mode offline + + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Scoop bucket (BEE-151 + BEE-1783 auto-update) + # Skipped on pre-release (bucket auto-update also skipped). + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + scoop-bucket: + name: ๐Ÿฅ„ scoop on windows-latest + needs: resolve + if: needs.resolve.outputs.prerelease == 'false' + runs-on: windows-latest + steps: + - name: ๐Ÿฅ„ Install Scoop + shell: powershell + run: | + Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + irm https://get.scoop.sh -outfile install-scoop.ps1 + .\install-scoop.ps1 -RunAsAdmin + + - name: ๐Ÿฅ„ scoop install beeping-cli + shell: powershell + run: | + scoop bucket add beeping https://github.com/beeping-io/scoop-bucket + scoop install beeping-cli + + - name: ๐Ÿ”ข --version + shell: powershell + run: beeping --version + + # No `doctor --mode offline` on Windows: BEE-2222 (FFI runtime + # crash) makes any FFI-touching subcommand crash with + # STATUS_ACCESS_VIOLATION on x86_64-pc-windows-msvc. --version + # is enough to prove the install path works. + + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Aggregate summary โ€” always runs, fails if any cell failed. + # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + summary: + name: ๐Ÿ“Š Smoke summary + needs: [resolve, direct-tarball, cargo-install, homebrew-tap, scoop-bucket] + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“Š Compose markdown summary + env: + TAG: ${{ needs.resolve.outputs.tag }} + PRERELEASE: ${{ needs.resolve.outputs.prerelease }} + R_DIRECT: ${{ needs.direct-tarball.result }} + R_CARGO: ${{ needs.cargo-install.result }} + R_BREW: ${{ needs.homebrew-tap.result }} + R_SCOOP: ${{ needs.scoop-bucket.result }} + run: | + set -euo pipefail + mark() { + case "$1" in + success) echo "โœ…" ;; + failure) echo "โŒ" ;; + cancelled) echo "๐Ÿšซ" ;; + skipped) echo "โญ๏ธ" ;; + *) echo "?" ;; + esac + } + { + echo "## ๐Ÿงช Post-release smoke โ€” $TAG" + echo "" + echo "Prerelease: \`$PRERELEASE\` (pre-release tags skip Homebrew + Scoop + crates.io because those channels also skip dispatching for pre-releases โ€” see BEE-1780/1782/1783)." + echo "" + echo "| Channel | Result |" + echo "|---|---|" + echo "| ๐Ÿ“ฆ Direct tarball/zip (5 targets) | $(mark "$R_DIRECT") |" + echo "| ๐Ÿ“ฆ \`cargo install beeping-cli\` (3 OSes) | $(mark "$R_CARGO") |" + echo "| ๐Ÿบ Homebrew tap (3 OSes) | $(mark "$R_BREW") |" + echo "| ๐Ÿฅ„ Scoop bucket (Windows) | $(mark "$R_SCOOP") |" + } >> "$GITHUB_STEP_SUMMARY" + + - name: ๐Ÿšฆ Gate โ€” fail if any active channel failed + env: + R_DIRECT: ${{ needs.direct-tarball.result }} + R_CARGO: ${{ needs.cargo-install.result }} + R_BREW: ${{ needs.homebrew-tap.result }} + R_SCOOP: ${{ needs.scoop-bucket.result }} + run: | + set -euo pipefail + fail=0 + for r in "$R_DIRECT" "$R_CARGO" "$R_BREW" "$R_SCOOP"; do + case "$r" in + success|skipped) ;; + *) fail=1 ;; + esac + done + if [ "$fail" = 1 ]; then + echo "::error::At least one channel smoke failed โ€” see Job Summary" + exit 1 + fi + echo "::notice::All active channels smoked green for ${{ needs.resolve.outputs.tag }}" diff --git a/README.md b/README.md index c181d30..baeaca0 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ ![Rust edition](https://img.shields.io/badge/Rust_edition-2024-CE412B) ![targets](https://img.shields.io/badge/targets-macOS_ยท_Linux_ยท_Windows-2EA44F) [![codecov](https://codecov.io/gh/beeping-io/beeping-cli/branch/develop/graph/badge.svg)](https://codecov.io/gh/beeping-io/beeping-cli) +[![post-release smoke](https://github.com/beeping-io/beeping-cli/actions/workflows/post-release-smoke.yml/badge.svg)](https://github.com/beeping-io/beeping-cli/actions/workflows/post-release-smoke.yml) > ๐Ÿ”Š Official Rust command-line tool for **data over sound** (audible + ultrasonic). > Encode / decode payloads locally via FFI to `beeping-core` (C++20) or remotely diff --git a/docs/installation.md b/docs/installation.md index ddd7789..0362363 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -8,7 +8,11 @@ install`, GitHub Releases tarball) and 5 more are queued (Homebrew core, winget, Chocolatey, AppImage, `.deb`/`.rpm`). Every published release ships with **SHA256 checksums**, **cosign keyless signatures**, **CycloneDX SBOM**, and **SLSA L3 build provenance** so you can verify -authenticity before running anything (BEE-1781). +authenticity before running anything (BEE-1781). Every release is also +exercised end-to-end by the +[post-release smoke matrix](https://github.com/beeping-io/beeping-cli/actions/workflows/post-release-smoke.yml) +(BEE-1786) โ€” install from each channel on its native OS + smoke +`--version` + `doctor` + offline encode/decode round-trip. --- diff --git a/external/README.md b/external/README.md index add8670..cf68baa 100644 --- a/external/README.md +++ b/external/README.md @@ -33,9 +33,9 @@ The plan is: ## What's NOT here yet -- Smoke tests post-release (BEE-1786) +- (all in-repo / cross-repo distribution channels for `beeping-cli` are now wired; remaining BEE-178x scope is external registry submissions and AppImage/`.deb`/`.rpm` packaging) -## What's now present (BEE-1781 + BEE-1782 + BEE-1783 โ€” implemented 2026-05-11 / 2026-05-12) +## What's now present (BEE-1781 + BEE-1782 + BEE-1783 + BEE-1786 โ€” implemented 2026-05-11 / 2026-05-12) - `cosign` keyless signatures (`.sig` + `.pem`) shipped alongside every release artifact. Verification recipe in `docs/supply-chain.md`. @@ -56,6 +56,14 @@ The plan is: That repo's `auto-update.yml` regenerates `bucket/beeping-cli.json` via `scripts/regen-manifest.py` (rewrites `version` + Windows ZIP URL + hash + `extract_dir`) and commits to develop. +- **Post-release smoke matrix** (BEE-1786): + `.github/workflows/post-release-smoke.yml` fires on + `release.published` and exercises every distribution channel on its + native OS (direct tarball/zip ร— 5 targets, `cargo install` ร— 3 OSes, + Homebrew tap ร— 3 OSes, Scoop bucket ร— Windows). Aggregates results + into a Job Summary table; fails CI if any cell fails. Pre-release + tags skip Homebrew + Scoop + crates.io (same predicate as + `notify-*`/`publish-crates`) โ€” only direct-tarball runs. Homebrew + Scoop only check the SHA256 hash (their schema can't encode cosign / SLSA today). The cosign + SLSA layer is opt-in via From d609ac40e2d951e4cb1bbd201c131fa49e1f77d1 Mon Sep 17 00:00:00 2001 From: Alfred Rivas Date: Tue, 12 May 2026 09:39:08 +0200 Subject: [PATCH 10/10] docs(roadmap): BEE-1786 recompute timeline + changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move BEE-1786 from Phase 15 shared scope to beeping-cli specific (+5 SP). Sixth consecutive move of this shape this milestone (BEE-1780/1781/1785/1782/1783/1786) โ€” every task whose implementation lives in this repo has been pulled here. - Phase 15 specific now 67 SP; 62/67 done (93 %), 1 remaining (BEE-2222 โ€” Windows FFI runtime crash). - Append History entry covering the smoke matrix workflow + 6 jobs + e2e CI execution gated on milestone PR merge to develop. - No timeline impact; estimated end stays 2026-05-19. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/ROADMAP.md | 28 ++++++++++++------ docs/ROADMAP_CHANGELOG.md | 60 +++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 910c7d1..6f188a8 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,11 +14,11 @@ | **Estimated end (with 20 % risk margin)** | 2026-05-15 (was 2026-05-30, advanced 15 days; scope-change absorbed into buffer) | | **Initial velocity assumed** | 5 SP / work-day (solo developer, multi-repo context) | | **Risk margin** | 20 % over raw work-day estimate | -| **Total story points scoped to this repo** | 139 SP (Phase 14: 77 ยท Phase 15: 62) | -| **Story points completed** | 134 SP (36 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782 + BEE-1783**) | +| **Total story points scoped to this repo** | 144 SP (Phase 14: 77 ยท Phase 15: 67) | +| **Story points completed** | 139 SP (37 tasks closed, **Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782 + BEE-1783 + BEE-1786**) | | **Story points remaining** | 5 SP (Phase 15: BEE-2222 โ€” 1 task) | -| **Global status** | โœ… On time โ€” Phase 15 in flight (92 % done), Phase 14 done | -| **Last update** | 2026-05-12 โ€” closed BEE-1783 (Scoop bucket auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) | +| **Global status** | โœ… On time โ€” Phase 15 in flight (93 % done), Phase 14 done | +| **Last update** | 2026-05-12 โ€” closed BEE-1786 (post-release smoke matrix across every channel, 5 SP); moved from shared to `beeping-cli`-specific scope (+5 SP to Phase 15 specific) | --- @@ -27,7 +27,7 @@ | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 62 | 2026-05-04 | 2026-05-19 | โณ in flight (57/62 SP done, 92 %) | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope) | 67 | 2026-05-04 | 2026-05-19 | โณ in flight (62/67 SP done, 93 %) | > **Note**: Phase 15 also contains 15 additional tasks (~60 SP) shared with > `beepbox-cli` (the C++ CLI). Those are not counted in this repo's SP total โ€” @@ -83,7 +83,7 @@ else; tests close out the milestone). --- -## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 62 SP) +## ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups (beeping-cli scope, 67 SP) **Goal**: Public installable binaries for `beeping-cli` on 6+ channels with signing, SBOM, and SLSA L3 provenance. Smoke tests validate every channel @@ -118,8 +118,9 @@ ecosystem level. | 13 | [BEE-1785](https://linear.app/me8/issue/BEE-1785) โ€” ๐Ÿ“š Install section in README + `docs/installation.md` polish | 2 | โœ… **Done** 2026-05-11 (per-OS one-liners + supply-chain verify recipe + Gatekeeper/SmartScreen workarounds + BEE-2222 caveat + troubleshooting matrix) | | 14 | [BEE-1782](https://linear.app/me8/issue/BEE-1782) โ€” ๐Ÿบ Homebrew tap auto-update on release | 3 | โœ… **Done** 2026-05-12 (release.yml dispatches โ†’ tap's auto-update.yml regenerates formula via regen-formula.py + commits to develop; e2e verified on v0.0.0-test4) | | 15 | [BEE-1783](https://linear.app/me8/issue/BEE-1783) โ€” ๐Ÿฅ„ Scoop bucket auto-update on release | 3 | โœ… **Done** 2026-05-12 (symmetric to BEE-1782 retargeted at JSON manifest schema; e2e verified on v0.0.0-test5) | -| 16 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | -| | **Total** | **62** | 57 done ยท 5 remaining | +| 16 | [BEE-1786](https://linear.app/me8/issue/BEE-1786) โ€” ๐Ÿงช Post-release smoke matrix across every distribution channel | 5 | โœ… **Done** 2026-05-12 (workflow fires on release.published + workflow_dispatch; 4 channels ร— native OS runners + aggregated summary; e2e exec gated on first stable release post-merge) | +| 17 | [BEE-2222](https://linear.app/me8/issue/BEE-2222) โ€” ๐ŸชŸ Windows FFI runtime crash investigation (BEE-1897 follow-up) | 5 | Backlog | +| | **Total** | **67** | 62 done ยท 5 remaining | ### Phase 15 shared scope (NOT counted here) @@ -129,7 +130,7 @@ that runs from `beepbox`'s side. They're not included in this repo's SP total to avoid double-counting: BEE-1778 (ADR), BEE-1779 (CI release matrix), -BEE-1784 (AppImage), BEE-1786 (smoke tests), +BEE-1784 (AppImage), BEE-1787 (winget), BEE-1788 (Chocolatey), BEE-1789 (Homebrew core), BEE-1790 (.deb + .rpm Cloudsmith), BEE-1791 (Apple Developer ID, pending budget), BEE-1792 (Authenticode, pending budget). @@ -167,6 +168,15 @@ budget), BEE-1792 (Authenticode, pending budget). > โ€” moved to the specific table on 2026-05-12 when it closed (+3 SP > to Phase 15 specific). Fifth consecutive sharedโ†’specific move this > milestone after BEE-1780/1781/1785/1782. +> +> Note: BEE-1786 (post-release smoke matrix) was originally listed +> here under the shared scope. The `beeping-cli` implementation lives +> entirely in this repo's `.github/workflows/post-release-smoke.yml` +> โ€” moved to the specific table on 2026-05-12 when it closed (+5 SP +> to Phase 15 specific). Sixth consecutive sharedโ†’specific move this +> milestone (BEE-1780/1781/1785/1782/1783/1786). The pattern is now +> firmly established: when a task's implementation lives in this +> repo, it counts here regardless of how the task title is worded. --- diff --git a/docs/ROADMAP_CHANGELOG.md b/docs/ROADMAP_CHANGELOG.md index eebaeb8..8fb9b0d 100644 --- a/docs/ROADMAP_CHANGELOG.md +++ b/docs/ROADMAP_CHANGELOG.md @@ -15,21 +15,71 @@ - **Project start**: 2026-04-28 - **Estimated end (with 20 % margin)**: 2026-05-19 (unchanged; within velocity) - **Velocity assumed**: 5 story points / work-day (actual sustained ~6 SP / work-day) -- **Total SP scoped to this repo**: 139 (Phase 14: 77 ยท Phase 15: 62) -- **SP completed**: 134 (36 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782 + BEE-1783) +- **Total SP scoped to this repo**: 144 (Phase 14: 77 ยท Phase 15: 67) +- **SP completed**: 139 (37 tasks closed, Phase 14 + BEE-150 + BEE-152 + BEE-151 + BEE-1780 + BEE-1897 + BEE-1883 + BEE-1886 + BEE-1887 + BEE-1885 + BEE-1884 + BEE-1888 + BEE-1781 + BEE-1785 + BEE-1782 + BEE-1783 + BEE-1786) - **SP remaining**: 5 (Phase 15: BEE-2222 = 1 task) -- **Global status**: โœ… On time โ€” Phase 15 in flight (57/62 SP done, 92 %) -- **Last update**: 2026-05-12 โ€” closed BEE-1783 (Scoop bucket auto-update on release, 3 SP); moved from shared to `beeping-cli`-specific scope (+3 SP to Phase 15 specific) +- **Global status**: โœ… On time โ€” Phase 15 in flight (62/67 SP done, 93 %) +- **Last update**: 2026-05-12 โ€” closed BEE-1786 (post-release smoke matrix across every channel, 5 SP); moved from shared to `beeping-cli`-specific scope (+5 SP to Phase 15 specific) | # | Milestone | SP | Est. start | Est. end | Status | |---|---|---|---|---|---| | 14 | ๐Ÿฆ€ Phase 14 โ€” beeping-cli (Rust) + dual-mode | 77 | 2026-04-28 | 2026-05-04 | โœ… done | -| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 62 | 2026-05-04 | 2026-05-19 | โณ in flight | +| 15 | ๐Ÿ“ฆ Phase 15 โ€” CLI distribution + Phase-14 follow-ups | 67 | 2026-05-04 | 2026-05-19 | โณ in flight | --- ## ๐Ÿ“œ History +### [2026-05-12] โ€” Closed BEE-1786 (5 SP, post-release smoke matrix across every distribution channel) + scope clarification + +**Trigger**: closure of BEE-1786, plus a 6th consecutive _Scope clarification_ entry this milestone (BEE-1780 โ†’ 1781 โ†’ 1785 โ†’ 1782 โ†’ 1783 โ†’ 1786). The implementation for `beeping-cli` lives entirely in this repo's `.github/workflows/post-release-smoke.yml`. Moves to the `beeping-cli`-specific table (+5 SP to Phase 15 specific). The remaining Phase 15 shared scope list is now down to 9 entries from the original 14 โ€” every task whose implementation actually lived in this repo has moved here. + +**Delivered**: + +- **`.github/workflows/post-release-smoke.yml`** โ€” fires on `release.published` + manual `workflow_dispatch` with `tag` input. Six jobs: + - `resolve` โ€” derives tag/version/prerelease boolean (same `contains('-')` heuristic as `release.yml`). + - `direct-tarball` โ€” matrix across all 5 release targets (macOS arm64 on `macos-latest`, macOS intel on `macos-15-intel`, Linux amd64 on `ubuntu-latest`, Linux arm64 on `ubuntu-24.04-arm`, Windows x86_64 on `windows-latest`). Download โ†’ extract โ†’ `--version` matches tag โ†’ `doctor --mode offline` โ†’ offline encodeโ†’WAVโ†’decode round-trip. Linux installs `libasound2` runtime (BEE-1888 lesson); macOS strips Gatekeeper quarantine xattr (BEE-1791 not yet); Windows skips round-trip per BEE-2222. + - `cargo-install` โ€” matrix across ubuntu/macos/windows. `cargo install beeping-cli --version $VERSION --locked` + smoke. Skipped on pre-release (matches `publish-crates`). + - `homebrew-tap` โ€” matrix across macos-latest (arm64) + macos-15-intel + ubuntu-latest (Linuxbrew). `brew tap` + `brew install --verbose` + smoke. Skipped on pre-release. + - `scoop-bucket` โ€” `windows-latest`. Install Scoop โ†’ add bucket โ†’ install โ†’ `--version`. Skipped on pre-release. + - `summary` โ€” always runs (`!cancelled()`). Reads `needs.*.result`, emits a markdown table to `$GITHUB_STEP_SUMMARY` mapping channel โ†’ โœ…/โŒ/โญ๏ธ/๐Ÿšซ, fails the workflow if any active channel failed. Skipped channels (pre-release) don't fail. +- **Doc updates** โ€” README gains the smoke workflow badge; docs/installation.md links the smoke matrix as the per-release end-to-end gate; external/README.md moves BEE-1786 to "What's now present" and notes the "NOT here yet" list is now empty for `beeping-cli`-scope work. + +**Tests**: + +- `actionlint .github/workflows/post-release-smoke.yml` clean. +- `markdownlint` on touched files clean. +- Workflow structure inspected: matrix sizes + OS labels match release.yml; pre-release gating matches `notify-tap`/`notify-scoop`/`publish-crates`; Linux ALSA prereq matches BEE-1888; Windows skip matches BEE-2222. +- Release pipeline ran on `v0.0.0-test6` (run [25719917164](https://github.com/beeping-io/beeping-cli/actions/runs/25719917164)) โ€” 23 assets published with full BEE-1780/1781 supply-chain artifacts; `notify-tap` + `notify-scoop` both correctly **skipped** per pre-release predicate. +- **End-to-end smoke matrix execution deferred** โ€” GitHub Actions only registers a workflow's `release.published` + `workflow_dispatch` triggers once the file appears on the default branch (`develop`). Workflow currently lives on `milestone/phase-15` only. Same gating shape as BEE-1782/1783's PAT-gated dispatch tests: structural validation complete, end-to-end CI run defers to first stable release after the milestone PR merges. + +**Net delta global**: 0 days. 5 SP within velocity. + +**New estimated end date**: 2026-05-19 (no change). + +**New global status**: โœ… On time, Phase 15 at 93 % (62/67 SP). + +#### Advanced (negative = earlier) + +- (none โ€” within velocity) + +#### Delayed + +- (none) + +#### Scope changes + +- **Scope clarification**: BEE-1786 (5 SP) moves from Phase 15 shared scope to `beeping-cli`-specific scope. Reason: implementation lives entirely in this repo. Sixth consecutive move of this shape this milestone (BEE-1780/1781/1785/1782/1783/1786). The pattern is now firmly established and exhausted โ€” every task whose implementation lives in this repo has been pulled into the specific table. + +#### Notes + +- Cumulative SP closed: 139 / 144 = 97 % of total scope, 93 % of Phase 15. +- Phase 15 specific scope: 16 tasks done ยท 1 remaining (BEE-2222). +- Phase 15 shared scope is now genuinely shared work (beepbox-cli ADR, AppImage Linux packaging, external registry submissions, paid signing) โ€” none of the remaining items can be unilaterally moved here. +- Next-likely candidates: **BEE-2222** (Windows FFI runtime crash investigation โ€” the only remaining specific task; closes the `continue-on-error: true` workaround on Windows CI and unlocks a fully-green release pipeline) OR **BEE-1784** (AppImage Linux universal โ€” independent packaging work that the smoke matrix can validate end-to-end once it lands). + +--- + ### [2026-05-12] โ€” Closed BEE-1783 (3 SP, Scoop bucket auto-update on release) + scope clarification **Trigger**: closure of BEE-1783, plus a 5th _Scope clarification_ entry this milestone (BEE-1780 โ†’ 1781 โ†’ 1785 โ†’ 1782 โ†’ 1783 โ€” five consecutive sharedโ†’specific moves). Symmetric mirror of BEE-1782 retargeted from Homebrew tap โ†’ Scoop bucket, Ruby formula โ†’ JSON manifest.