diff --git a/VERSION b/VERSION index a4c853ea2..50035d832 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.4.2 +6.4.3-rc.1 diff --git a/deploy/helm/pulse/Chart.yaml b/deploy/helm/pulse/Chart.yaml index 95d84e26e..af9e6ceed 100644 --- a/deploy/helm/pulse/Chart.yaml +++ b/deploy/helm/pulse/Chart.yaml @@ -2,9 +2,9 @@ apiVersion: v2 name: pulse description: Helm chart for deploying the Pulse hub and optional Docker, Kubernetes, or OpenShift monitoring agent. type: application -version: 6.4.2 -appVersion: "6.4.2" -icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.4.2/docs/images/pulse-logo.svg +version: 6.4.3-rc.1 +appVersion: "6.4.3-rc.1" +icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.4.3-rc.1/docs/images/pulse-logo.svg keywords: - monitoring - proxmox @@ -32,7 +32,7 @@ annotations: description: Smoke tests with kind cluster deployment artifacthub.io/links: | - name: Documentation - url: https://github.com/rcourtman/Pulse/blob/v6.4.2/docs/KUBERNETES.md + url: https://github.com/rcourtman/Pulse/blob/v6.4.3-rc.1/docs/KUBERNETES.md - name: Support url: https://github.com/rcourtman/Pulse/discussions artifacthub.io/maintainers: | diff --git a/deploy/helm/pulse/README.md b/deploy/helm/pulse/README.md index 6191c03bc..fa85bdcdf 100644 --- a/deploy/helm/pulse/README.md +++ b/deploy/helm/pulse/README.md @@ -1,6 +1,6 @@ # pulse -![Version: 6.4.2](https://img.shields.io/badge/Version-6.4.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.4.2](https://img.shields.io/badge/AppVersion-6.4.2-informational?style=flat-square) +![Version: 6.4.3-rc.1](https://img.shields.io/badge/Version-6.4.3--rc.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.4.3-rc.1](https://img.shields.io/badge/AppVersion-6.4.3--rc.1-informational?style=flat-square) Helm chart for deploying the Pulse hub and optional Docker, Kubernetes, or OpenShift monitoring agent. diff --git a/docker-compose.yml b/docker-compose.yml index 82068da8b..7b9484164 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: pulse: - image: ${PULSE_IMAGE:-rcourtman/pulse:6.4.2} + image: ${PULSE_IMAGE:-rcourtman/pulse:6.4.3-rc.1} container_name: pulse restart: unless-stopped logging: diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index 450fb505b..d53446766 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -6,18 +6,22 @@ Pulse release notes live on GitHub: For historical v4 notes that previously lived in this repo, see: `docs/releases/RELEASE_NOTES_v4.md` -For the current stable v6 packet, see: -- `docs/releases/RELEASE_NOTES_v6.4.2.md` -- `docs/releases/V6_CHANGELOG_v6.4.2.md` +For the current v6 release candidate packet, see: +- `docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md` +- `docs/releases/V6_CHANGELOG_v6.4.3-rc.1.md` -For the preceding stable v6 packet, see: +For the current stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.4.1.md` - `docs/releases/V6_CHANGELOG_v6.4.1.md` -For the earlier stable v6 packet, see: +For the preceding stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.4.0.md` - `docs/releases/V6_CHANGELOG_v6.4.0.md` +The `v6.4.2` packet was tagged but never published; its changes ship through the v6.4.3 candidate line: +- `docs/releases/RELEASE_NOTES_v6.4.2.md` +- `docs/releases/V6_CHANGELOG_v6.4.2.md` + For the earlier stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.3.2.md` - `docs/releases/V6_CHANGELOG_v6.3.2.md` diff --git a/docs/UPGRADE_v6.md b/docs/UPGRADE_v6.md index 89bf62ce4..7000f87f6 100644 --- a/docs/UPGRADE_v6.md +++ b/docs/UPGRADE_v6.md @@ -2,21 +2,26 @@ This guide covers practical upgrade steps for existing Pulse installs moving to v6. +For the current v6 release candidate packet, see: + +- `docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md` +- `docs/releases/V6_CHANGELOG_v6.4.3-rc.1.md` + For the current stable v6 packet, see: -- `docs/releases/RELEASE_NOTES_v6.4.2.md` -- `docs/releases/V6_CHANGELOG_v6.4.2.md` - -For the preceding stable v6 packet, see: - - `docs/releases/RELEASE_NOTES_v6.4.1.md` - `docs/releases/V6_CHANGELOG_v6.4.1.md` -For the earlier stable v6 packet, see: +For the preceding stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.4.0.md` - `docs/releases/V6_CHANGELOG_v6.4.0.md` +The `v6.4.2` packet was tagged but never published; its changes ship through the v6.4.3 candidate line: + +- `docs/releases/RELEASE_NOTES_v6.4.2.md` +- `docs/releases/V6_CHANGELOG_v6.4.2.md` + For the earlier stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.3.2.md` diff --git a/docs/release-control/v6/internal/subsystems/deployment-installability.md b/docs/release-control/v6/internal/subsystems/deployment-installability.md index b0febfc25..3fbaa522f 100644 --- a/docs/release-control/v6/internal/subsystems/deployment-installability.md +++ b/docs/release-control/v6/internal/subsystems/deployment-installability.md @@ -2497,7 +2497,29 @@ version. It opened the `v6.4.0` candidate line from `main` with `rollback_version=v6.3.1` and did not move stable/latest install pointers or stable semver aliases. -The active stable `v6.4.2` cut sets the repo-root `VERSION`, repo-root +The active prerelease `v6.4.3-rc.1` cut sets the repo-root `VERSION`, repo-root +`docker-compose.yml` image default, `scripts/install-docker.sh` fallback, and +Helm chart release metadata to the same `6.4.3-rc.1` release version. It follows +stable `v6.4.1` and opens the published `v6.4.3` candidate line. It opens that +line from `main` after the `v6.4.2` tag was staged on 2026-08-31 but never +activated publicly: the private Pro build failed its +compiler memory gate and the release commit verdict failed, so the latest +published stable remains `v6.4.1`. This prerelease keeps +`rollback_version=v6.4.1`, publishes a versioned public GitHub prerelease plus +versioned Docker and Helm artifacts, and does not move stable/latest install +pointers or stable semver aliases. The candidate carries the complete unpublished +`v6.4.2` change set plus the corrections landed after that tag, including the +stale PBS Backup Running state (#1815), the Windows Unified Agent auto-update +404 (#1820), and shared-token same-hostname agent identity collapse (#1753). No +governed mobile-facing path changed from `v6.4.1`, so the release decision is +`no-mobile-impact`; published Pulse Mobile builds remain compatible and no +companion upload or public mobile-store rollout is part of this candidate. The +prerelease Windows path retains exact-SHA, checksum, and detached-signature +verification without Authenticode. Stable `v6.4.3` also skips SignPath under the +standing unavailable policy from `v6.3.2` onward, with public Unknown Publisher +disclosure and the existing signed integrity controls. + +The tagged but unpublished `v6.4.2` cut set the repo-root `VERSION`, repo-root `docker-compose.yml` image default, `scripts/install-docker.sh` fallback, and Helm chart release metadata to the same `6.4.2` release version. This patch release uses the stable hotfix path with `rollback_version=v6.4.1`, @@ -2950,9 +2972,10 @@ For the active stable `v6.1.2` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `6.1.2` whenever the governed `VERSION` is that stable cut. The stable promotion guard remains in force and rejects leftover `-rc.` defaults. -For the active stable `v6.4.2` cut, the repo-root compose default and -`scripts/install-docker.sh` fallback must both pin `6.4.2` until the next -governed release moves them forward. The stable promotion guard remains in +For the active prerelease `v6.4.3-rc.1` cut, the repo-root compose default and +`scripts/install-docker.sh` fallback must both pin `6.4.3-rc.1` until the next +governed stable cut moves them forward. The tagged but unpublished `v6.4.2` +cut pinned `6.4.2` until this candidate moved them forward. The stable promotion guard remains in force and rejects leftover `-rc.` defaults. Each new release moves these two pins together with the repo-root `VERSION` and the Helm chart metadata in the same commit; a cut that leaves any of the four on a superseded value is a diff --git a/docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md b/docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md new file mode 100644 index 000000000..6ce50b2ac --- /dev/null +++ b/docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md @@ -0,0 +1,26 @@ +# Pulse v6.4.3-rc.1 Release Notes + +This preview makes large and mixed estates more dependable, with stronger resource identity, safer agent operations, faster recovery from slow starts, clearer workflows, and broader accessibility support. + +## What's improved + +- **Same-name systems stay separate** - Stronger host, Docker, Kubernetes, and Proxmox identity checks reduce incorrect merges and keep alerts, metrics, actions, and removal tied to the right machine. +- **Agent lifecycle operations are safer** - Linux installs protect tokens under sudo, offline recovery verifies signed installers, shared credentials survive partial removal, and uninstall waits for confirmed server removal. +- **Windows agent delivery is restored** - Unified Agent downloads now resolve canonical signed `.exe` assets and signature sidecars, preventing asset lookup failures during installation and updates. +- **Large Availability estates scan faster** - Estates with 20 or more checks open in fleet view, while table and fleet choices remain stable across refreshes and shareable URLs. +- **Slow starts are recoverable** - Pulse shows connection status and a retry after delayed app startup, while large alert histories catch up incrementally in the background after server restarts. +- **Alert workflows stay focused** - Patrol opens findings for the affected resource, snooze blocks duplicate submissions, incident recovery is clearer, and delivery warnings link to detailed activity. +- **Navigation is more accessible** - Menus, dialogs, charts, toasts, filters, thresholds, and compact controls improve keyboard, screen-reader, focus, mobile, and reduced-motion support. +- **Health APIs are consistent** - Resource APIs provide canonical health verdicts and a bounded fleet summary, while missing or stale telemetry can no longer appear healthy. +- **Disk I/O totals are more accurate** - Partitions of NVMe, MMC, MD, persistent-memory, and ZFS volume devices no longer inflate whole-device traffic. +- **Privileged actions fail more safely** - Linux package and Proxmox operations run in bounded units, abandoned requests are cancelled, and uncertain outcomes are not reported as successful. +- **Oversized responses are contained** - Pulse applies response limits across agents, Proxmox, discovery, updates, remote configuration, AI providers, and other integrations to reduce memory pressure. + +## Before you upgrade + +- This candidate carries every change from the `v6.4.2` packet, which was tagged on 2026-08-31 but never published. If you run `v6.4.1`, read the `v6.4.2` notes for the administrator-boundary changes as well. +- On an SSO-only deployment, map at least one trusted IdP group to the built-in `admin` role before upgrading so an intended administrator retains access. +- If the least-privilege agent monitors rootless Docker or Podman, ensure the collector account exposes exactly one local, collector-owned runtime socket. Ambiguous or invalid sockets may fall back to summary-only monitoring. +- Windows Unified Agent binaries are not Authenticode-signed while SignPath remains unavailable and may show an Unknown Publisher warning. Verify downloads with the published checksums and detached signatures. +- Pulse Mobile remains compatible. This candidate does not require a companion mobile release. +- The rollback target is stable `v6.4.1`. On systemd and Proxmox LXC installs, use `sudo /bin/update --version v6.4.1` to return to the previous stable release. diff --git a/docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md.visuals.json b/docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md.visuals.json new file mode 100644 index 000000000..611074972 --- /dev/null +++ b/docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md.visuals.json @@ -0,0 +1,5 @@ +{ + "schema_version": 1, + "decision": "The release owner declined the model-selected visual plan. The single proposed Patrol before/after capture depends on mock mode holding an attention item and an active finding for the same resource at capture time, which is not a deterministic static UI comparison, so this candidate publishes no screenshots.", + "captures": [] +} diff --git a/docs/releases/V6_CHANGELOG_v6.4.3-rc.1.md b/docs/releases/V6_CHANGELOG_v6.4.3-rc.1.md new file mode 100644 index 000000000..0b40cbb6e --- /dev/null +++ b/docs/releases/V6_CHANGELOG_v6.4.3-rc.1.md @@ -0,0 +1,105 @@ +# Pulse v6.4.3-rc.1 + +This changelog describes the changes since `v6.4.1`, the latest published +stable release. The `v6.4.2` tag was staged on 2026-08-31 but never activated +as a public release, so this candidate carries the complete `v6.4.2` change +set recorded in `V6_CHANGELOG_v6.4.2.md` plus the corrections that landed on +`main` after that tag. + +## Carried from the unpublished v6.4.2 packet + +- Infrastructure actions and administrator routes honor the canonical + administrator boundary for browser, proxy, and SSO sessions, SAML allowlists + fail closed without an email claim, and security-sensitive setup request + bodies are bounded. +- Failed backups and completed PBS-to-PBS sync copies no longer pin a guest in + Backup Running, and incomplete artifacts are excluded from recoverable + latest-backup pointers (#1815). +- Retained delivery failures can be retried or dismissed from the Alerts + overview, Assistant command help behaves as a complete dialog, systemd + services preserve native journal priorities, and durable Proxmox identity + recovery keeps same-name estates distinct after restart. +- Infrastructure settings name uncovered Proxmox cluster nodes, Agent Doctor + reports privilege-helper degradation, TrueNAS API-key connections identify + their owner, and configuration forms expose programmatic labels. + +## Fixed + +- Two standalone sites that reuse one short node name and one shared install + token no longer collapse into a single host or Docker record, and removing + such a record no longer revokes the shared token for every surviving agent + (#1753). +- Windows Unified Agent auto-update no longer fails with HTTP 404 after + upgrading the server: the update endpoint serves the signed `.exe` and its + detached signatures from the canonical release assets, and the server image + carries the extensionless compatibility aliases for them (#1820). +- Same-name standalone Proxmox connections keep their own node labels and + agent links after an agent merges into the site, and Proxmox agent links stay + within their provider scope. +- Kubernetes hosts link through node identity, and ambiguous enrichment that + could attach a node to the wrong host is rejected. +- Disk I/O collection skips numbered partitions of whole devices whose names + end in a digit, so MMC, MD, and persistent block devices no longer double + count partition traffic. +- Health evaluation reports `unknown` with a `telemetry_missing` reason instead + of green when health telemetry is absent. +- Alert lifecycle replay is bounded by a durable projection watermark, so a + large event log no longer stalls startup with repeated full replays. +- Uninstalling the Unified Agent removes the safe-profile and privileged-helper + state it created, and full uninstall preserves shared agent credentials that + other machines still use. +- Oversized agent reports are classified with an explicit payload-size reason + instead of an opaque decode failure. + +## Changed + +- Machines > Availability defaults estates with 20 or more checks to the + compact fleet view, and the chosen table or fleet presentation stays stable + across refreshes and shareable through the URL. +- The Alerts overview keeps delivery warnings concise and offers a refresh + action beside retry and dismiss. +- A slow application bootstrap shows a recoverable status after ten seconds + instead of a blank page. +- Platform pages announce filter result counts, help and infrastructure dialogs + are keyboard accessible and named from visible context, resource action menus + and compact controls meet accessible target sizes, history charts and toasts + are readable by assistive technology, and the product honors reduced-motion + preferences. +- Patrol finding options open as a true disclosure and finding handoffs keep + their context. +- TrueNAS onboarding and troubleshooting guidance matches the JSON-RPC runtime + connection test. + +## Security and release integrity + +- Control-plane, agent-capability, discovery-probe, container-stats, remote + configuration, PDM and updater metadata, AI provider, and Proxmox API + responses are read with explicit size bounds. +- Typed agent actions run in systemd-contained subprocesses, abandoned typed + operations are cancelled, runner activation session authority is fenced, and + helper quarantine and rollback recovery state are hardened. +- Stable installs are continuously verified by a scheduled continuity + workflow, release continuity failures surface with complete actionable + detail, and release activation verifies exact asset bytes. +- Security disclosures route to `security@pulserelay.pro`, and the Go crypto + dependency is updated. + +## Release Metadata + +- Version: `v6.4.3-rc.1` +- Previous candidate: none. This cut opens the `v6.4.3` candidate line +- Previous stable: `v6.4.1` +- Rollback target: `v6.4.1` +- Rollback command: `sudo /bin/update --version v6.4.1` +- Promotion path: exact-SHA single-build release candidate from `main` +- Unpublished predecessor: `v6.4.2` was tagged at `0c76b5d756` on 2026-08-31; + its release pipeline run was cancelled after the private Pro build failed + its compiler memory gate, and no public release, Docker alias, or Helm + chart was activated for it +- Windows signing decision: prereleases publish checksum- and + detached-signature-verified Windows agents without Authenticode while + SignPath remains unavailable. Windows Unified Agent binaries may display an + Unknown Publisher warning +- Mobile decision: `no-mobile-impact`. No governed mobile route, payload, + Relay, pairing, approval, push, or onboarding contract changed from + `v6.4.1`, so no companion mobile build or store rollout is required diff --git a/frontend-modern/public/docs/UPGRADE_v6.md b/frontend-modern/public/docs/UPGRADE_v6.md index 89bf62ce4..7000f87f6 100644 --- a/frontend-modern/public/docs/UPGRADE_v6.md +++ b/frontend-modern/public/docs/UPGRADE_v6.md @@ -2,21 +2,26 @@ This guide covers practical upgrade steps for existing Pulse installs moving to v6. +For the current v6 release candidate packet, see: + +- `docs/releases/RELEASE_NOTES_v6.4.3-rc.1.md` +- `docs/releases/V6_CHANGELOG_v6.4.3-rc.1.md` + For the current stable v6 packet, see: -- `docs/releases/RELEASE_NOTES_v6.4.2.md` -- `docs/releases/V6_CHANGELOG_v6.4.2.md` - -For the preceding stable v6 packet, see: - - `docs/releases/RELEASE_NOTES_v6.4.1.md` - `docs/releases/V6_CHANGELOG_v6.4.1.md` -For the earlier stable v6 packet, see: +For the preceding stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.4.0.md` - `docs/releases/V6_CHANGELOG_v6.4.0.md` +The `v6.4.2` packet was tagged but never published; its changes ship through the v6.4.3 candidate line: + +- `docs/releases/RELEASE_NOTES_v6.4.2.md` +- `docs/releases/V6_CHANGELOG_v6.4.2.md` + For the earlier stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.3.2.md` diff --git a/scripts/install-docker.sh b/scripts/install-docker.sh index 30a75a155..ed73f1acd 100755 --- a/scripts/install-docker.sh +++ b/scripts/install-docker.sh @@ -6,7 +6,7 @@ set -euo pipefail SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" DOCKER_IMAGE_REPO="${DOCKER_IMAGE_REPO:-rcourtman/pulse}" -CANONICAL_DEFAULT_PULSE_VERSION="6.4.2" +CANONICAL_DEFAULT_PULSE_VERSION="6.4.3-rc.1" resolve_default_pulse_version() { if [ -n "${PULSE_IMAGE_VERSION:-}" ]; then diff --git a/scripts/installtests/build_release_assets_test.go b/scripts/installtests/build_release_assets_test.go index 7c1c17b2f..1d8d045d7 100644 --- a/scripts/installtests/build_release_assets_test.go +++ b/scripts/installtests/build_release_assets_test.go @@ -1277,24 +1277,17 @@ func TestCurrentPrereleasePacketTracksInstallMetadata(t *testing.T) { "# Pulse v"+version+" Release Notes", "## What's improved", "## Before you upgrade", - "## Known issues", - "Durable alert lifecycles", - "Better notification control", - "informational events remain distinct from warnings", - "Earlier capacity warnings", - "More accurate host disk health", - "External availability monitoring", - "Clearer infrastructure details", - "phone Settings use a searchable index, sticky section title, compact controls, and full-size touch targets", - "Safer governed actions", - "Safer recovery and watchdog isolation", - "Alert lifecycle failures retain a crash-safe restart snapshot until SQLite is durably repaired", - "external dead-man targets fail closed when any address points to a Pulse host interface", - "View preferences expand inline without covering tables", - "Existing Pulse Mobile iOS build 12 and Android versionCode 9 remain compatible", - "The new `alert_fired` push uses the already-supported `view_alert` action", + "Same-name systems stay separate", + "Windows agent delivery is restored", + "Large Availability estates scan faster", + "Slow starts are recoverable", + "Disk I/O totals are more accurate", + "carries every change from the `v6.4.2` packet", + "map at least one trusted IdP group to the built-in `admin` role", "not Authenticode-signed", "Unknown Publisher warning", + "does not require a companion mobile release", + "The rollback target is stable `v"+previous+"`", ) assertFileDoesNotContain(t, releaseNotesPath, "## Fixes") comparisonSummary := "This changelog describes the changes since `v" + comparisonVersion + "`" @@ -1307,23 +1300,16 @@ func TestCurrentPrereleasePacketTracksInstallMetadata(t *testing.T) { "Rollback target: `v"+previous+"`", "Promotion path: exact-SHA single-build release candidate from `main`", comparisonSummary, - "Rolling-window metric evaluation supports sustained CPU and memory policies", - "Predictive storage-capacity alerts estimate exhaustion risk", - "Per-alert snooze, recurring scoped maintenance, destination severity routing", - "Informational alerts now retain an explicit `info` severity through configuration, persistence, API responses, filtering, notification routing, and display.", - "The append-only event log is the authority for alert history and active lifecycle reconstruction", - "Alert hydration no longer exposes a false all-clear state", - "Docker lifecycle results distinguish command acceptance from independently observed post-action state", - "Alert-lifecycle failures synchronously checkpoint a crash-safe recovery envelope", - "A malformed or source-less degraded-state marker no longer lets startup trust a potentially stale SQLite alert projection", - "Dead-man configuration and dial-time DNS validation reject every address assigned to the Pulse host", - "Remembered table View preferences expand in a responsive inline disclosure", - "Phone Settings use a searchable two-level workspace with a sticky section title", - "Email, ntfy, and mobile push presentation preserve informational priority instead of elevating non-warning events to warning treatment.", + "carries the complete `v6.4.2` change set", + "no longer pin a guest in Backup Running", + "(#1815)", + "no longer collapse into a single host or Docker record", + "(#1753)", + "Windows Unified Agent auto-update no longer fails with HTTP 404", + "(#1820)", "Windows signing decision: prereleases publish checksum- and detached-signature-verified Windows agents without Authenticode", - "Mobile decision: `existing-mobile-build-compatible`", - "Published iOS build 12 and Android versionCode 9 already route `action_type=view_alert`", - "no companion upload is required", + "Mobile decision: `no-mobile-impact`", + "no companion mobile build or store rollout is required", ) if version == "6.3.0-rc.6" { assertFileContainsAllNormalized(t, releaseNotesPath, @@ -1378,8 +1364,8 @@ func TestCurrentPrereleasePacketTracksInstallMetadata(t *testing.T) { "The active prerelease `v"+version+"` cut sets the repo-root `VERSION`, repo-root `docker-compose.yml` image default, `scripts/install-docker.sh` fallback, and Helm chart release metadata to the same `"+version+"` release version.", "This prerelease keeps `rollback_version=v"+previous+"`, publishes a versioned public GitHub prerelease plus versioned Docker and Helm artifacts, and does not move stable/latest install pointers or stable semver aliases.", "For the active prerelease `v"+version+"` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `"+version+"` until the next governed stable cut moves them forward.", - "add the canonical `alert_fired` mobile push type, but preserve the existing `view_alert` navigation action and all route, request/response, pairing, and authorization contracts.", - "Published Pulse Mobile iOS build 12 and Android versionCode 9 already route `action_type=view_alert`, so the server cut is classified `existing-mobile-build-compatible`; no companion upload or public mobile-store rollout is part of this candidate.", + "No governed mobile-facing path changed from `v"+previous+"`, so the release decision is `no-mobile-impact`", + "no companion upload or public mobile-store rollout is part of this candidate.", "The prerelease Windows path retains exact-SHA, checksum, and detached-signature verification without Authenticode. Stable `v"+stableTarget+"` also skips SignPath under the standing unavailable policy", ) } diff --git a/scripts/installtests/install_docker_sh_test.go b/scripts/installtests/install_docker_sh_test.go index 6de9fee82..1a55fb128 100644 --- a/scripts/installtests/install_docker_sh_test.go +++ b/scripts/installtests/install_docker_sh_test.go @@ -41,6 +41,15 @@ func isPrereleaseVersion(version string) bool { return strings.Contains(version, "-") } +// unpublishedStableVersions lists stable versions whose tag and packet exist in +// the repository but which never activated as a public GitHub release. They are +// not valid rollback targets and must not be treated as the previous stable. +var unpublishedStableVersions = map[string]bool{ + // Tagged 2026-08-31; the private Pro build failed its memory gate and the + // release commit verdict failed, so the packet shipped through v6.4.3 instead. + "6.4.2": true, +} + func previousStablePatchVersion(version string) (string, bool) { if isPrereleaseVersion(version) { return "", false @@ -50,10 +59,17 @@ func previousStablePatchVersion(version string) (string, bool) { return "", false } patch, err := strconv.Atoi(parts[2]) - if err != nil || patch <= 0 { + if err != nil { return "", false } - return fmt.Sprintf("%s.%s.%d", parts[0], parts[1], patch-1), true + for patch > 0 { + patch-- + candidate := fmt.Sprintf("%s.%s.%d", parts[0], parts[1], patch) + if !unpublishedStableVersions[candidate] { + return candidate, true + } + } + return "", false } func previousStableForPrereleaseVersion(version string) (string, bool) { @@ -80,7 +96,7 @@ func previousStableForPrereleaseVersion(version string) (string, bool) { filename := filepath.Base(releaseNote) candidate := strings.TrimSuffix(strings.TrimPrefix(filename, "RELEASE_NOTES_v"), ".md") parts, valid := parseStableVersion(candidate) - if !valid || compareStableVersions(parts, baseParts) >= 0 { + if !valid || compareStableVersions(parts, baseParts) >= 0 || unpublishedStableVersions[candidate] { continue } if !found || compareStableVersions(parts, best) > 0 { @@ -397,8 +413,8 @@ func TestInstallDockerProofTracksPrereleaseContract(t *testing.T) { "The active prerelease `v"+version+"` cut sets the repo-root `VERSION`, repo-root `docker-compose.yml` image default, `scripts/install-docker.sh` fallback, and Helm chart release metadata to the same `"+version+"` release version.", comparisonLine, "This prerelease keeps `rollback_version=v"+previous+"`, publishes a versioned public GitHub prerelease plus versioned Docker and Helm artifacts, and does not move stable/latest install pointers or stable semver aliases.", - "add the canonical `alert_fired` mobile push type, but preserve the existing `view_alert` navigation action and all route, request/response, pairing, and authorization contracts.", - "Published Pulse Mobile iOS build 12 and Android versionCode 9 already route `action_type=view_alert`, so the server cut is classified `existing-mobile-build-compatible`; no companion upload or public mobile-store rollout is part of this candidate.", + "No governed mobile-facing path changed from `v"+previous+"`, so the release decision is `no-mobile-impact`", + "no companion upload or public mobile-store rollout is part of this candidate.", "The prerelease Windows path retains exact-SHA, checksum, and detached-signature verification without Authenticode. Stable `v"+stableTarget+"` also skips SignPath under the standing unavailable policy", "For the active prerelease `v"+version+"` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `"+version+"` until the next governed stable cut moves them forward.", ) diff --git a/scripts/release_control/render_release_body_test.py b/scripts/release_control/render_release_body_test.py index a601b93df..a939e5e24 100644 --- a/scripts/release_control/render_release_body_test.py +++ b/scripts/release_control/render_release_body_test.py @@ -39,7 +39,7 @@ class RenderReleaseBodyTest(unittest.TestCase): "SSO access no longer implies administrator access", "Partial Proxmox cluster coverage is visible", "Agent Doctor reports privilege-helper degradation", - "Release workflow checkouts retain their security boundary", + "Privileged workflows stay bound to canonical code", "map at least one trusted IdP group to the built-in `admin` role before upgrading", "The rollback target is stable `v6.4.1`", ):