Merge pull request #1651 from DeusData/fix/checksums-and-license-gate

fix(release,ci): cover ui-* aliases in checksums.txt, and stop the licence gate depending on a live fetch
This commit is contained in:
Martin Vogel authored and GitHub committed 2026-08-15 10:45:39 +02:00
commit 77195634e1
3 files changed
+84 -5

No files matched your search

+8
View File
@@ -164,6 +164,14 @@ jobs:
release-selection.tsv \
> checksums.txt
# The legacy ui-* aliases are byte-identical copies published after verify
# (scripts/ci/publish-legacy-aliases.sh), so they were absent from
# checksums.txt and 0.9.x updaters refused to install them (#1134). Their
# digests are added here, BEFORE attestation, so the attested artifact
# covers both names.
- name: Cover legacy ui-* aliases in checksums
run: scripts/ci/append-legacy-alias-checksums.sh checksums.txt
- name: Attest checksum provenance
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
+17 -5
View File
@@ -10,6 +10,7 @@ Verdicts:
ERROR upstream fetch failed
"""
import base64
import hashlib
import json
import os
import re
@@ -159,13 +160,24 @@ def main():
check_upstream(rel, os.path.join(ROOT, rel), repo, exact_path=exact)
# Special: nomic = canonical Apache-2.0 text; sqlite3 = first-party notice
#
# This used to `curl` https://www.apache.org/licenses/LICENSE-2.0.txt at
# gate time and byte-compare. A gating verdict must not depend on a live
# HTTP request: any fetch failure yielded an empty string, compared unequal,
# and reported DIFFERS -- indistinguishable from a real licence change. That
# is what reddened `security / license-gate` on PR #1337 for over two weeks,
# on a branch touching three CLI files and no licence at all.
#
# The canonical Apache-2.0 text is immutable and versioned, so it is pinned
# by digest instead. Verified byte-identical to the upstream text at the time
# of pinning (11358 bytes). A mismatch now means our vendored copy changed --
# which is exactly, and only, what this audit is meant to detect.
APACHE_2_0_SHA256 = "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"
fname, ours = local_license(os.path.join(ROOT, "vendored/nomic"))
apache = subprocess.run(
["curl", "-fsSL", "https://www.apache.org/licenses/LICENSE-2.0.txt"],
capture_output=True, text=True).stdout
ours_digest = hashlib.sha256(ours.encode("utf-8")).hexdigest() if ours is not None else None
results["vendored/nomic"] = (
"IDENTICAL" if ours == apache else "DIFFERS",
"apache.org canonical LICENSE-2.0.txt")
"IDENTICAL" if ours_digest == APACHE_2_0_SHA256 else "DIFFERS",
"canonical Apache-2.0 text, pinned by sha256")
results["vendored/sqlite3"] = ("FIRST-PARTY-NOTICE",
"own public-domain notice (sqlite has no upstream LICENSE)")
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# Add the legacy ui-* names to checksums.txt, carrying the canonical digest.
#
# publish-legacy-aliases.sh publishes byte-identical ui-*-named copies of the
# release archives so already-released 0.9.x updaters stop 404ing (#1538). It
# runs after verify, so those copies inherit the hash-bound VirusTotal verdicts
# — and it therefore left them out of checksums.txt entirely, on the reasoning
# that the file "covers the canonical names current installers request".
#
# That reasoning has a hole. The aliases exist ONLY for 0.9.x updaters, and
# those verify the NAME they asked for. So the alias fixed the 404 and moved the
# failure one step later: the updater downloads the archive, cannot find its name
# in checksums.txt, and refuses to install it (#1134):
#
# warning: codebase-memory-mcp-ui-darwin-arm64.tar.gz not found in checksums.txt
# error: refusing to install an unverified download
#
# An alias is a copy, so its sha256 is by construction the digest already
# computed for the canonical archive. Emitting that digest under the legacy name
# introduces no new bytes and no new scan surface. This runs BEFORE the
# attestation step so the attested artifact covers both names.
#
# The alias rule MUST stay in step with publish-legacy-aliases.sh: .tar.gz and
# .zip only, never an already-ui-* name. A name here with no published asset is
# as broken as an asset with no name, so this fails closed when it matches
# nothing.
#
# Usage: append-legacy-alias-checksums.sh <checksums-file>
set -euo pipefail
CHECKSUMS="${1:?usage: append-legacy-alias-checksums.sh <checksums-file>}"
if [ ! -s "$CHECKSUMS" ]; then
echo "error: $CHECKSUMS is missing or empty" >&2
exit 1
fi
aliases="$(mktemp)"
trap 'rm -f "$aliases"' EXIT
awk '
$2 ~ /^codebase-memory-mcp-/ &&
$2 !~ /^codebase-memory-mcp-ui-/ &&
($2 ~ /\.tar\.gz$/ || $2 ~ /\.zip$/) {
alias = $2
sub(/^codebase-memory-mcp-/, "codebase-memory-mcp-ui-", alias)
print $1 " " alias
}
' "$CHECKSUMS" > "$aliases"
if [ ! -s "$aliases" ]; then
echo "error: no canonical archives matched the ui-* alias rule in $CHECKSUMS;" >&2
echo " publish-legacy-aliases.sh would then publish assets that" >&2
echo " checksums.txt does not cover (#1134)." >&2
exit 1
fi
cat "$aliases" >> "$CHECKSUMS"
echo "added $(wc -l < "$aliases" | tr -d ' ') legacy alias checksum line(s); $CHECKSUMS now covers $(wc -l < "$CHECKSUMS" | tr -d ' ') names"