mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-09 18:15:50 +00:00
Prepare v6.1.1 emergency patch release
This commit is contained in:
@@ -38,12 +38,12 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
unsigned_windows_exception:
|
||||
description: 'v6.1.0 only: publish Windows agents without Authenticode under the recorded owner exception'
|
||||
description: 'v6.1.0 or v6.1.1 only: publish Windows agents without Authenticode under a recorded owner exception'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
unsigned_windows_reason:
|
||||
description: 'v6.1.0 only: owner reason for the unsigned Windows exception'
|
||||
description: 'v6.1.0 or v6.1.1 only: owner reason for the unsigned Windows exception'
|
||||
required: false
|
||||
type: string
|
||||
historical_asset_backfill_only:
|
||||
|
||||
@@ -43,12 +43,12 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
unsigned_windows_exception:
|
||||
description: 'v6.1.0 only: rehearse Windows agents without Authenticode under the recorded owner exception'
|
||||
description: 'v6.1.0 or v6.1.1 only: rehearse Windows agents without Authenticode under a recorded owner exception'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
unsigned_windows_reason:
|
||||
description: 'v6.1.0 only: owner reason for the unsigned Windows exception'
|
||||
description: 'v6.1.0 or v6.1.1 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.unsigned_windows_exception) }}
|
||||
require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1') && inputs.unsigned_windows_exception) }}
|
||||
windows_signing_backend: signpath
|
||||
|
||||
dry-run:
|
||||
|
||||
@@ -2,9 +2,9 @@ apiVersion: v2
|
||||
name: pulse
|
||||
description: Helm chart for deploying the Pulse hub and optional Docker monitoring agent.
|
||||
type: application
|
||||
version: 6.1.0
|
||||
appVersion: "6.1.0"
|
||||
icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.1.0/docs/images/pulse-logo.svg
|
||||
version: 6.1.1
|
||||
appVersion: "6.1.1"
|
||||
icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.1.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.1.0/docs/KUBERNETES.md
|
||||
url: https://github.com/rcourtman/Pulse/blob/v6.1.1/docs/KUBERNETES.md
|
||||
- name: Support
|
||||
url: https://github.com/rcourtman/Pulse/discussions
|
||||
artifacthub.io/maintainers: |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# pulse
|
||||
|
||||
  
|
||||
  
