From 6915b6111d3506d01010b5e27c6c91eb346604ad Mon Sep 17 00:00:00 2001 From: Gnani Rahul Nutakki Date: Tue, 21 Jul 2026 13:37:01 -0500 Subject: [PATCH] fix(desktop): enforce exact Wails tool version Align the desktop CLI gate with the Wails module, reject lookalike or failed version probes, and exercise the policy in the standard script suite. GSTACK-Checkpoint: 2026-07-21/wails-policy#1 Signed-off-by: Gnani Rahul Nutakki --- Makefile | 6 +- hack/verify-wails-version.sh | 36 ++++++++++ sessions/2026-07-21-wails-version-policy.md | 40 +++++++++++ tests/scripts/wails_tooling_policy_test.sh | 79 +++++++++++++++++++++ 4 files changed, 158 insertions(+), 3 deletions(-) create mode 100755 hack/verify-wails-version.sh create mode 100644 sessions/2026-07-21-wails-version-policy.md create mode 100755 tests/scripts/wails_tooling_policy_test.sh diff --git a/Makefile b/Makefile index 0e857f5..a3e3ae5 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ KIND ?= kind HELM ?= helm GORELEASER ?= goreleaser WAILS ?= wails -WAILS_VERSION ?= v2.12.0 +WAILS_VERSION ?= v2.13.0 CODESIGN ?= codesign PLISTBUDDY ?= /usr/libexec/PlistBuddy LIPO ?= lipo @@ -44,8 +44,7 @@ build: ## Build the sith binary into bin/ go build -trimpath -ldflags '$(LDFLAGS)' -o $(BIN_DIR)/$(BINARY) $(CMD) desktop-build: ## Build the ad-hoc-signed macOS arm64 Sith.app development bundle - @command -v "$(WAILS)" >/dev/null || { echo "Wails $(WAILS_VERSION) is required" >&2; exit 1; } - @"$(WAILS)" version | grep -q '$(WAILS_VERSION)' || { echo "Wails $(WAILS_VERSION) is required" >&2; exit 1; } + @hack/verify-wails-version.sh "$(WAILS)" "$(WAILS_VERSION)" cd cmd/sith-desktop && "$(WAILS)" build -clean -m -nosyncgomod -s -trimpath -platform darwin/arm64 @set -euo pipefail; \ app='cmd/sith-desktop/build/bin/Sith.app'; \ @@ -60,6 +59,7 @@ test: ## Run unit tests with the race detector and report coverage go test -race -count=1 -coverprofile=coverage.out ./... test-scripts: ## Run focused safety tests for operator-facing shell harnesses + bash tests/scripts/wails_tooling_policy_test.sh bash tests/scripts/helm_tooling_policy_test.sh bash tests/scripts/m0_ocm_falsification_safety_test.sh bash tests/scripts/release_tag_identity_guide_test.sh diff --git a/hack/verify-wails-version.sh b/hack/verify-wails-version.sh new file mode 100755 index 0000000..d8fcdf2 --- /dev/null +++ b/hack/verify-wails-version.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + +set -Eeuo pipefail + +if [[ "$#" -ne 2 ]]; then + printf 'usage: %s \n' "$0" >&2 + exit 2 +fi + +readonly WAILS_COMMAND="$1" +readonly EXPECTED_VERSION="$2" + +if [[ ! "${EXPECTED_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + printf 'invalid expected Wails version: %s\n' "${EXPECTED_VERSION}" >&2 + exit 2 +fi + +if ! wails_path="$(command -v "${WAILS_COMMAND}")"; then + printf 'Wails %s is required\n' "${EXPECTED_VERSION}" >&2 + exit 1 +fi +readonly wails_path + +if ! version_output="$("${wails_path}" version)"; then + printf 'failed to execute Wails version check\n' >&2 + exit 1 +fi +readonly version_output + +actual_version="${version_output%%$'\n'*}" +readonly actual_version +if [[ "${actual_version}" != "${EXPECTED_VERSION}" ]]; then + printf 'Wails %s is required; got: %s\n' "${EXPECTED_VERSION}" "${actual_version:-}" >&2 + exit 1 +fi diff --git a/sessions/2026-07-21-wails-version-policy.md b/sessions/2026-07-21-wails-version-policy.md new file mode 100644 index 0000000..29f4cfc --- /dev/null +++ b/sessions/2026-07-21-wails-version-policy.md @@ -0,0 +1,40 @@ +# Wails desktop version policy — 2026-07-21 + +## [S] Scope + +The desktop module was already upgraded to Wails v2.13.0, but `make desktop-build` still required +v2.12.0. Its substring check also accepted lookalike version strings. This slice aligns the tool +gate with `go.mod` and makes exact-version enforcement independently testable on every CI runner. + +## [D] Decision + +Treat the `github.com/wailsapp/wails/v2` requirement in `go.mod` as the authoritative compatibility +version. A fail-closed verifier resolves the configured executable, requires a strict `vX.Y.Z` +expected value, executes the version command successfully, and compares its first output line +exactly. Additional informational lines remain compatible; prerelease, vendor, whitespace, empty, +and failed-command variants are rejected. + +## [V] Verification + +- Rebased without conflict onto the exact post-merge `dev` commit + `9e135de08cab047386b0a948311e7443e2741404`, whose CI and CodeQL runs completed successfully. +- The policy test derives both pins and passed 12 assertions covering valid, lookalike, + missing-command, command-failure, and malformed-expectation cases; both scripts pass ShellCheck. +- The checksummed Wails v2.13.0 CLI passes the verifier. The corresponding upstream release is + stable and was published on 2026-07-06: + . +- `go mod verify`, `govulncheck ./...`, and `make ci` pass, including the race detector and all + operator-facing policy tests. +- `make e2e-isolation` passes against PostgreSQL plus 100,000 tenant-boundary fuzz executions. +- `make release-check` passes two independently rebuilt archive/SBOM distributions, Homebrew + formula validation, and the dual-architecture OCI layout contract. +- `make desktop-build` produces a strictly code-sign-valid `com.ardurai.sith` bundle containing a + Mach-O arm64 executable. +- `make e2e-kind KIND=/Volumes/EXTENDED/MacData/tools/bin/kind` passes the fleet fan-out, immutable + OCI image, and Argo application projection contracts in 241.937 seconds. + +## [C] Security, operations, and cost + +Exact matching prevents an unintended prerelease or vendor binary from satisfying the local build +gate. The change adds no runtime dependency, service, permission, network path, storage, or recurring +cloud cost. diff --git a/tests/scripts/wails_tooling_policy_test.sh b/tests/scripts/wails_tooling_policy_test.sh new file mode 100755 index 0000000..bc891ac --- /dev/null +++ b/tests/scripts/wails_tooling_policy_test.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# shellcheck disable=SC2016 + +set -Eeuo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel)" +readonly REPO_ROOT +readonly EXPECTED_VERSION="v2.13.0" +readonly VERIFIER="${REPO_ROOT}/hack/verify-wails-version.sh" + +PASS_COUNT=0 + +pass() { + PASS_COUNT=$((PASS_COUNT + 1)) + printf '[wails-policy] PASS: %s\n' "$1" +} + +assert_equal() { + local actual=$1 + local expected=$2 + local description=$3 + + if [[ "${actual}" != "${expected}" ]]; then + printf '[wails-policy] FAIL: %s = %q, want %q\n' \ + "${description}" "${actual}" "${expected}" >&2 + return 1 + fi + pass "${description}" +} + +expect_failure() { + local description=$1 + shift + if "$@" >/dev/null 2>&1; then + printf '[wails-policy] FAIL: %s\n' "${description}" >&2 + exit 1 + fi + pass "${description}" +} + +makefile_version="$(awk '$1 == "WAILS_VERSION" && $2 == "?=" { print $3 }' "${REPO_ROOT}/Makefile")" +module_version="$(awk '$1 == "github.com/wailsapp/wails/v2" { print $2 }' "${REPO_ROOT}/go.mod")" + +assert_equal "${module_version}" "${EXPECTED_VERSION}" "Wails module is current" +assert_equal "${makefile_version}" "${module_version}" "desktop tool pin matches go.mod" + +scratch="$(mktemp -d)" +readonly scratch +trap 'rm -rf "${scratch}"' EXIT + +fake_wails="${scratch}/wails" +readonly fake_wails +printf '%s\n' \ + '#!/usr/bin/env bash' \ + 'if [[ "${WAILS_FAKE_EXIT:-0}" != "0" ]]; then exit "${WAILS_FAKE_EXIT}"; fi' \ + 'printf "%b" "${WAILS_FAKE_OUTPUT:-}"' >"${fake_wails}" +chmod 0700 "${fake_wails}" + +WAILS_FAKE_OUTPUT=$'v2.13.0\nadditional upstream text\n' \ + "${VERIFIER}" "${fake_wails}" "${EXPECTED_VERSION}" +pass "exact version accepts additional lines after the version" + +for lookalike in 'v2.13.0-rc.1' 'v2.13.00' 'v2.13.0+vendor' ' v2.13.0' ''; do + expect_failure "rejects lookalike version ${lookalike:-}" \ + env WAILS_FAKE_OUTPUT="${lookalike}" "${VERIFIER}" "${fake_wails}" "${EXPECTED_VERSION}" +done + +expect_failure "rejects a failed version command" \ + env WAILS_FAKE_EXIT=1 "${VERIFIER}" "${fake_wails}" "${EXPECTED_VERSION}" +expect_failure "rejects a missing Wails command" \ + "${VERIFIER}" "${scratch}/missing-wails" "${EXPECTED_VERSION}" +expect_failure "rejects a malformed expected version" \ + "${VERIFIER}" "${fake_wails}" 'v2.13' + +grep -Fq 'hack/verify-wails-version.sh "$(WAILS)" "$(WAILS_VERSION)"' "${REPO_ROOT}/Makefile" +pass "desktop build invokes the tested exact-version verifier" + +printf '[wails-policy] %d assertions passed\n' "${PASS_COUNT}"