Merge remote-tracking branch 'origin/main'

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-09-01 21:40:47 +01:00
15 changed files with 244 additions and 69 deletions
+1 -1
View File
@@ -1 +1 @@
6.4.2
6.4.3-rc.1
+4 -4
View File
@@ -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: |
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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:
+9 -5
View File
@@ -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`
+11 -6
View File
@@ -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`
@@ -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
@@ -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.
@@ -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": []
}
+105
View File
@@ -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
+11 -6
View File
@@ -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`
+1 -1
View File
@@ -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
@@ -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",
)
}
+21 -5
View File
@@ -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.",
)
@@ -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`",
):