diff --git a/core/Cargo.lock b/core/Cargo.lock index 694de8f8..e57b7b67 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.5.0" +version = "1.5.0-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index ef7faef5..b599844c 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.5.0" +version = "1.5.0-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/neode-ui/package.json b/neode-ui/package.json index 997cdf25..258ac501 100644 --- a/neode-ui/package.json +++ b/neode-ui/package.json @@ -1,7 +1,7 @@ { "name": "neode-ui", "private": true, - "version": "1.3.5", + "version": "1.5.0-alpha", "type": "module", "scripts": { "start": "./start-dev.sh", diff --git a/releases/manifest.json b/releases/manifest.json index ffef45fe..35344238 100644 --- a/releases/manifest.json +++ b/releases/manifest.json @@ -1,29 +1,31 @@ { - "version": "1.4.0", + "version": "1.5.0-alpha", "release_date": "2026-04-19", "changelog": [ - "FIPS mesh transport integrated (github.com/jmcorgan/fips): preferred over Tor for peer traffic", - "Seed-derived FIPS identity via HKDF label archipelago/fips/secp256k1/v1", - "Federation invites carry an optional fips_npub so peers can reach each other via FIPS", - "Network tab surfaces FIPS daemon version + copyable npub; Home shows FIPS status line", - "WiFi SSID now shown on Network tab when connected (was N/A)" + "FIPS-first transport for federation, messaging, peer linking, and file sharing — Tor stays as automatic fallback", + "Per-service transport preference Settings card (Auto / FIPS / Tor) per node-to-node surface", + "Transport badge (FIPS / TOR / LAN / MESH) on every federated node card, reflecting the transport actually used on the last reach", + "Transitive federation — accepting one peer automatically learns their trusted peers (one hop) so subsequent syncs go over FIPS directly", + "Cancel button for outbound pending peer requests: withdraws locally and notifies the recipient to drop their inbound row", + "Dedicated FIPS peer listener bound to fips0 ULA on port 5679 with a path whitelist (only signed endpoints are reachable from the mesh)", + "Deploy script now writes /opt/archipelago/build-info.txt on every deploy so the UI sidebar version never drifts from the binary again" ], "components": [ { "name": "archipelago", - "current_version": "1.3.5", - "new_version": "1.4.0", - "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.4.0/archipelago", - "sha256": "f42b03622ea47b953f5961a364cdfd1c354f21456dff7ec26594af4150c4976d", - "size_bytes": 37714624 + "current_version": "1.4.0", + "new_version": "1.5.0-alpha", + "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.5.0-alpha/archipelago", + "sha256": "b7527e53b373aba05013b35750f890e5f98c91be542cbe406fa55216cb6a6acc", + "size_bytes": 40020488 }, { - "name": "archipelago-frontend-1.4.0.tar.gz", - "current_version": "1.3.5", - "new_version": "1.4.0", - "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.4.0/archipelago-frontend-1.4.0.tar.gz", - "sha256": "100388985b98ab1adab191a23dd7a197f9a6c45c743da39f9df99d0213880086", - "size_bytes": 76984287 + "name": "archipelago-frontend-1.5.0-alpha.tar.gz", + "current_version": "1.4.0", + "new_version": "1.5.0-alpha", + "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.5.0-alpha/archipelago-frontend-1.5.0-alpha.tar.gz", + "sha256": "83fbacf3b0ba237cd78cc0be798f7d74d8aea5d62110a1eb6ecdc56f77cf505e", + "size_bytes": 53359792 } ] } diff --git a/releases/v1.5.0-alpha/archipelago b/releases/v1.5.0-alpha/archipelago new file mode 100755 index 00000000..b325a39d Binary files /dev/null and b/releases/v1.5.0-alpha/archipelago differ diff --git a/releases/v1.5.0-alpha/archipelago-frontend-1.5.0-alpha.tar.gz b/releases/v1.5.0-alpha/archipelago-frontend-1.5.0-alpha.tar.gz new file mode 100644 index 00000000..4953bab9 Binary files /dev/null and b/releases/v1.5.0-alpha/archipelago-frontend-1.5.0-alpha.tar.gz differ diff --git a/scripts/check-release-manifest.sh b/scripts/check-release-manifest.sh new file mode 100755 index 00000000..d7463def --- /dev/null +++ b/scripts/check-release-manifest.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Validate releases/manifest.json: +# - version matches core/archipelago/Cargo.toml +# - changelog is non-empty (release notes are mandatory per product policy) +# - every component's download_url exists on disk and matches sha256/size +# +# Run on every push from CI, and also locally before publishing a release: +# scripts/check-release-manifest.sh +# +# Exits non-zero on any mismatch so the release process fails loud. + +set -eo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +MANIFEST="$REPO_ROOT/releases/manifest.json" + +if [ ! -f "$MANIFEST" ]; then + echo "❌ releases/manifest.json missing" + exit 1 +fi + +fail() { echo "❌ $*"; exit 1; } +ok() { echo "✅ $*"; } + +MANIFEST_VERSION=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['version'])") +CARGO_VERSION=$(grep '^version' "$REPO_ROOT/core/archipelago/Cargo.toml" | head -1 | sed -E 's/.*"([^"]+)".*/\1/') + +if [ "$MANIFEST_VERSION" != "$CARGO_VERSION" ]; then + fail "manifest version ($MANIFEST_VERSION) ≠ Cargo.toml ($CARGO_VERSION)" +fi +ok "version matches: $MANIFEST_VERSION" + +# Release notes mandatory — ships stuff nobody can read otherwise. +CHANGELOG_COUNT=$(python3 -c "import json; print(len(json.load(open('$MANIFEST'))['changelog']))") +if [ "$CHANGELOG_COUNT" -eq 0 ]; then + fail "changelog is empty — every release MUST have release notes" +fi +ok "changelog has $CHANGELOG_COUNT lines" + +# Each component: the artifact on disk under releases/v/ must match +# the declared sha256 and size_bytes. +VERSION_DIR="$REPO_ROOT/releases/v${MANIFEST_VERSION}" +if [ ! -d "$VERSION_DIR" ]; then + fail "releases/v${MANIFEST_VERSION}/ missing — artifacts not staged" +fi + +COMPONENT_COUNT=$(python3 -c "import json; print(len(json.load(open('$MANIFEST'))['components']))") +for i in $(seq 0 $((COMPONENT_COUNT - 1))); do + NAME=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['components'][$i]['name'])") + DECLARED_SHA=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['components'][$i]['sha256'])") + DECLARED_SIZE=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['components'][$i]['size_bytes'])") + + # Component names other than exactly "archipelago" are the tarball's + # filename; use as-is. The bare "archipelago" component maps to the + # binary file literally named `archipelago`. + FILE="$VERSION_DIR/$NAME" + if [ "$NAME" = "archipelago" ]; then + FILE="$VERSION_DIR/archipelago" + fi + + if [ ! -f "$FILE" ]; then + fail "component '$NAME' file missing at $FILE" + fi + + ACTUAL_SHA=$(sha256sum "$FILE" | awk '{print $1}') + ACTUAL_SIZE=$(stat -c%s "$FILE") + + if [ "$ACTUAL_SHA" != "$DECLARED_SHA" ]; then + fail "component '$NAME' sha256 mismatch (declared=$DECLARED_SHA actual=$ACTUAL_SHA)" + fi + if [ "$ACTUAL_SIZE" != "$DECLARED_SIZE" ]; then + fail "component '$NAME' size mismatch (declared=$DECLARED_SIZE actual=$ACTUAL_SIZE)" + fi + ok "component '$NAME': sha256 + size match on-disk artifact" +done + +echo +ok "releases/manifest.json passes all checks — safe to publish v${MANIFEST_VERSION}" diff --git a/scripts/deploy-to-target.sh b/scripts/deploy-to-target.sh index 2880e280..3ce24086 100755 --- a/scripts/deploy-to-target.sh +++ b/scripts/deploy-to-target.sh @@ -923,6 +923,19 @@ PYEOF } MANIFEST_EOF + # Write build-info.txt — this is what the UI sidebar reads for the + # displayed version (overrides the binary's CARGO_PKG_VERSION). Keeping + # it synced with Cargo.toml on every deploy prevents the 1.3.x drift + # we saw on .198/.253 where stale build-info survived across upgrades. + DEPLOY_PKG_VERSION=$(grep '^version' "$PROJECT_DIR/core/archipelago/Cargo.toml" | head -1 | sed -E 's/.*"([^"]+)".*/\1/') + ssh $SSH_OPTS "$TARGET_HOST" "sudo tee /opt/archipelago/build-info.txt > /dev/null" << BUILDINFO_EOF +version=$DEPLOY_PKG_VERSION +build=$DEPLOY_TS +commit=$DEPLOY_COMMIT +date=$DEPLOY_TS +type=deployed +BUILDINFO_EOF + # Ensure NTP and swap are configured (prevents OOM kills and clock drift) progress "Ensuring NTP + swap" ssh $SSH_OPTS "$TARGET_HOST" '