Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions .github/workflows/supply-chain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,22 @@ jobs:
# the loop by running it ourselves against the real published tarballs
# rather than the local workspace. npm (not pnpm) on purpose: the
# signature audit needs an npm-resolved tree and lockfile.
# bestax-migrate is deliberately absent: its published manifest still
# carries an unresolved `workspace:^` specifier, so `npm install` of it
# fails outright and would mask real signature failures here. Add it back
# once that is fixed.
#
# This step is itself the assertion, not just setup for the audit below:
# `npm install` exits non-zero on an uninstallable package, so the job
# goes red whether the artifact is unsigned or simply broken. That is the
# check #412 did not have — it shipped an uninstallable `workspace:^`
# manifest precisely because everything else in CI resolves against the
# workspace, where the specifier works.
#
# Keep this list in sync with the provenance loop below.
- name: Install published packages into a scratch tree
run: |
mkdir -p "$RUNNER_TEMP/verify"
cd "$RUNNER_TEMP/verify"
npm init -y > /dev/null
npm install --ignore-scripts \
@allxsmith/bestax-bulma create-bestax
@allxsmith/bestax-bulma create-bestax bestax-migrate bestax-mcp

- name: Audit registry signatures and provenance attestations
run: |
Expand All @@ -312,7 +317,27 @@ jobs:
- name: Assert our packages actually carry provenance
run: |
fail=0
for pkg in @allxsmith/bestax-bulma create-bestax; do
cd "$RUNNER_TEMP/verify"
for pkg in @allxsmith/bestax-bulma create-bestax bestax-migrate bestax-mcp; do
# Pin to the version that was actually installed and audited above.
# A bare `npm view "$pkg"` re-resolves the `latest` dist-tag, which
# is mutable, so a publish landing between the install step and this
# one would have this step vouch for a version the job never
# installed. Reading the version back out of the tree keeps all
# three steps talking about the same artifacts. Local read, no
# network, so it belongs outside the retry loop below.
#
# Absent from the tree is its own failure, reported as such rather
# than folded into the "no provenance" message below — a missing
# install and a dropped attestation want different investigations.
version=$(npm ls "$pkg" --depth=0 --json 2>/dev/null \
| jq -r --arg pkg "$pkg" '.dependencies[$pkg].version // empty' 2>/dev/null || true)
if [ -z "$version" ]; then
echo "::error::$pkg is not in the installed tree; cannot verify its provenance"
fail=1
continue
fi

# --json + a type guard so only a real string counts as present:
# null, undefined, [] and non-strings all collapse to empty. The
# array branch covers npm aggregating a bare spec into one element.
Expand All @@ -325,16 +350,16 @@ jobs:
# spend three attempts before believing provenance is really gone.
predicate=""
for attempt in 1 2 3; do
predicate=$(npm view "$pkg" dist.attestations.provenance.predicateType --json 2>/dev/null \
predicate=$(npm view "$pkg@$version" dist.attestations.provenance.predicateType --json 2>/dev/null \
| jq -r 'if type=="array" then .[0] else . end | select(type=="string")' 2>/dev/null || true)
[ -n "$predicate" ] && break
[ "$attempt" -lt 3 ] && sleep $((attempt * 5))
done
if [ -z "$predicate" ]; then
echo "::error::$pkg has NO provenance attestation on the registry"
echo "::error::$pkg@$version has NO provenance attestation on the registry"
fail=1
else
echo "ok: $pkg -> $predicate"
echo "ok: $pkg@$version -> $predicate"
fi
done
exit "$fail"
15 changes: 8 additions & 7 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
## Supported Versions

Security fixes land on the **latest release line only** — currently
`@allxsmith/bestax-bulma` 5.x, `create-bestax` 3.x, and `bestax-migrate` 1.x.
All three packages release automatically from `main` (semantic-release), so the
latest published version is always the patched one. Older majors may still work
but receive no security updates; please upgrade.
`@allxsmith/bestax-bulma` 5.x, `create-bestax` 4.x, `bestax-migrate` 2.x, and
`bestax-mcp` 1.x. All four packages release automatically from `main`
(semantic-release), so the latest published version is always the patched one.
Older majors may still work but receive no security updates; please upgrade.

| Package | Supported | Unsupported |
| ------------------------- | ------------ | ----------- |
| `@allxsmith/bestax-bulma` | 5.x (latest) | < 5.0 |
| `create-bestax` | 3.x (latest) | < 3.0 |
| `bestax-migrate` | 1.x (latest) | — |
| `create-bestax` | 4.x (latest) | < 4.0 |
| `bestax-migrate` | 2.x (latest) | < 2.0 |
| `bestax-mcp` | 1.x (latest) | — |

## Supply-Chain Security

Expand Down Expand Up @@ -42,7 +43,7 @@ Measures active in this repository and its release pipeline:
reviewed lockfile resolves. (The React 18/19 compatibility matrix is the
one deliberate exception: it re-resolves to pin the requested React major
for testing, and never publishes.)
- **npm provenance** — all three published packages set
- **npm provenance** — all four published packages set
`publishConfig.provenance`, so every release carries a signed attestation
linking the tarball to the exact commit and CI run that built it.
- **OIDC trusted publishing** — releases authenticate to npm with
Expand Down
7 changes: 4 additions & 3 deletions docs/docs/guides/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ npm via **OIDC trusted publishing** (short-lived, per-run tokens), so there is
no long-lived npm token that could leak and be used to push a rogue release.

Only the **latest release line** of each package receives security fixes
(currently bestax-bulma 5.x and create-bestax 3.x). Releases are fully
automated from `main` via semantic-release, so the newest published version is
always the patched one — staying current is the supported posture. See
(currently bestax-bulma 5.x, create-bestax 4.x, bestax-migrate 2.x, and
bestax-mcp 1.x). Releases are fully automated from `main` via semantic-release,
so the newest published version is always the patched one — staying current is
the supported posture. See
[SECURITY.md](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) for
the full policy.

Expand Down
Loading