diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 186f270fb..f6662eed2 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -38,12 +38,12 @@ on: required: false type: string unsigned_windows_exception: - description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, or v6.2.1 only: publish Windows agents without Authenticode under a recorded owner exception' + description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, v6.2.1, or v6.3.0 only: publish Windows agents without Authenticode under a recorded owner exception' required: false type: boolean default: false unsigned_windows_reason: - description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, or v6.2.1 only: owner reason for the unsigned Windows exception' + description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, v6.2.1, or v6.3.0 only: owner reason for the unsigned Windows exception' required: false type: string historical_asset_backfill_only: diff --git a/.github/workflows/release-dry-run.yml b/.github/workflows/release-dry-run.yml index 8a4579d3d..c53ad8f92 100644 --- a/.github/workflows/release-dry-run.yml +++ b/.github/workflows/release-dry-run.yml @@ -43,12 +43,12 @@ on: required: false type: string unsigned_windows_exception: - description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, or v6.2.1 only: rehearse Windows agents without Authenticode under a recorded owner exception' + description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, v6.2.1, or v6.3.0 only: rehearse Windows agents without Authenticode under a recorded owner exception' required: false type: boolean default: false unsigned_windows_reason: - description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, or v6.2.1 only: owner reason for the unsigned Windows exception' + description: 'v6.1.0, v6.1.1, v6.1.2, v6.2.0, v6.2.1, or v6.3.0 only: owner reason for the unsigned Windows exception' required: false type: string note: @@ -79,7 +79,7 @@ jobs: with: version: ${{ inputs.version }} require_macos_signing: true - require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1' || inputs.version == '6.1.2' || inputs.version == '6.2.0' || inputs.version == '6.2.1') && inputs.unsigned_windows_exception) }} + require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1' || inputs.version == '6.1.2' || inputs.version == '6.2.0' || inputs.version == '6.2.1' || inputs.version == '6.3.0') && inputs.unsigned_windows_exception) }} windows_signing_backend: signpath dry-run: diff --git a/VERSION b/VERSION index 4efd9a1f4..798e38995 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.3.0-rc.6 +6.3.0 diff --git a/deploy/helm/pulse/Chart.yaml b/deploy/helm/pulse/Chart.yaml index fd82540c0..a891dfaba 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.3.0-rc.6 -appVersion: "6.3.0-rc.6" -icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.3.0-rc.6/docs/images/pulse-logo.svg +version: 6.3.0 +appVersion: "6.3.0" +icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.3.0/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.3.0-rc.6/docs/KUBERNETES.md + url: https://github.com/rcourtman/Pulse/blob/v6.3.0/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 a583b857a..fef8c08af 100644 --- a/deploy/helm/pulse/README.md +++ b/deploy/helm/pulse/README.md @@ -1,6 +1,6 @@ # pulse -![Version: 6.3.0-rc.6](https://img.shields.io/badge/Version-6.3.0--rc.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.3.0-rc.6](https://img.shields.io/badge/AppVersion-6.3.0--rc.6-informational?style=flat-square) +![Version: 6.3.0](https://img.shields.io/badge/Version-6.3.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.3.0](https://img.shields.io/badge/AppVersion-6.3.0-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 6387aadee..38579c63f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: pulse: - image: ${PULSE_IMAGE:-rcourtman/pulse:6.3.0-rc.6} + image: ${PULSE_IMAGE:-rcourtman/pulse:6.3.0} container_name: pulse restart: unless-stopped logging: diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index d1042d3d0..360962c0f 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -6,15 +6,18 @@ 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 v6 release candidate packet -(the current v6 support release candidate packet), see: -- `docs/releases/RELEASE_NOTES_v6.3.0-rc.6.md` -- `docs/releases/V6_CHANGELOG_v6.3.0-rc.6.md` - For the current stable v6 packet, see: +- `docs/releases/RELEASE_NOTES_v6.3.0.md` +- `docs/releases/V6_CHANGELOG_v6.3.0.md` + +For the preceding stable v6 packet, see: - `docs/releases/RELEASE_NOTES_v6.2.1.md` - `docs/releases/V6_CHANGELOG_v6.2.1.md` +For historical v6.3 release candidate packets, see: +- `docs/releases/RELEASE_NOTES_v6.3.0-rc.6.md` +- `docs/releases/V6_CHANGELOG_v6.3.0-rc.6.md` + For earlier stable v6.2 packets, see: - `docs/releases/RELEASE_NOTES_v6.2.0.md` - `docs/releases/V6_CHANGELOG_v6.2.0.md` diff --git a/docs/UPGRADE_v6.md b/docs/UPGRADE_v6.md index 8f074c1e9..9e36b1b17 100644 --- a/docs/UPGRADE_v6.md +++ b/docs/UPGRADE_v6.md @@ -2,16 +2,21 @@ 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.3.0-rc.6.md` -- `docs/releases/V6_CHANGELOG_v6.3.0-rc.6.md` - For the current stable v6 packet, see: +- `docs/releases/RELEASE_NOTES_v6.3.0.md` +- `docs/releases/V6_CHANGELOG_v6.3.0.md` + +For the preceding stable v6 packet, see: + - `docs/releases/RELEASE_NOTES_v6.2.1.md` - `docs/releases/V6_CHANGELOG_v6.2.1.md` +For historical v6.3 release candidate packets, see: + +- `docs/releases/RELEASE_NOTES_v6.3.0-rc.6.md` +- `docs/releases/V6_CHANGELOG_v6.3.0-rc.6.md` + For earlier stable v6.2 packets, see: - `docs/releases/RELEASE_NOTES_v6.2.0.md` diff --git a/docs/release-control/v6/internal/PRE_RELEASE_CHECKLIST.md b/docs/release-control/v6/internal/PRE_RELEASE_CHECKLIST.md index f36146641..cfae3838e 100644 --- a/docs/release-control/v6/internal/PRE_RELEASE_CHECKLIST.md +++ b/docs/release-control/v6/internal/PRE_RELEASE_CHECKLIST.md @@ -40,6 +40,16 @@ Use this as the final gate before cutting a Pulse v6 pre-release. remained pending, the release owner separately approved a v6.2.0-only unsigned-Windows exception with mandatory public disclosure and exact-SHA, checksum, detached-signature, manifest, and published-digest verification. +- The 2026-08-22 v6.3.0 stable-cutoff decision authorizes promotion from + `v6.3.0-rc.6` after the release owner reviewed the aggregate `rc.5` and + `rc.6` production telemetry cohorts and accepted the shortened soak, modest + cohort size, young follow-up window, and bounded post-RC cutoff. The exact + stable SHA still requires the no-publication dry run. +- The release owner separately approved a v6.3.0-only unsigned-Windows + exception because Authenticode signing is not yet available. The Windows + packet must retain exact-SHA, checksum, detached-signature, immutable- + manifest, and published-digest proof and publicly disclose the Unknown + Publisher warning. - `known-rc-issue-closure-for-ga` was introduced on 2026-04-21 to reflect the locked rule that v6 GA must be feature-complete relative to the prerelease issue set. It is currently blocked on the dated RC issue-closure packet. @@ -65,6 +75,14 @@ Use this as the final gate before cutting a Pulse v6 pre-release. accepting the shortened RC11 soak and bind it to the exact content cutoff, rollback command, dry-run requirement, and the separate v6.2.0-only unsigned Windows decision recorded after the SignPath CSR-pending failure. +- [x] For stable v6.3.0 promotion, record the 2026-08-22 release-owner decision + accepting the shortened `rc.6` soak and bounded post-RC cutoff after the + canonical production telemetry report showed no new update failures, + rollback signals, notification-failure increases, or governed-action-failure + increases across the `rc.5` and `rc.6` cohorts. +- [x] For stable v6.3.0 publication, record the independent, version-bound + owner exception for unsigned Windows artifacts and require both public + Unknown Publisher disclosure and the unchanged exact-SHA integrity controls. - [x] For GA/stable promotion, confirm `V5_MAINTENANCE_SUPPORT_POLICY.md` is still the intended policy and replace any placeholder GA notice dates with the exact v6 GA date and exact v5 end-of-support date that will ship with the announcement. - [x] For GA/stable promotion, confirm the pushed governed release-branch copy of `.github/workflows/release-dry-run.yml` already accepts the governed stable rehearsal metadata envelope (`promoted_from_tag`, `rollback_version`, `ga_date`, `v5_eos_date`) through `workflow_dispatch`, because GitHub executes the selected remote ref and does not see local-only governance state. - [x] For GA/stable promotion, confirm the local rehearsal branch exactly matches `origin` before dispatching `Release Dry Run`, so the run exercises the intended governed branch state instead of stale remote control-plane metadata. diff --git a/docs/release-control/v6/internal/RELEASE_PROMOTION_POLICY.md b/docs/release-control/v6/internal/RELEASE_PROMOTION_POLICY.md index 2f44acd3f..6d9f1ddcf 100644 --- a/docs/release-control/v6/internal/RELEASE_PROMOTION_POLICY.md +++ b/docs/release-control/v6/internal/RELEASE_PROMOTION_POLICY.md @@ -398,6 +398,41 @@ TLS-unverified receipts leave the claim at `implemented` or checksums, detached `.sig`/`.sshsig` signatures, and published digests. Public notes must disclose that the binaries are not Authenticode-signed and may display an Unknown Publisher warning. +13. v6.3.0 release-cutoff exception: + - On 2026-08-22, the release owner reviewed the privacy-safe production + telemetry posture for `v6.3.0-rc.5` and `v6.3.0-rc.6`, declared current + `main` at `53ba9786c5522a6839f9cbd3d01c02402556f9eb` the v6.3.0 content + cutoff, and explicitly directed stable promotion from `v6.3.0-rc.6` + without completing its normal 72-hour soak. The dated decision record is + `docs/release-control/v6/internal/records/v6.3.0-stable-cutoff-owner-approval-2026-08-22.md`. + - This is a bounded v6.3.0 owner-risk acceptance, not soak evidence and not + a standing exception for later releases. It explicitly accepts the modest + telemetry cohort, the young `rc.6` follow-up window, and the bounded + runtime and release-path changes between the promoted tag and the cutoff. + The workflow input `hotfix_exception=true` transports the approved waiver + through the shared resolver; it does not reclassify v6.3.0 as a patch + hotfix. + - The final release-preparation commit may change only governed version, + release-note, qualification, test-guardrail, and release-control metadata. + The exact pushed SHA must pass the no-publication `Release Dry Run` before + the same SHA is dispatched through the single-build publication workflow. + - This cutoff decision did not itself waive Windows signing. The release + owner subsequently recorded a separate version-bound v6.3.0 + unsigned-Windows decision; neither exception broadens the other. +14. v6.3.0 unsigned-Windows exception: + - On 2026-08-22, the release owner explicitly authorized unsigned Windows + Unified Agent artifacts for stable `v6.3.0` because Authenticode signing + is not yet available for this release. The dated decision record is + `docs/release-control/v6/internal/records/v6.3.0-unsigned-windows-owner-approval-2026-08-22.md`. + - This is a bounded `v6.3.0` decision, not evidence that Authenticode + succeeded and not a standing exception. Stable `v6.3.1` and later restore + mandatory Authenticode unless another explicit, version-bound owner + decision is recorded. + - Windows artifacts remain bound by the exact release SHA, immutable + candidate manifest, SHA-256 checksums, detached `.sig` and `.sshsig` + signatures, and published-digest verification. Public notes must disclose + that the binaries are not Authenticode-signed and may display an Unknown + Publisher warning. ## Single-Build Release Path diff --git a/docs/release-control/v6/internal/records/v6.3.0-stable-cutoff-owner-approval-2026-08-22.md b/docs/release-control/v6/internal/records/v6.3.0-stable-cutoff-owner-approval-2026-08-22.md new file mode 100644 index 000000000..cca2d1638 --- /dev/null +++ b/docs/release-control/v6/internal/records/v6.3.0-stable-cutoff-owner-approval-2026-08-22.md @@ -0,0 +1,88 @@ +# v6.3.0 Stable Cutoff Owner Approval + +- Decision date: `2026-08-22` +- Release: `v6.3.0` +- Content cutoff base: `53ba9786c5522a6839f9cbd3d01c02402556f9eb` +- Promoted prerelease: `v6.3.0-rc.6` +- Rollback target: `v6.2.1` +- Exact rollback reinstall command: `./scripts/install.sh --version v6.2.1` + +## Owner Decision + +The release owner directed stable `v6.3.0` publication after reviewing the +production telemetry posture of the latest two release candidates. The owner +explicitly accepted the shortened `v6.3.0-rc.6` soak and the bounded runtime +and release-path changes between that tag and the content cutoff above. + +This is a one-version owner-risk acceptance, not 72-hour soak evidence and not +a standing exception for later releases. The workflow input +`hotfix_exception=true` carries the approved waiver through the existing +promotion resolver; it does not reclassify this stable minor release as a patch +hotfix. + +The final release-preparation commit may change only governed version, +release-note, qualification, test-guardrail, and release-control metadata. The +exact pushed stable SHA must pass the no-publication `Release Dry Run` before +the same SHA is dispatched through the normal single-build publication +workflow. + +## Telemetry Evidence + +The decision used the canonical, privacy-safe production telemetry report over +a 14-day source window. The report queried pseudonymous aggregate heartbeat +rows read-only on `pulse-license`; it did not join telemetry to accounts, +licenses, people, or infrastructure identifiers. + +- Measurement completed: `2026-08-22T09:19:36Z` +- Latest telemetry row: `2026-08-22 09:19:36 UTC` +- Retained database population: 379,909 rows from 27,539 rotating + pseudonymous install IDs +- Exact report commands: + +```bash +python3 scripts/telemetry_adoption_report.py \ + --ssh-host root@pulse-license \ + --since-days 14 \ + --target-version 6.3.0-rc.5 \ + --format json + +python3 scripts/telemetry_adoption_report.py \ + --ssh-host root@pulse-license \ + --since-days 14 \ + --target-version 6.3.0-rc.6 \ + --format json +``` + +Sanitized aggregate snapshot: + +1. `v6.3.0-rc.6` + - 18 active installs: 10 binary and 8 Docker + - 35 target-version heartbeat rows; 3 installs had a later same-version + heartbeat at measurement time + - 56 rolling-window update attempts, 56 successes, and zero failures + - zero rollback, forward-departure, or unclassified version transitions + - zero follow-up increases across update failures, notification failure + categories, approved-action failures, and stuck-executing actions +2. `v6.3.0-rc.5` + - 7 installs observed; 6 remained on `rc.5` and 1 advanced to `rc.6` + - 10 target-version heartbeat rows; 2 installs had same-version follow-up + - zero rollback or unclassified version transitions + - the one rolling-window update failure was present on the first heartbeat + and did not increase on any same-version follow-up, so the report does not + attribute it to `rc.5` + - zero follow-up increases across notification failure categories, + approved-action failures, and stuck-executing actions + +The telemetry sample is modest and `rc.6` is younger than the normal 72-hour +window. The report is coarse operational telemetry rather than crash analytics, +and first-heartbeat rolling counters are baseline only. Those limitations are +part of the accepted risk rather than being presented as stronger evidence. + +## Windows Signing Boundary + +This cutoff decision did not itself waive Windows signing. The release owner +subsequently recorded a separate, version-bound `v6.3.0` unsigned-Windows +decision in +`v6.3.0-unsigned-windows-owner-approval-2026-08-22.md`. That decision changes +only the Authenticode requirement and preserves the exact-SHA, checksum, +detached-signature, manifest, and published-digest controls. diff --git a/docs/release-control/v6/internal/records/v6.3.0-unsigned-windows-owner-approval-2026-08-22.md b/docs/release-control/v6/internal/records/v6.3.0-unsigned-windows-owner-approval-2026-08-22.md new file mode 100644 index 000000000..541d0fed3 --- /dev/null +++ b/docs/release-control/v6/internal/records/v6.3.0-unsigned-windows-owner-approval-2026-08-22.md @@ -0,0 +1,35 @@ +# v6.3.0 Unsigned Windows Owner Approval + +- Decision date: `2026-08-22` +- Release: `v6.3.0` +- Promoted prerelease: `v6.3.0-rc.6` +- Rollback target: `v6.2.1` +- Exact rollback reinstall command: `./scripts/install.sh --version v6.2.1` + +## Owner Decision + +Windows Authenticode signing is not yet available for this release. On +2026-08-22, the release owner explicitly authorized unsigned Windows Unified +Agent artifacts for stable `v6.3.0` so the unavailable signing path does not +block the otherwise qualified GA release. + +This is a version-bound risk acceptance, not evidence that Authenticode +succeeded and not a standing exception for later releases. Stable `v6.3.1` +and later restore mandatory Authenticode unless a new explicit, version-bound +owner decision is recorded. + +This signing decision is independent of the separate v6.3.0 telemetry-backed +cutoff and shortened-soak approval. Neither exception broadens the other. + +## Required Integrity Controls + +The exception changes only the Authenticode requirement. Windows artifacts +must still be built from the exact release SHA and bound to the immutable +candidate manifest, SHA-256 checksums, detached `.sig` and `.sshsig` +signatures, and published-digest verification. The public release notes must +state that the Windows binaries are not Authenticode-signed and may display an +Unknown Publisher warning. + +The normal integrated frontend, backend, installer, Docker, Helm, macOS +signing and notarization, candidate validation, publication, activation, and +convergence controls remain unchanged. diff --git a/docs/release-control/v6/internal/status.json b/docs/release-control/v6/internal/status.json index f46202bda..9601db3b3 100644 --- a/docs/release-control/v6/internal/status.json +++ b/docs/release-control/v6/internal/status.json @@ -9646,13 +9646,13 @@ "candidate_lanes": [], "work_claims": [ { - "id": "release-acceleration-lane-l1", - "agent_id": "release-acceleration", - "summary": "Reduce warm RC dispatch-to-convergence time to 15 minutes with credential-isolated PVE runners, deterministic sharding, and cross-repo build parallelism.", + "id": "ga-release-2026-08-22-lane-l1", + "agent_id": "ga-release-2026-08-22", + "summary": "Audit production telemetry and prepare and publish v6.3.0 stable under the owner-authorized promotion after clean rc.5 and rc.6 cohorts.", "target_id": "v6-product-lane-expansion", - "claimed_at": "2026-08-21T11:23:13Z", - "heartbeat_at": "2026-08-21T19:14:24Z", - "expires_at": "2026-08-21T21:14:24Z", + "claimed_at": "2026-08-22T09:15:48Z", + "heartbeat_at": "2026-08-22T09:20:31Z", + "expires_at": "2026-08-22T15:20:31Z", "work_item": { "kind": "lane", "id": "L1" @@ -10577,6 +10577,30 @@ "lane_ids": [ "L3" ] + }, + { + "id": "v6-3-0-telemetry-backed-stable-cutoff", + "summary": "On 2026-08-22 the release owner reviewed the privacy-safe production telemetry posture for v6.3.0-rc.5 and v6.3.0-rc.6, found no new update failures, rollback signals, notification-failure increases, or governed-action-failure increases, and approved stable v6.3.0 from main cutoff 53ba9786c5522a6839f9cbd3d01c02402556f9eb without another RC or the remainder of the normal 72-hour soak. This is a version-bound owner-risk acceptance that explicitly includes the modest cohort, young rc.6 follow-up window, and bounded post-RC changes; it is not soak evidence or a standing exception.", + "kind": "release-policy", + "decided_at": "2026-08-22", + "subsystem_ids": [ + "deployment-installability" + ], + "lane_ids": [ + "L1" + ] + }, + { + "id": "v6-3-0-unsigned-windows-owner-exception", + "summary": "On 2026-08-22 the release owner explicitly authorized unsigned Windows Unified Agent artifacts for stable v6.3.0 because Authenticode signing is not yet available. This version-bound exception changes only the Authenticode requirement: the exact release SHA, immutable candidate manifest, SHA-256 checksums, detached signatures, published-digest verification, and public Unknown Publisher disclosure remain mandatory. Stable v6.3.1 and later restore mandatory Authenticode unless another explicit version-bound decision is recorded.", + "kind": "release-policy", + "decided_at": "2026-08-22", + "subsystem_ids": [ + "deployment-installability" + ], + "lane_ids": [ + "L1" + ] } ] } diff --git a/docs/release-control/v6/internal/subsystems/deployment-installability.md b/docs/release-control/v6/internal/subsystems/deployment-installability.md index 189660d4c..a8b988e5b 100644 --- a/docs/release-control/v6/internal/subsystems/deployment-installability.md +++ b/docs/release-control/v6/internal/subsystems/deployment-installability.md @@ -1656,12 +1656,20 @@ diagnostics. The same release workflow also executes the generated self-signed and custom-CA Windows installer commands through Windows PowerShell 5.1 before release assembly, so the first HTTPS fetch is release proof rather than a string-shape assertion. -The active prerelease `v6.3.0-rc.6` cut sets the repo-root `VERSION`, +The active stable `v6.3.0` 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.3.0-rc.6` release -version. It follows `v6.3.0-rc.5` on the published 6.3 candidate line, uses -`rollback_version=v6.2.1`, and keeps stable/latest pointers on `v6.2.1`. This -candidate establishes the new minor-release packet with durable scoped Patrol +fallback, and Helm chart release metadata to the same `6.3.0` release version. +This stable minor release uses `promoted_from_tag=v6.3.0-rc.6`, +`rollback_version=v6.2.1`, and the explicit version-bound decision recorded on +2026-08-22 to accept the shortened soak and bounded post-RC cutoff after the +canonical production telemetry review. The workflow input +`hotfix_exception=true` transports that approved waiver through the shared +promotion resolver; it does not reclassify v6.3.0 as a patch hotfix. The exact +stable `main` SHA must pass the no-publication dry run before the same SHA is +dispatched through the single-build publish workflow. The release moves +stable/latest install pointers and stable semver aliases only after the exact +public and private candidate paths pass. This release establishes the new +minor-release packet with durable scoped Patrol objectives, validated read-only observers, verified work receipts, agent action preflight with stable refusal codes, large-estate response improvements, and monitoring correctness fixes. The advanced branch also carries the decision-first @@ -1671,11 +1679,11 @@ Patrol turns bound command cleanup after an idle deadline so descendant-held output pipes cannot extend the caller-owned stall budget. This candidate also adds canonical estate summaries and search, a real-delivery activity log, least-privilege agent installation, and bounded Docker-in-LXC discovery while -preserving unreadable settings and AI state. The changes since -`v6.3.0-rc.5` do not require a Pulse Mobile client change and preserve the -existing mobile, Relay, onboarding, and mobile-facing API contracts, so the -server cut is classified `no-mobile-impact`; no companion upload or public -mobile-store rollout is part of this candidate. +preserving unreadable settings and AI state. The stable server cut is +classified `existing-mobile-build-compatible`. The changes since +`v6.3.0-rc.6` do not require a Pulse Mobile client change and preserve the +existing mobile, Relay, onboarding, and mobile-facing API contracts, so no +companion upload or public mobile-store rollout is part of this stable release. For `v6.3.0-rc.5`, credential-free public and private payload compilation ran on dedicated PVE workers with persistent caches. Platform archive validation, exact-candidate container and Helm smoke, backend shards, frontend checks, @@ -1697,6 +1705,24 @@ consumed by Pro assembly, and paid-runtime Docker and direct-binary mismatch proofs execute concurrently without weakening either proof. All immutable candidate, signing, installer, public/private integrity, activation, and final convergence joins remain mandatory. +The v6.3.0 stable cutoff at +`53ba9786c5522a6839f9cbd3d01c02402556f9eb` adds fail-closed release dry-run +diagnostics, native-agent fixture portability, measured backend shard +admission, Patrol provider-unavailable recovery, per-resource alert override +correctness, and cross-estate host identity preservation on top of the +published `v6.3.0-rc.6` lineage. The 2026-08-22 release-owner record binds the +shortened-soak and post-RC risk acceptance to aggregate production telemetry: +18 active `rc.6` installs across binary and Docker, 56 recorded update +successes and zero update failures, no rollback or version-departure signal, +and no follow-up notification-failure or governed-action-failure increase; the +preceding `rc.5` cohort likewise showed no rollback and one forward transition +to `rc.6`. The record states the modest sample and young `rc.6` follow-up +window explicitly rather than presenting them as 72-hour soak evidence. +The release owner separately approved a v6.3.0-only unsigned-Windows +exception because Authenticode signing is not yet available. This independent +decision does not broaden the soak waiver. The Windows packet must disclose +the Unknown Publisher warning and retain exact-SHA, checksum, +detached-signature, immutable-manifest, and published-digest verification. Release run `32493044910` exposed the memory-driven one-shard backend fallback before publication: all 3,736 top-level API tests were encoded into one `-test.run` argument and Linux rejected the invocation with `Argument list too @@ -1724,12 +1750,12 @@ observer coverage, estate-first platform search and facets, and real delivery- attempt visibility. The detailed packet must also retain the bounded Docker-in- LXC and supported least-privilege Unified Agent statements instead of dropping them during publish-body condensation. -The prerelease Windows path retains exact-SHA, checksum, and detached-signature -verification without Authenticode; stable `v6.3.0` restores mandatory SignPath -signing unless a new version-bound decision is recorded. -This prerelease keeps `rollback_version=v6.2.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 preceding prerelease Windows path retained exact-SHA, checksum, and +detached-signature verification without Authenticode. Stable `v6.3.0` uses the +separately recorded version-bound unsigned-Windows exception: the public notes +must state that its Windows binaries are not Authenticode-signed and may +display an Unknown Publisher warning. The immutable-candidate, checksum, +detached-signature, manifest, and published-digest controls remain mandatory. The preceding `v6.3.0-rc.1` publication attempt was quarantined before the GitHub release commit point when its exact private Pro staging run was @@ -2006,9 +2032,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 prerelease `v6.3.0-rc.6` cut, the repo-root compose default and -`scripts/install-docker.sh` fallback must both pin `6.3.0-rc.6` -until the next governed stable cut moves them forward. Each new release moves +For the active stable `v6.3.0` cut, the repo-root compose default and +`scripts/install-docker.sh` fallback must both pin `6.3.0` until the next +governed release moves 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 release-packet blocker. diff --git a/docs/releases/RELEASE_NOTES_v6.3.0.md b/docs/releases/RELEASE_NOTES_v6.3.0.md new file mode 100644 index 000000000..79fe5ffed --- /dev/null +++ b/docs/releases/RELEASE_NOTES_v6.3.0.md @@ -0,0 +1,104 @@ +# Pulse v6.3.0 Release Notes + +`v6.3.0` is a stable minor release for the Pulse v6 line. It follows stable +`v6.2.1` and promotes the monitoring-first operations work exercised across +the `v6.3.0-rc.1` through `v6.3.0-rc.6` line, plus the bounded fixes included +in the final stable cutoff. + +## Highlights + +- Patrol adds durable objectives and verified work receipts; Actions provides + a dedicated inbox for governed approvals and execution. +- Estate-first pages add canonical search, status facets, relationships, + timelines, and Operational Trust signals across mixed infrastructure. +- Safer Unified Agent operation, clearer delivery evidence, and a fail-closed + release pipeline strengthen monitoring and controlled action. + +## Added + +- Durable scoped Patrol objectives, validated read-only observer missions, and + content-free telemetry for operational outcomes. +- A first-class Actions workspace for approval requests, governed plans, + execution records, audit evidence, and verification state. +- Typed Unified Agent action preflight for supported host and Docker + operations, with stable refusal codes for stale plans, changed targets, + missing prerequisites, policy decisions, and unavailable capabilities. +- Canonical estate summaries, status facets, shared platform search, resource + relationship views, and resource-change timelines. +- A seven-day activity log for real notification delivery attempts and a + supported least-privilege Unified Agent installation profile. + +## Improved + +- Patrol surfaces provider-unavailable state directly and clears stale blocked + findings when a configured provider becomes available again. +- Resource presentation keeps same-short-name hosts from separate estates + distinct instead of collapsing them into one row. +- Per-resource severity overrides can re-enable an offline alert even when the + corresponding global threshold is disabled. +- Subscription-backed turns bound canceled command cleanup so descendant-held + output pipes cannot extend the caller-owned idle timeout. +- Docker-in-LXC discovery backs off against slow or failing Proxmox hosts, and + Unified Agent observers remain report-only with destination-scoped trust. +- Release compilation, backend admission, container qualification, public and + private staging, and post-publication convergence make fuller use of the + dedicated PVE capacity without moving customer pointers before exact-SHA + readiness. + +## Fixed + +- Release dry-run diagnostics now fail closed when the diagnostic runner or + stable-tier test path fails, while preserving actionable artifacts. +- Native-agent fixtures are path-portable on Windows, and pre-commit Go linting + follows the repository toolchain declared by `go.mod`. +- Release qualification retains the resource controls required by the release + asset builder and rejects insufficient measured worker headroom before + backend shard execution starts. +- Activation recovery, Helm convergence, private-license checks, and paid + runtime proof continue to join the canonical release result rather than + relying on duplicate or moving state. + +## Release Qualification + +- The v6 control plane reports all 44 readiness assertions and all 26 release + gates passed, with `release_ready=True` at the stable cutoff. +- Production telemetry on 2026-08-22 showed 18 active `v6.3.0-rc.6` installs + across binary and Docker, 56 recorded update successes, zero update + failures, zero rollback or version-departure signals, and no new notification + or governed-action failure counters on follow-up heartbeats. +- The preceding `v6.3.0-rc.5` cohort likewise showed no rollback signal; one + install advanced to `v6.3.0-rc.6`, and its single rolling-window update + failure was already present on the first heartbeat rather than increasing on + the candidate. +- The release owner explicitly accepted the shortened `rc.6` soak and the + bounded post-RC cutoff for `v6.3.0`. This is version-bound risk acceptance, + not 72-hour soak evidence. +- The exact pushed stable SHA must pass the no-publication Release Dry Run + before the same SHA enters the single-build publication workflow. +- Windows Unified Agent binaries are not Authenticode-signed for `v6.3.0` and + may display an Unknown Publisher warning. The release owner approved this + version-bound exception because Windows signing is not yet available. +- The unsigned-Windows exception changes only Authenticode. Exact-SHA builds, + SHA-256 checksums, detached signatures, the immutable candidate manifest, + and published-digest verification remain required. + +## Upgrade Notes + +Use the normal v6 install or update flow for `v6.3.0`. Existing configurations +remain valid and no manual data migration is required. + +The rollback target is `v6.2.1`. The exact rollback reinstall command is: + +```bash +./scripts/install.sh --version v6.2.1 +``` + +This server release is compatible with the existing Pulse Mobile candidate. +The changes since `v6.3.0-rc.6` preserve the checked-in mobile API, Relay, +pairing, approval, push, authentication, and onboarding contracts. No companion +upload or public mobile-store rollout is part of this server release. + +Paid Pulse Pro, Relay, and eligible legacy customers should continue to use the +private download page and private runtime image for paid runtime features. +Unproved self-service commercial plan or billing-cadence transitions remain +disabled and are not introduced by this release. diff --git a/docs/releases/V6_CHANGELOG_v6.3.0.md b/docs/releases/V6_CHANGELOG_v6.3.0.md new file mode 100644 index 000000000..206fcb6e2 --- /dev/null +++ b/docs/releases/V6_CHANGELOG_v6.3.0.md @@ -0,0 +1,65 @@ +# Pulse v6.3.0 + +_This changelog describes stable `v6.3.0` compared with stable `v6.2.1`._ + +## Added + +- Durable scoped Patrol objectives, read-only observer missions, verified work + receipts, and a dedicated Actions workspace for approvals and governed work. +- Typed Unified Agent action preflight with stable refusal classifications for + target changes, prerequisites, policy, capability, contract, and stale-plan + boundaries. +- Estate summaries, status facets, canonical platform search, resource + relationships, change timelines, and real notification-delivery history. +- A supported least-privilege Unified Agent profile and destination-scoped + report-only observer topology. + +## Changed + +- Patrol provider-unavailable state is explicit and stale blocked findings + recover when a configured provider returns. +- Platform and resource presentation preserve canonical identity across + separate estates even when hosts share the same short name. +- Per-resource severity overrides can deliberately re-enable disabled offline + alerts without changing the global threshold. +- Subscription-backed AI turns, Docker-in-LXC discovery, large-estate reads, + release compilation, backend admission, container staging, and paid-runtime + convergence use bounded work and measured capacity. +- Release publication keeps exact-source, signing, immutable-manifest, + installer, public/private artifact, Helm, activation, and convergence proof + joined at one release commit. + +## Fixed + +- Release dry runs fail closed on diagnostic runner and stable-tier failures + and retain the corresponding diagnostics. +- Native-agent fixtures remain path-portable on Windows, and pre-commit linting + uses the Go toolchain selected by `go.mod`. +- Release qualification preserves asset-builder resource controls and refuses + a backend shard plan that lacks measured worker headroom. +- Activation recovery, Helm repository operations, private-license checks, and + paid-runtime verification use canonical exact-release state. + +## Release Metadata + +- Version: `v6.3.0` +- Previous stable: `v6.2.1` +- Promoted prerelease lineage: `v6.3.0-rc.6` +- Content cutoff base: `53ba9786c5522a6839f9cbd3d01c02402556f9eb` +- Rollback target: `v6.2.1` +- Rollback command: `./scripts/install.sh --version v6.2.1` +- Promotion path: owner-approved exact-SHA stable cutoff from `main`, using the + v6.3.0-only soak waiver and the single-build release workflow +- Soak decision: production telemetry showed no new update failures, rollback + signals, notification-failure increases, or governed-action-failure + increases in the `rc.5` and `rc.6` cohorts; the release owner accepted the + shortened soak and bounded post-RC cutoff as version-bound risk acceptance +- Windows signing decision: version-bound unsigned-Windows exception because + signing is not yet available; the binaries are not Authenticode-signed and + may display an Unknown Publisher warning, while exact-SHA, checksum, + detached-signature, immutable-manifest, and published-digest verification + remain mandatory +- Mobile decision: `existing-mobile-build-compatible`; the changes since + `v6.3.0-rc.6` preserve the checked-in mobile, Relay, onboarding, and + mobile-facing API contracts, and no companion upload or public store rollout + is required diff --git a/frontend-modern/public/docs/UPGRADE_v6.md b/frontend-modern/public/docs/UPGRADE_v6.md index 8f074c1e9..9e36b1b17 100644 --- a/frontend-modern/public/docs/UPGRADE_v6.md +++ b/frontend-modern/public/docs/UPGRADE_v6.md @@ -2,16 +2,21 @@ 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.3.0-rc.6.md` -- `docs/releases/V6_CHANGELOG_v6.3.0-rc.6.md` - For the current stable v6 packet, see: +- `docs/releases/RELEASE_NOTES_v6.3.0.md` +- `docs/releases/V6_CHANGELOG_v6.3.0.md` + +For the preceding stable v6 packet, see: + - `docs/releases/RELEASE_NOTES_v6.2.1.md` - `docs/releases/V6_CHANGELOG_v6.2.1.md` +For historical v6.3 release candidate packets, see: + +- `docs/releases/RELEASE_NOTES_v6.3.0-rc.6.md` +- `docs/releases/V6_CHANGELOG_v6.3.0-rc.6.md` + For earlier stable v6.2 packets, see: - `docs/releases/RELEASE_NOTES_v6.2.0.md` diff --git a/scripts/install-docker.sh b/scripts/install-docker.sh index 547b0a2b5..6e273318e 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.3.0-rc.6" +CANONICAL_DEFAULT_PULSE_VERSION="6.3.0" 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 dac67c7d9..0a26bc9a1 100644 --- a/scripts/installtests/build_release_assets_test.go +++ b/scripts/installtests/build_release_assets_test.go @@ -1335,12 +1335,12 @@ func TestReleaseCandidateRequiresPlatformNativeAgentSigning(t *testing.T) { ) assertFileContainsAll(t, repoFile(".github", "workflows", "release-dry-run.yml"), `Definitive Dry-Run Verdict`, - `require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1' || inputs.version == '6.1.2' || inputs.version == '6.2.0' || inputs.version == '6.2.1') && inputs.unsigned_windows_exception) }}`, + `require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1' || inputs.version == '6.1.2' || inputs.version == '6.2.0' || inputs.version == '6.2.1' || inputs.version == '6.3.0') && inputs.unsigned_windows_exception) }}`, `require_result "exact-SHA release candidate" "$CANDIDATE_RESULT" success`, `require_result "stable demo no-mutation verification" "$DEMO_RESULT" success`, ) assertFileContainsAll(t, repoFile("scripts", "release_control", "resolve_release_promotion.py"), - `version not in {"6.1.0", "6.1.1", "6.1.2", "6.2.0", "6.2.1"}`, + `version not in {"6.1.0", "6.1.1", "6.1.2", "6.2.0", "6.2.1", "6.3.0"}`, `unsigned_windows_reason is required`, `not Authenticode-signed`, `require_windows_signing = not is_prerelease and not unsigned_windows_exception`, diff --git a/scripts/installtests/install_docker_sh_test.go b/scripts/installtests/install_docker_sh_test.go index 7e21ceb49..a0e212bce 100644 --- a/scripts/installtests/install_docker_sh_test.go +++ b/scripts/installtests/install_docker_sh_test.go @@ -332,8 +332,8 @@ func TestInstallDockerProofTracksStableMinorContract(t *testing.T) { "The active stable `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.", "`rollback_version=v"+previous+"`", "`hotfix_exception=true` transports that approved waiver through the shared promotion resolver; it does not reclassify v"+version+" as a patch hotfix.", - "The release owner then separately approved a v"+version+"-only unsigned-Windows exception.", - "The Windows packet must disclose the Unknown Publisher warning and retain exact-SHA, checksum, detached-signature, manifest, and published-digest verification", + "The release owner separately approved a v"+version+"-only unsigned-Windows exception", + "The Windows packet must disclose the Unknown Publisher warning and retain exact-SHA, checksum, detached-signature, immutable-manifest, and published-digest verification.", "For the active stable `v"+version+"` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `"+version+"`", ) } diff --git a/scripts/release_control/release_promotion_policy_test.py b/scripts/release_control/release_promotion_policy_test.py index 8a7ec9712..eb3097177 100644 --- a/scripts/release_control/release_promotion_policy_test.py +++ b/scripts/release_control/release_promotion_policy_test.py @@ -1255,7 +1255,7 @@ class ReleasePromotionPolicyTest(unittest.TestCase): self.assertIn("if: ${{ inputs.version != '' }}", workflow) self.assertIn("require_macos_signing: true", workflow) self.assertIn( - "require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1' || inputs.version == '6.1.2' || inputs.version == '6.2.0' || inputs.version == '6.2.1') && inputs.unsigned_windows_exception) }}", + "require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1' || inputs.version == '6.1.2' || inputs.version == '6.2.0' || inputs.version == '6.2.1' || inputs.version == '6.3.0') && inputs.unsigned_windows_exception) }}", workflow, ) self.assertIn("unsigned_windows_exception:", workflow) @@ -1455,7 +1455,7 @@ class ReleasePromotionPolicyTest(unittest.TestCase): self.assertIn("require_windows_signing: ${{ needs.prepare.outputs.require_windows_signing == 'true' }}", content) self.assertIn("unsigned_windows_exception:", content) self.assertIn("unsigned_windows_reason:", content) - self.assertIn('version not in {"6.1.0", "6.1.1", "6.1.2", "6.2.0", "6.2.1"}', resolver) + self.assertIn('version not in {"6.1.0", "6.1.1", "6.1.2", "6.2.0", "6.2.1", "6.3.0"}', resolver) self.assertIn("not Authenticode-signed", resolver) self.assertIn("windows_signing_backend: signpath", content) self.assertIn('if [[ "$REQUIRE_WINDOWS_SIGNING" == "true" ]]', candidate_workflow) @@ -1703,6 +1703,42 @@ class ReleasePromotionPolicyTest(unittest.TestCase): self.assertIn("not Authenticode-signed", owner_record) self.assertIn("Unknown Publisher warning", owner_record) + def test_v630_owner_telemetry_cutoff_is_version_bound(self) -> None: + policy = normalize_ws( + read("docs/release-control/v6/internal/RELEASE_PROMOTION_POLICY.md") + ) + owner_record = normalize_ws( + read( + "docs/release-control/v6/internal/records/" + "v6.3.0-stable-cutoff-owner-approval-2026-08-22.md" + ) + ) + + self.assertIn("v6.3.0 release-cutoff exception", policy) + self.assertIn("bounded v6.3.0 owner-risk acceptance", policy) + self.assertIn("not soak evidence and not a standing exception", policy) + self.assertIn("Promoted prerelease: `v6.3.0-rc.6`", owner_record) + self.assertIn("Rollback target: `v6.2.1`", owner_record) + self.assertIn( + "Exact rollback reinstall command: `./scripts/install.sh --version v6.2.1`", + owner_record, + ) + self.assertIn("18 active installs: 10 binary and 8 Docker", owner_record) + self.assertIn("56 rolling-window update attempts, 56 successes, and zero failures", owner_record) + self.assertIn("separate, version-bound `v6.3.0` unsigned-Windows decision", owner_record) + + signing_record = normalize_ws( + read( + "docs/release-control/v6/internal/records/" + "v6.3.0-unsigned-windows-owner-approval-2026-08-22.md" + ) + ) + self.assertIn("v6.3.0 unsigned-Windows exception", policy) + self.assertIn("Stable `v6.3.1` and later restore mandatory Authenticode", policy) + self.assertIn("Windows Authenticode signing is not yet available", signing_record) + self.assertIn("not Authenticode-signed", signing_record) + self.assertIn("Unknown Publisher warning", signing_record) + def test_release_artifact_workflows_refuse_stable_without_matching_rc(self) -> None: publish = read(".github/workflows/publish-docker.yml") promote = read(".github/workflows/promote-floating-tags.yml") diff --git a/scripts/release_control/resolve_release_promotion.py b/scripts/release_control/resolve_release_promotion.py index 27ccd4746..c945747c3 100644 --- a/scripts/release_control/resolve_release_promotion.py +++ b/scripts/release_control/resolve_release_promotion.py @@ -245,10 +245,10 @@ def resolve_metadata( promotion_mode = "prerelease" if is_prerelease else "stable-rc-promotion" if unsigned_windows_exception: - if version not in {"6.1.0", "6.1.1", "6.1.2", "6.2.0", "6.2.1"}: + if version not in {"6.1.0", "6.1.1", "6.1.2", "6.2.0", "6.2.1", "6.3.0"}: raise ValueError( "unsigned_windows_exception is approved only for stable v6.1.0, v6.1.1, " - "v6.1.2, v6.2.0, or v6.2.1. Later stable releases require a new explicit, " + "v6.1.2, v6.2.0, v6.2.1, or v6.3.0. Later stable releases require a new explicit, " "version-bound owner decision." ) if not unsigned_windows_reason: diff --git a/scripts/release_control/resolve_release_promotion_test.py b/scripts/release_control/resolve_release_promotion_test.py index 6cc98ec79..71050aa50 100644 --- a/scripts/release_control/resolve_release_promotion_test.py +++ b/scripts/release_control/resolve_release_promotion_test.py @@ -289,15 +289,44 @@ class ResolveReleasePromotionTest(unittest.TestCase): self.assertEqual(metadata["require_windows_signing"], "false") self.assertEqual(metadata["unsigned_windows_exception"], "true") + def test_v630_owner_exception_allows_disclosed_stable_promotion(self) -> None: + metadata = resolver.resolve_metadata( + version="6.3.0", + promoted_from_tag_input="v6.3.0-rc.6", + rollback_version_input="v6.2.1", + ga_date_input="", + v5_eos_date_input="", + hotfix_exception=True, + hotfix_reason_input="Owner accepted the shortened prerelease soak.", + release_notes_input=( + "Windows Unified Agent binaries are not Authenticode-signed for v6.3.0." + ), + unsigned_windows_exception=True, + unsigned_windows_reason_input=( + "Windows signing is not yet available; the release owner accepts unsigned " + "Windows binaries for v6.3.0." + ), + tag_exists_fn=lambda tag: tag in {"v6.3.0-rc.6", "v6.2.1"}, + tag_commit_fn=lambda tag: "rc6-commit", + head_descends_from_fn=lambda commit: commit == "rc6-commit", + tag_created_unix_fn=lambda tag: 100, + now_unix_fn=lambda: 100 + (24 * 3600), + ) + + self.assertEqual(metadata["promotion_mode"], "stable-rc-promotion") + self.assertEqual(metadata["rollback_tag"], "v6.2.1") + self.assertEqual(metadata["require_windows_signing"], "false") + self.assertEqual(metadata["unsigned_windows_exception"], "true") + def test_unsigned_windows_exception_is_rejected_for_other_stable_versions(self) -> None: with self.assertRaisesRegex( ValueError, - "approved only for stable v6.1.0, v6.1.1, v6.1.2, v6.2.0, or v6.2.1", + "approved only for stable v6.1.0, v6.1.1, v6.1.2, v6.2.0, v6.2.1, or v6.3.0", ): resolver.resolve_metadata( - version="6.1.3", + version="6.3.1", promoted_from_tag_input="", - rollback_version_input="v6.1.2", + rollback_version_input="v6.3.0", ga_date_input="", v5_eos_date_input="", hotfix_exception=True,