|
||||
|
||||
Helm chart for deploying the Pulse hub and optional Docker monitoring agent.
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ version: '3.8'
|
||||
|
||||
services:
|
||||
pulse:
|
||||
image: ${PULSE_IMAGE:-rcourtman/pulse:6.1.0}
|
||||
image: ${PULSE_IMAGE:-rcourtman/pulse:6.1.1}
|
||||
container_name: pulse
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
Pulse release notes live on GitHub:
|
||||
<https://github.com/rcourtman/Pulse/releases>
|
||||
|
||||
For the next release disclosure draft (version assigned at release cut), see:
|
||||
- `docs/releases/RELEASE_NOTES_NEXT_DRAFT.md`
|
||||
|
||||
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.1.1.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.1.1.md`
|
||||
|
||||
For earlier stable v6.1 packets, see:
|
||||
- `docs/releases/RELEASE_NOTES_v6.1.0.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.1.0.md`
|
||||
|
||||
|
||||
+4
-2
@@ -4,11 +4,13 @@ This guide covers practical upgrade steps for existing Pulse installs moving to
|
||||
|
||||
For the current stable v6 packet, see:
|
||||
|
||||
- `docs/releases/RELEASE_NOTES_v6.1.0.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.1.0.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.1.1.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.1.1.md`
|
||||
|
||||
For earlier stable v6 packets and rollout references, see:
|
||||
|
||||
- `docs/releases/RELEASE_NOTES_v6.1.0.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.1.0.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.0.5.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.0.5.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.0.4.md`
|
||||
|
||||
@@ -1022,9 +1022,10 @@ Companion drill:
|
||||
the public demo remains healthy on stable `6.0.5`.
|
||||
- Pass when:
|
||||
The external rehearsal proves the canonical exact-SHA candidate builder and
|
||||
its version-specific native-signing policy. If the `v6.1.0` Windows exception
|
||||
is used, the rehearsal must preserve checksum, detached-signature, manifest,
|
||||
and digest controls and record the owner reason and public disclosure. Local
|
||||
its version-specific native-signing policy. If a recorded `v6.1.0` or
|
||||
`v6.1.1` Windows exception is used, the rehearsal must preserve checksum,
|
||||
detached-signature, manifest, and digest controls and record the
|
||||
version-bound owner reason and public disclosure. Local
|
||||
tests pin candidate-only publication and GitHub digest validation, and the
|
||||
static release DAG contains no duplicate release build,
|
||||
backend-to-integration serialization, full-download standard validator, or
|
||||
@@ -1037,7 +1038,8 @@ Companion drill:
|
||||
release packet, independent post-release jobs are serialized, or the
|
||||
definitive verdict can pass without all applicable downstream results. Also
|
||||
block if an unsigned stable Windows exception can apply to any version other
|
||||
than `v6.1.0` or can omit its owner reason and release-note disclosure.
|
||||
than the recorded `v6.1.0` and `v6.1.1` decisions or can omit its owner
|
||||
reason and release-note disclosure.
|
||||
|
||||
## Gate: `operational-trust-canonical-lifecycle`
|
||||
|
||||
|
||||
@@ -179,8 +179,15 @@ Cloud, and self-hosted production users.
|
||||
Windows Authenticode exception. The Windows artifacts must remain bound
|
||||
by the exact-SHA candidate manifest, checksums, detached `.sig`/`.sshsig`
|
||||
signatures, and published digests, and the public notes must disclose the
|
||||
Unknown Publisher state. Later stable releases restore the Authenticode
|
||||
requirement; this flag cannot be reused for another version.
|
||||
Unknown Publisher state.
|
||||
- On 2026-07-23, the release owner separately approved a `v6.1.1`-only
|
||||
Windows Authenticode exception for the emergency patch addressing active
|
||||
customer update harm. This is a new, version-bound decision rather than a
|
||||
reuse of the `v6.1.0` exception. The same exact-SHA candidate, checksum,
|
||||
detached-signature, manifest, published-digest, owner-reason, and public
|
||||
Unknown Publisher disclosure controls remain mandatory. Stable `v6.1.2`
|
||||
and later restore the Authenticode requirement unless another explicit
|
||||
version-bound owner decision is recorded in policy.
|
||||
- Unproved self-service commercial transitions remain unavailable and
|
||||
unadvertised under the exposure-safety gate. This exception does not
|
||||
authorize enabling that feature or running a production billing proof.
|
||||
@@ -237,8 +244,11 @@ Cloud, and self-hosted production users.
|
||||
onto the RC promotion path. The resolver enforces that boundary. Do not use
|
||||
the routine helper to relabel a risky patch as routine.
|
||||
4. `--emergency-hotfix-reason` is the narrow escape hatch for active customer
|
||||
harm. It does not remove the exact-SHA dry-run requirement, and the reason is
|
||||
recorded in the release metadata.
|
||||
harm. It does not remove the integrated exact-SHA candidate and release
|
||||
checks, and the reason is recorded in the release metadata.
|
||||
A version-bound unsigned Windows decision must additionally be supplied
|
||||
through `--unsigned-windows-exception-reason`; it never follows implicitly
|
||||
from emergency patch status.
|
||||
5. The release workflow must await Docker publication, stable demo deployment,
|
||||
public health/browser verification, install smoke, Helm publication,
|
||||
floating-tag promotion, and private Pro promotion where applicable. The
|
||||
|
||||
@@ -9176,7 +9176,21 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"work_claims": [],
|
||||
"work_claims": [
|
||||
{
|
||||
"id": "codex-release-gate-stable-patch-unattended-release-path",
|
||||
"agent_id": "codex",
|
||||
"summary": "Prepare and publish v6.1.1 emergency stable patch with owner-approved unsigned Windows exception",
|
||||
"target_id": "v6-product-lane-expansion",
|
||||
"claimed_at": "2026-07-23T12:19:02Z",
|
||||
"heartbeat_at": "2026-07-23T12:19:02Z",
|
||||
"expires_at": "2026-07-23T16:19:02Z",
|
||||
"work_item": {
|
||||
"kind": "release-gate",
|
||||
"id": "stable-patch-unattended-release-path"
|
||||
}
|
||||
}
|
||||
],
|
||||
"open_decisions": [],
|
||||
"source_of_truth_file": "docs/release-control/v6/internal/SOURCE_OF_TRUTH.md",
|
||||
"resolved_decisions": [
|
||||
|
||||
@@ -379,12 +379,14 @@ TLS floor in the dynamic config.
|
||||
apply the same channel-specific native-signing policy as a publish run.
|
||||
macOS notarization remains mandatory for both prerelease and stable
|
||||
candidates. Windows Authenticode remains mandatory for stable candidates
|
||||
except for the explicitly version-bound `v6.1.0` owner exception;
|
||||
prerelease candidates and that one stable exception may retain checksum and
|
||||
detached-signature verification without Authenticode while the release
|
||||
packet explicitly discloses the unknown-publisher warning. Prerelease promotion remains
|
||||
blocked on the normal stable signing requirement, and every stable version
|
||||
after `v6.1.0` restores it automatically. A cheap signing-configuration job
|
||||
except for the explicitly version-bound `v6.1.0` and `v6.1.1` owner
|
||||
exceptions; prerelease candidates and those two stable exceptions may
|
||||
retain checksum and detached-signature verification without Authenticode
|
||||
while the release packet explicitly discloses the unknown-publisher warning.
|
||||
Prerelease promotion remains blocked on the normal stable signing
|
||||
requirement, and stable `v6.1.2` and later restore it automatically unless
|
||||
policy records a new version-bound owner decision. A cheap
|
||||
signing-configuration job
|
||||
must report every missing secret for the platforms required by that
|
||||
candidate before either platform runner is allocated. Stable Windows signing must use SignPath's GitHub
|
||||
trusted-build-system action by default, submit an immutable GitHub artifact
|
||||
@@ -1055,9 +1057,12 @@ evidence beside the candidate manifest. Release Dry Run now has a terminal
|
||||
verdict covering the exact-SHA candidate and no-mutation demo lane. Stable
|
||||
rehearsal `29927692302` confirmed that the external SignPath project was not
|
||||
configured and stopped without creating a public release. The release owner
|
||||
subsequently approved a `v6.1.0`-only unsigned-Windows exception; the gate stays
|
||||
blocked until a new exact-`main` rehearsal proves that exception and the
|
||||
remaining candidate controls.
|
||||
subsequently approved and exercised a `v6.1.0`-only unsigned-Windows exception.
|
||||
On 2026-07-23 the owner separately approved a `v6.1.1`-only exception for the
|
||||
emergency patch addressing active customer update harm. The new decision must
|
||||
flow through the normal exact-SHA candidate, checksum, detached-signature,
|
||||
manifest, published-digest, and definitive-verdict controls with an explicit
|
||||
owner reason and public Unknown Publisher disclosure.
|
||||
Every caller of the reusable release-candidate builder must delegate
|
||||
`actions: read` alongside `contents: read`; the Windows signing job reads the
|
||||
exact uploaded artifact through the GitHub Actions API, and GitHub validates
|
||||
@@ -1068,11 +1073,35 @@ host-local redirect contract as runtime token minting and exchange. Proof input
|
||||
must reject absolute, scheme-relative, backslash-authority, encoded-separator,
|
||||
and control-character targets before constructing the handoff request.
|
||||
|
||||
The active stable `v6.1.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.1.0` release version.
|
||||
This stable minor release uses `promoted_from_tag=v6.1.0-rc.4`,
|
||||
`rollback_version=v6.0.5`, and the one-version release-owner cutoff exception
|
||||
The active stable `v6.1.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.1.1` release version. This patch
|
||||
release uses the stable hotfix path with `rollback_version=v6.1.0`,
|
||||
`hotfix_exception=true`, a release-owner reason, and no fabricated
|
||||
same-version RC tag. It fixes manual Unified Agent updates that received a
|
||||
distribution identifier instead of the canonical Linux platform family and
|
||||
durable Docker update actions that could remain stuck after a terminal
|
||||
digest-drift preflight refusal. The exact stable `main` SHA must pass the
|
||||
integrated release checks and immutable-candidate build before the single-build
|
||||
workflow crosses its public mutation boundary. The same workflow must finish
|
||||
Docker, Helm, stable demo, install-smoke, public-health, floating-tag,
|
||||
paid-runtime, and definitive-verdict lanes before the cut is complete.
|
||||
The `v6.1.1` release is `existing-mobile-build-compatible`: no production
|
||||
relay or mobile trust contract changed from `v6.1.0`, the matched mobile-facing
|
||||
path is test-only expiry branch coverage, and Pulse Mobile `1.0.0` iOS build
|
||||
`11` and Android versionCode `9` remain the compatible candidate builds without
|
||||
a companion upload or public store rollout.
|
||||
The release owner separately approved a `v6.1.1`-only unsigned-Windows
|
||||
exception because SignPath configuration remains unavailable. Windows assets
|
||||
must remain exact-SHA and manifest-bound with checksums, detached
|
||||
`.sig`/`.sshsig` signatures, and published-digest verification; the release
|
||||
notes must disclose the Unknown Publisher state. Stable `v6.1.2` and later
|
||||
restore Authenticode unless policy records another explicit version-bound
|
||||
decision.
|
||||
|
||||
The preceding stable `v6.1.0` cut used
|
||||
`promoted_from_tag=v6.1.0-rc.4`, `rollback_version=v6.0.5`, and the
|
||||
one-version release-owner cutoff exception
|
||||
recorded on 2026-07-22. The workflow input `hotfix_exception=true` carries that
|
||||
approved soak bypass through the existing promotion resolver; it does not
|
||||
reclassify the release as a patch hotfix. The exact stable `main` SHA must pass
|
||||
@@ -1112,8 +1141,10 @@ explicitly waived Authenticode after the first stable rehearsal exposed
|
||||
unavailable external SignPath configuration. The unsigned Windows binaries
|
||||
remain exact-SHA and manifest-bound with checksum, detached `.sig`/`.sshsig`,
|
||||
and published-digest verification, and the release notes disclose the Unknown
|
||||
Publisher state. This exception cannot apply to a later stable version.
|
||||
The stable server cut is classified `existing-mobile-build-compatible`. Pulse
|
||||
Publisher state. That `v6.1.0` decision does not itself authorize another
|
||||
version.
|
||||
The `v6.1.0` stable server cut was classified
|
||||
`existing-mobile-build-compatible`. Pulse
|
||||
Mobile `1.0.0` iOS build `11` and Android versionCode `9` remain the existing
|
||||
candidate builds; the canonical core/mobile contract proves that `v6.1.0`
|
||||
serves their route, scope, payload, pairing, and push requirements, including
|
||||
@@ -1180,8 +1211,8 @@ compose image default, standalone installer fallback constant, and packaged
|
||||
Helm metadata. A draft release workflow failure caused by stale image or chart
|
||||
pins is a release-packet blocker until the defaults, tests, and evidence
|
||||
record are refreshed from the new branch head.
|
||||
For the active stable `v6.1.0` cut, the repo-root compose default and
|
||||
`scripts/install-docker.sh` fallback must both pin `6.1.0` until the next
|
||||
For the active stable `v6.1.1` cut, the repo-root compose default and
|
||||
`scripts/install-docker.sh` fallback must both pin `6.1.1` until the next
|
||||
governed stable cut moves them forward. The stable promotion guard remains in
|
||||
force and rejects leftover `-rc.` defaults.
|
||||
The RC7 packet refresh records `fc10de9b5477613316473267b72b05b6b2b7aaff`
|
||||
@@ -2496,8 +2527,9 @@ discloses the unsigned Windows publisher state and the Windows binaries retain
|
||||
the exact-SHA candidate, checksum, detached-signature, and post-publication
|
||||
digest controls. Stable publication and the stable-path dry-run must continue
|
||||
to require both native signing lanes except for the recorded, version-bound
|
||||
`v6.1.0` Windows exception; every subsequent stable release restores both
|
||||
requirements. `scripts/build-release.sh` must replace
|
||||
`v6.1.0` and `v6.1.1` Windows exceptions; stable `v6.1.2` and later restore
|
||||
both requirements unless policy records a new explicit version-bound owner
|
||||
decision. `scripts/build-release.sh` must replace
|
||||
only the native targets required by those independent inputs and must fail
|
||||
closed when a required native-binary directory or target is absent.
|
||||
Historical published-release repair must flow through
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# Next Pulse Release — Disclosure Draft
|
||||
|
||||
This draft records customer-visible disclosures that must be carried into the
|
||||
next Pulse release packet. The release version is assigned only when that
|
||||
packet is cut.
|
||||
|
||||
## Outbound usage telemetry schema v2
|
||||
|
||||
This release updates Pulse's legacy unversioned outbound usage telemetry
|
||||
payload to schema v2. Telemetry remains enabled by default unless an operator
|
||||
has disabled it; an existing enabled or disabled choice is preserved on
|
||||
upgrade. The purpose remains aggregate product and release understanding, and
|
||||
the payload remains pseudonymous rather than tied to a Pulse account or
|
||||
person.
|
||||
|
||||
Schema v2 adds these deliberately coarse signal categories:
|
||||
|
||||
- closed deployment-method, known-install-age, activation-stage,
|
||||
time-to-first-monitored-resource, and estate-size buckets;
|
||||
- authentication-configured and monitoring-active booleans, plus an aggregate
|
||||
configured-connection count;
|
||||
- aggregate alert fired, acknowledged, and resolved counts from the existing
|
||||
30-day local window;
|
||||
- aggregate notification attempt, delivery, and failure counts from the
|
||||
existing seven-day local window; and
|
||||
- a boolean indicating whether an operational outcome was observed in the
|
||||
existing 30-day local window.
|
||||
|
||||
The payload does not include names, email addresses, account IDs, hostnames,
|
||||
credentials, infrastructure or resource identifiers, IP addresses, URLs,
|
||||
paths, locale, recipients, notification endpoints, alert or notification
|
||||
content, prompts, chat messages, command text, action output, token values,
|
||||
browser events, or an event-level journey or clickstream. The rotating
|
||||
pseudonymous installation ID continues to rotate every 30 days. Telemetry rows
|
||||
are retained server-side for up to 90 days; request IP addresses are used only
|
||||
transiently for rate limiting and are not stored in telemetry rows.
|
||||
|
||||
Existing installations receive a one-time, non-blocking
|
||||
**Telemetry payload updated** notice after upgrade. It links directly to the
|
||||
exact payload preview, the disable action, and the full privacy disclosure.
|
||||
Fresh installations do not receive a duplicate banner because the current
|
||||
payload and controls are already disclosed during setup.
|
||||
|
||||
## Terminology correction
|
||||
|
||||
Earlier public website copy used an anonymity label that was too strong for a
|
||||
payload containing a rotating installation identifier. The accurate term is
|
||||
**pseudonymous**. The website wording was corrected in July 2026, before
|
||||
schema v2 reached a public Pulse release; the shipped privacy documentation
|
||||
and in-product control identify the rotating pseudonymous ID and the concrete
|
||||
data categories excluded from the payload.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Pulse v6.1.1 Release Notes
|
||||
|
||||
`v6.1.1` is a stable patch release following `v6.1.0`. It takes the governed
|
||||
emergency stable-patch path to resolve active customer harm in the manual
|
||||
Unified Agent update flow and durable Docker update recovery. It also carries
|
||||
the reliability, infrastructure, and privacy-disclosure improvements already
|
||||
completed on `main` after the `v6.1.0` cutoff.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Manual Unified Agent updates now use the canonical operating-system family,
|
||||
so Mageia and other supported Linux distributions receive the Linux update
|
||||
path instead of being rejected by a distribution-specific platform value.
|
||||
- Docker update actions recover their durable terminal receipt by immutable
|
||||
action and operation identity. A failed or no-effect digest-drift preflight
|
||||
no longer leaves an update stuck after the live capability disappears.
|
||||
- Outbound usage telemetry moves to a documented schema v2 with coarse,
|
||||
pseudonymous operational signals, an exact payload preview, and a one-time
|
||||
non-blocking upgrade notice.
|
||||
- Infrastructure pages retain navigation through stream reconnects, proxy and
|
||||
SSO bootstrap is more reliable, node edits use the correct update endpoint,
|
||||
and PBS datastore alert overrides appear on the thresholds page.
|
||||
|
||||
## Changed
|
||||
|
||||
- Agent runtime platform reporting is normalized to the canonical Go operating
|
||||
system family while preserving the original operating-system identity for
|
||||
diagnostics. Unsupported platforms still fail closed.
|
||||
- Outbound usage telemetry remains enabled by default unless an operator has
|
||||
disabled it, and an existing enabled or disabled preference is preserved on
|
||||
upgrade. The rotating pseudonymous installation ID continues to rotate every
|
||||
30 days.
|
||||
- Telemetry schema v2 adds deliberately coarse deployment-method, install-age,
|
||||
activation-stage, time-to-first-monitored-resource, and estate-size buckets;
|
||||
authentication-configured and monitoring-active booleans; configured
|
||||
connection count; aggregate alert outcome counts; aggregate notification
|
||||
attempt, delivery, and failure counts; and an operational-outcome boolean.
|
||||
- Existing installations receive one non-blocking **Telemetry payload
|
||||
updated** notice with direct links to the exact payload preview, disable
|
||||
action, and privacy disclosure. Fresh installations do not receive a
|
||||
duplicate notice.
|
||||
- Public privacy terminology now describes this rotating-identifier payload as
|
||||
**pseudonymous**, not anonymous.
|
||||
|
||||
Telemetry does not include identities, account details, hostnames, credentials,
|
||||
resource identifiers, IP addresses, URLs, paths, locale, recipients,
|
||||
notification endpoints, alert or notification content, prompts, chat
|
||||
messages, command text or output, token values, browser events, or an
|
||||
event-level journey or clickstream. Telemetry rows are retained server-side for
|
||||
up to 90 days; request IP addresses are used transiently for rate limiting and
|
||||
are not stored in telemetry rows.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Manual Unified Agent updates on Mageia and other supported Linux
|
||||
distributions no longer fail because the update planner receives a distro
|
||||
identifier instead of the Linux platform family (#1607).
|
||||
- Docker update actions that reach a terminal digest-drift preflight refusal
|
||||
now recover as failed or no-effect without redispatch, even when the live
|
||||
update capability is no longer advertised (#1608).
|
||||
- Node state aggregation keeps clusters separate when they reuse the same node
|
||||
names.
|
||||
- Missing Patrol verdicts are swept with bounded follow-up instead of remaining
|
||||
indefinitely unresolved.
|
||||
- Platform navigation survives stream reconnects, and authenticated bootstrap
|
||||
works correctly through proxy and SSO configurations.
|
||||
- Infrastructure node edits route to the update endpoint.
|
||||
- PBS datastore alert overrides are projected onto the thresholds page.
|
||||
- The Proxmox VE setup script avoids an `awk` variable name that conflicts with
|
||||
implementations where `exp` is reserved.
|
||||
|
||||
## Upgrade Notes
|
||||
|
||||
Use the normal v6 install or update flow for `v6.1.1`.
|
||||
|
||||
Windows Unified Agent binaries in `v6.1.1` are not Authenticode-signed and may
|
||||
show an Unknown Publisher warning. Verify published checksums and detached
|
||||
`.sig` or `.sshsig` signatures before installation. This is a `v6.1.1`-only
|
||||
release-owner exception; later stable releases restore the Windows
|
||||
Authenticode requirement.
|
||||
|
||||
The rollback target for this patch release is `v6.1.0`. The exact rollback
|
||||
reinstall command is:
|
||||
|
||||
```bash
|
||||
./scripts/install.sh --version v6.1.0
|
||||
```
|
||||
|
||||
The server/mobile decision is `existing-mobile-build-compatible`. Pulse Mobile
|
||||
`1.0.0` iOS build `11` and Android versionCode `9` remain the compatible
|
||||
candidate builds. No production relay or mobile trust contract changed after
|
||||
`v6.1.0`; the matched mobile-facing path is test-only branch coverage. This
|
||||
release does not upload a companion build or start a public mobile-store
|
||||
rollout.
|
||||
|
||||
Paid Pulse Pro, Relay, and eligible legacy customers should continue to use the
|
||||
private download page and private runtime image for paid runtime features.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Pulse v6.1.1
|
||||
|
||||
_This changelog describes stable `v6.1.1` compared with stable `v6.1.0`._
|
||||
|
||||
## Changed
|
||||
|
||||
- Unified Agent operating-system reporting now provides the canonical runtime
|
||||
platform family to the update planner while retaining detailed OS identity
|
||||
for diagnostics.
|
||||
- Outbound usage telemetry uses schema v2 with rotating pseudonymous identity,
|
||||
bounded aggregate operational signals, preserved operator preference, exact
|
||||
payload preview, and a one-time non-blocking upgrade disclosure.
|
||||
- Privacy copy uses the accurate term **pseudonymous** and explicitly lists the
|
||||
identity, infrastructure, content, command, and clickstream categories
|
||||
excluded from telemetry.
|
||||
- Infrastructure navigation, authenticated proxy/SSO bootstrap, node-edit
|
||||
routing, and PBS alert-threshold projection are more consistent.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Linux manual agent updates no longer misclassify Mageia or other supported
|
||||
distributions as an unsupported update platform (#1607).
|
||||
- Durable Docker update receipt recovery uses immutable action and operation
|
||||
binding, terminalizes digest-drift preflight refusals after capability loss,
|
||||
and never redispatches the rejected operation (#1608).
|
||||
- Cluster node aggregation no longer conflates separate clusters that reuse a
|
||||
node name.
|
||||
- Missing Patrol verdicts retain bounded follow-up.
|
||||
- The Proxmox VE setup script avoids an `awk` identifier collision.
|
||||
|
||||
## Release Metadata
|
||||
|
||||
- Version: `v6.1.1`
|
||||
- Previous stable: `v6.1.0`
|
||||
- Rollback target: `v6.1.0`
|
||||
- Rollback command: `./scripts/install.sh --version v6.1.0`
|
||||
- Promotion path: stable patch hotfix from `main`, with an owner-recorded reason
|
||||
for active customer update harm and no fabricated same-version RC tag
|
||||
- Windows signing decision: `v6.1.1`-only release-owner exception; Windows
|
||||
Unified Agent binaries are not Authenticode-signed and may show an Unknown
|
||||
Publisher warning, while exact-SHA candidate binding, checksums, detached
|
||||
`.sig`/`.sshsig` signatures, manifests, and published digests remain required
|
||||
- Mobile decision: `existing-mobile-build-compatible`; Pulse Mobile `1.0.0`
|
||||
iOS build `11` and Android versionCode `9` require no companion upload, and
|
||||
no public store rollout is part of this server release
|
||||
@@ -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.1.0"
|
||||
CANONICAL_DEFAULT_PULSE_VERSION="6.1.1"
|
||||
|
||||
resolve_default_pulse_version() {
|
||||
if [ -n "${PULSE_IMAGE_VERSION:-}" ]; then
|
||||
|
||||
@@ -269,25 +269,23 @@ func TestCurrentStablePatchReleasePacketTracksInstallMetadata(t *testing.T) {
|
||||
assertFileContainsAllNormalized(t, releaseNotesPath,
|
||||
"`v"+version+"` is a stable patch release",
|
||||
"`v"+previous+"`",
|
||||
"Patrol Gemini model readiness",
|
||||
"remembered-login submit persistence",
|
||||
"Proxmox SMART temperature fallback",
|
||||
"direct SATA/SAT disks",
|
||||
"paid-runtime activation continuity",
|
||||
"license-period status fixes",
|
||||
"Manual Unified Agent updates now use the canonical operating-system family",
|
||||
"Docker update actions recover their durable terminal receipt",
|
||||
"Outbound usage telemetry moves to a documented schema v2",
|
||||
"clusters separate when they reuse the same node names",
|
||||
"not Authenticode-signed",
|
||||
"`existing-mobile-build-compatible`",
|
||||
"rollback target for this patch release is `v"+previous+"`",
|
||||
)
|
||||
assertFileContainsAll(t, changelogPath,
|
||||
"Version: `v"+version+"`",
|
||||
"Rollback target: `v"+previous+"`",
|
||||
"Promotion path: stable patch hotfix from `"+releaseBranch+"`",
|
||||
"Gemini tool-call capability",
|
||||
"Remembered-login state now persists",
|
||||
"Proxmox SMART temperature collection",
|
||||
"explicit SAT probe",
|
||||
"Paid runtime activation now writes and reuses a durable installation fingerprint",
|
||||
"License grants now include the billing `current_period_end`",
|
||||
"Server installer execution now rejects unsafe piped invocation",
|
||||
"canonical runtime",
|
||||
"telemetry uses schema v2",
|
||||
"Durable Docker update receipt recovery",
|
||||
"`v6.1.1`-only release-owner exception",
|
||||
"Mobile decision: `existing-mobile-build-compatible`",
|
||||
)
|
||||
assertFileContainsAll(t, repoFile("docs", "RELEASE_NOTES.md"),
|
||||
"docs/releases/RELEASE_NOTES_v"+version+".md",
|
||||
@@ -385,7 +383,7 @@ func TestCurrentStableMinorReleasePacketTracksInstallMetadata(t *testing.T) {
|
||||
"`rollback_version=v"+previous+"`",
|
||||
"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 stable server cut is classified `existing-mobile-build-compatible`.",
|
||||
"This exception cannot apply to a later stable version",
|
||||
"explicit version-bound decision",
|
||||
"For the active stable `v"+version+"` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `"+version+"`",
|
||||
)
|
||||
}
|
||||
@@ -849,12 +847,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.unsigned_windows_exception) }}`,
|
||||
`require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1') && 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 != "6.1.0"`,
|
||||
`version not in {"6.1.0", "6.1.1"}`,
|
||||
`unsigned_windows_reason is required`,
|
||||
`not Authenticode-signed`,
|
||||
`require_windows_signing = not is_prerelease and not unsigned_windows_exception`,
|
||||
|
||||
@@ -288,9 +288,10 @@ func TestInstallDockerProofTracksStablePatchReleaseContract(t *testing.T) {
|
||||
assertFileContainsAllNormalized(t, repoFile("docs", "release-control", "v6", "internal", "subsystems", "deployment-installability.md"),
|
||||
"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.",
|
||||
"This patch release uses the stable hotfix path with `rollback_version=v"+previous+"`, `hotfix_exception=true`, a release-owner reason, and no fabricated same-version RC tag.",
|
||||
"It advances the v"+previous+" stable line with customer-support fixes",
|
||||
"paid-runtime activation fingerprint reuse",
|
||||
"pinned installer execution hardening",
|
||||
"manual Unified Agent updates",
|
||||
"durable Docker update actions",
|
||||
"`existing-mobile-build-compatible`",
|
||||
"`v"+version+"`-only unsigned-Windows exception",
|
||||
"For the active stable `v"+version+"` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `"+version+"`",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -488,7 +488,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.unsigned_windows_exception) }}",
|
||||
"require_windows_signing: ${{ !contains(inputs.version, '-') && !((inputs.version == '6.1.0' || inputs.version == '6.1.1') && inputs.unsigned_windows_exception) }}",
|
||||
workflow,
|
||||
)
|
||||
self.assertIn("unsigned_windows_exception:", workflow)
|
||||
@@ -669,7 +669,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 != "6.1.0"', resolver)
|
||||
self.assertIn('version not in {"6.1.0", "6.1.1"}', resolver)
|
||||
self.assertIn("not Authenticode-signed", resolver)
|
||||
self.assertIn("windows_signing_backend: signpath", content)
|
||||
self.assertIn('if [[ "$REQUIRE_WINDOWS_SIGNING" == "true" ]]', candidate_workflow)
|
||||
@@ -1124,6 +1124,10 @@ class ReleasePromotionPolicyTest(unittest.TestCase):
|
||||
self.assertNotIn(".createdAt >= $cutoff", helper)
|
||||
self.assertIn("gh workflow run create-release.yml", helper)
|
||||
self.assertIn("gh workflow run \"$WORKFLOW\"", helper)
|
||||
self.assertIn("--unsigned-windows-exception-reason", helper)
|
||||
self.assertIn("--unsigned-windows-exception", helper)
|
||||
self.assertIn("unsigned_windows_exception", helper)
|
||||
self.assertIn("unsigned_windows_reason", helper)
|
||||
self.assertIn("Single-Build Release Path", policy)
|
||||
self.assertIn("Routine Stable Patch Path", policy)
|
||||
self.assertIn("single publish workflow performs the exact-SHA preflight", normalize_ws(policy))
|
||||
|
||||
@@ -245,10 +245,10 @@ def resolve_metadata(
|
||||
promotion_mode = "prerelease" if is_prerelease else "stable-rc-promotion"
|
||||
|
||||
if unsigned_windows_exception:
|
||||
if version != "6.1.0":
|
||||
if version not in {"6.1.0", "6.1.1"}:
|
||||
raise ValueError(
|
||||
"unsigned_windows_exception is approved only for stable v6.1.0. "
|
||||
"Later stable releases must restore Windows Authenticode signing."
|
||||
"unsigned_windows_exception is approved only for stable v6.1.0 or v6.1.1. "
|
||||
"Stable v6.1.2 and later must restore Windows Authenticode signing."
|
||||
)
|
||||
if not unsigned_windows_reason:
|
||||
raise ValueError(
|
||||
@@ -256,7 +256,7 @@ def resolve_metadata(
|
||||
)
|
||||
if release_notes and "not authenticode-signed" not in release_notes.lower():
|
||||
raise ValueError(
|
||||
"Stable v6.1.0 release_notes must disclose that Windows binaries are not Authenticode-signed."
|
||||
f"Stable v{version} release_notes must disclose that Windows binaries are not Authenticode-signed."
|
||||
)
|
||||
elif unsigned_windows_reason:
|
||||
raise ValueError(
|
||||
|
||||
@@ -171,12 +171,41 @@ class ResolveReleasePromotionTest(unittest.TestCase):
|
||||
"Release owner accepted the Windows unknown-publisher warning for v6.1.0.",
|
||||
)
|
||||
|
||||
def test_v611_owner_exception_allows_disclosed_emergency_patch(self) -> None:
|
||||
metadata = resolver.resolve_metadata(
|
||||
version="6.1.1",
|
||||
promoted_from_tag_input="",
|
||||
rollback_version_input="v6.1.0",
|
||||
ga_date_input="",
|
||||
v5_eos_date_input="",
|
||||
hotfix_exception=True,
|
||||
hotfix_reason_input="Active customer update harm.",
|
||||
release_notes_input=(
|
||||
"Windows Unified Agent binaries are not Authenticode-signed for v6.1.1."
|
||||
),
|
||||
unsigned_windows_exception=True,
|
||||
unsigned_windows_reason_input=(
|
||||
"Release owner accepted the Windows unknown-publisher warning for v6.1.1."
|
||||
),
|
||||
list_stable_tags_fn=lambda: ["v6.1.0", "v6.0.5"],
|
||||
list_same_version_rc_tags_fn=lambda version: [],
|
||||
changed_paths_fn=lambda tag: ["install.sh"],
|
||||
tag_exists_fn=lambda tag: tag == "v6.1.0",
|
||||
tag_commit_fn=lambda tag: "v610-commit",
|
||||
head_descends_from_fn=lambda commit: commit == "v610-commit",
|
||||
)
|
||||
|
||||
self.assertEqual(metadata["promotion_mode"], "emergency-stable-patch")
|
||||
self.assertEqual(metadata["rollback_tag"], "v6.1.0")
|
||||
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"):
|
||||
with self.assertRaisesRegex(ValueError, "approved only for stable v6.1.0 or v6.1.1"):
|
||||
resolver.resolve_metadata(
|
||||
version="6.1.1",
|
||||
version="6.1.2",
|
||||
promoted_from_tag_input="",
|
||||
rollback_version_input="v6.1.0",
|
||||
rollback_version_input="v6.1.1",
|
||||
ga_date_input="",
|
||||
v5_eos_date_input="",
|
||||
hotfix_exception=True,
|
||||
|
||||
@@ -6,6 +6,7 @@ VERSION=""
|
||||
MOBILE_RELEASE_DECISION=""
|
||||
MOBILE_RELEASE_EVIDENCE=""
|
||||
HOTFIX_REASON=""
|
||||
UNSIGNED_WINDOWS_REASON=""
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
@@ -20,6 +21,8 @@ Options:
|
||||
--mobile-release-decision VALUE Override the inferred mobile decision.
|
||||
--mobile-release-evidence VALUE Evidence for a mobile compatibility decision.
|
||||
--emergency-hotfix-reason VALUE Bypass an RC-required risk with an explicit reason.
|
||||
--unsigned-windows-exception-reason VALUE
|
||||
Use an approved version-bound unsigned Windows exception.
|
||||
-h, --help Show this help.
|
||||
EOF
|
||||
}
|
||||
@@ -42,6 +45,10 @@ while [ "$#" -gt 0 ]; do
|
||||
HOTFIX_REASON="${2:?--emergency-hotfix-reason requires a value}"
|
||||
shift 2
|
||||
;;
|
||||
--unsigned-windows-exception-reason)
|
||||
UNSIGNED_WINDOWS_REASON="${2:?--unsigned-windows-exception-reason requires a value}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
@@ -111,6 +118,14 @@ if [ -n "$HOTFIX_REASON" ]; then
|
||||
HOTFIX_EXCEPTION="true"
|
||||
RESOLVER_ARGS+=(--hotfix-exception --hotfix-reason "$HOTFIX_REASON")
|
||||
fi
|
||||
UNSIGNED_WINDOWS_EXCEPTION="false"
|
||||
if [ -n "$UNSIGNED_WINDOWS_REASON" ]; then
|
||||
UNSIGNED_WINDOWS_EXCEPTION="true"
|
||||
RESOLVER_ARGS+=(
|
||||
--unsigned-windows-exception
|
||||
--unsigned-windows-reason "$UNSIGNED_WINDOWS_REASON"
|
||||
)
|
||||
fi
|
||||
|
||||
PROMOTION_METADATA="$(python3 scripts/release_control/resolve_release_promotion.py "${RESOLVER_ARGS[@]}")"
|
||||
ROLLBACK_TAG="$(awk -F= '$1 == "rollback_tag" {print $2}' <<<"$PROMOTION_METADATA")"
|
||||
@@ -150,6 +165,8 @@ if [ "$MODE" = "dry-run" ]; then
|
||||
--require v5_eos_date \
|
||||
--require hotfix_exception \
|
||||
--require hotfix_reason \
|
||||
--require unsigned_windows_exception \
|
||||
--require unsigned_windows_reason \
|
||||
--require note \
|
||||
--require mobile_release_decision \
|
||||
--require mobile_release_evidence
|
||||
@@ -163,6 +180,8 @@ if [ "$MODE" = "dry-run" ]; then
|
||||
-f v5_eos_date="" \
|
||||
-f hotfix_exception="$HOTFIX_EXCEPTION" \
|
||||
-f hotfix_reason="$HOTFIX_REASON" \
|
||||
-f unsigned_windows_exception="$UNSIGNED_WINDOWS_EXCEPTION" \
|
||||
-f unsigned_windows_reason="$UNSIGNED_WINDOWS_REASON" \
|
||||
-f note="Stable patch preflight for ${VERSION} at ${LOCAL_SHA}" \
|
||||
-f mobile_release_decision="$MOBILE_RELEASE_DECISION" \
|
||||
-f mobile_release_evidence="$MOBILE_RELEASE_EVIDENCE"
|
||||
@@ -182,6 +201,8 @@ else
|
||||
--require v5_eos_date \
|
||||
--require hotfix_exception \
|
||||
--require hotfix_reason \
|
||||
--require unsigned_windows_exception \
|
||||
--require unsigned_windows_reason \
|
||||
--require draft_only \
|
||||
--require mobile_release_decision \
|
||||
--require mobile_release_evidence
|
||||
@@ -195,6 +216,8 @@ else
|
||||
--arg v5_eos_date "" \
|
||||
--argjson hotfix_exception "$HOTFIX_EXCEPTION" \
|
||||
--arg hotfix_reason "$HOTFIX_REASON" \
|
||||
--argjson unsigned_windows_exception "$UNSIGNED_WINDOWS_EXCEPTION" \
|
||||
--arg unsigned_windows_reason "$UNSIGNED_WINDOWS_REASON" \
|
||||
--argjson draft_only false \
|
||||
--arg mobile_release_decision "$MOBILE_RELEASE_DECISION" \
|
||||
--arg mobile_release_evidence "$MOBILE_RELEASE_EVIDENCE" \
|
||||
@@ -207,6 +230,8 @@ else
|
||||
v5_eos_date: $v5_eos_date,
|
||||
hotfix_exception: $hotfix_exception,
|
||||
hotfix_reason: $hotfix_reason,
|
||||
unsigned_windows_exception: $unsigned_windows_exception,
|
||||
unsigned_windows_reason: $unsigned_windows_reason,
|
||||
draft_only: $draft_only,
|
||||
mobile_release_decision: $mobile_release_decision,
|
||||
mobile_release_evidence: $mobile_release_evidence
|
||||
|
||||
Reference in New Issue
Block a user