Commit Graph

33 Commits

Author SHA1 Message Date
pulse-triage[bot] 8d8a1790ad Refuse incomplete updater manager observations
Keep stderr and trailing blank records in service-state and running-PID admission. Incomplete reads must not authorise installation, restart, rollback or update success. Require production caller and real-process controls for both read boundaries; preserve existing recovery, trust and deadlines.

Change-source: pulse-maintainer
2026-10-14 11:58:09 +01:00
pulse-triage[bot] c1139b83ec Bound unattended installer downloads before signed execution
Give each installer and signature transfer a five-second connection and sixty-second total budget, ignore ambient curl settings and preserve HTTPS through redirects. Failed or partial downloads leave the prior install, service and identity unchanged; pinned signature admission and recovery deadlines are unchanged.

Change-source: pulse-maintainer
2026-10-13 22:15:02 +01:00
pulse-triage[bot] b3b368c21b Admit silent unit absence without losing inventory failures
Adapt rcourtman’s Pulse PR2855 (aef53d0d3e), which diagnosed systemd’s silent exit-one absence. The original contributor commit is unchanged and explicitly credited, not imported, amended or re-parented in this maintainer candidate.

One bounded stdout/stderr observation accepts genuine absence but retains failed first reads, other statuses and blank-line output. Include the existing registered installer/updater verification hooks, real-empty-root controls and missing-unit recovery double in this same source commit. This replaces the rejected foreign-history composition with a normal maintainer-reviewed implementation; no provenance policy, credential or host installation changes.

Source-attribution: rcourtman, https://github.com/rcourtman/Pulse/pull/2855, aef53d0d3e
Change-source: pulse-maintainer
2026-10-12 03:15:49 +01:00
pulse-triage[bot] 7eb12d0bf5 Require running executable proof for unattended update success
An installed target version and active service can conceal an old managed executable. Compare the actual process bytes between complete bounded MainPID observations before accepting an update or restored active service. Retain the backup and current service on uncertainty without an automatic restart or rollback grant. Register real owned-process and conditional transaction controls; keep synthetic/native and customer acceptance distinct.

Change-source: pulse-maintainer
2026-10-11 12:53:23 +01:00
pulse-triage[bot] a8fadc30e4 Retain real unattended updater log-sink failures
Conditional Bash callers hid a failed logger write behind successful stdout. Attempt both sinks, return the first failed sink, and exercise the unchanged draining collector and recovery path with the real log primitive and confined external logger. Preserve the distinction between observed pipeline completion and native or customer recovery.

Change-source: pulse-maintainer
2026-10-11 11:22:21 +01:00
pulse-triage[bot] a04c246adf Keep updater collector failures and final installer evidence
Drain the installer pipe after a failed log write, retain its first observed failure across later successes and collect an unterminated final line. Reuse the guarded restoration path without changing signed-input, service-state, mask or prior-activity safeguards; bind the regression controls to package acceptance.

Change-source: pulse-maintainer
2026-10-10 17:15:39 +01:00
pulse-triage[bot] 74a8d0d05a Record unattended installer and log-collector exits separately
Capture both pipeline statuses before logging overwrites them. Keep recovery, signature and prior-service safeguards unchanged; cover installer, collector, simultaneous and successful observations without attributing a past host interruption.

Change-source: pulse-maintainer
2026-10-10 13:52:14 +01:00
pulse-triage[bot] 9060dbd54d Refuse unattended recovery on uncertain systemd service state
Read bounded, complete unit state before mutation and confirm inactive state before rollback replacement. Keep the verified backup and stop automatic recovery when service state cannot be reconciled; preserve prior-active restoration, masks, signatures and configuration.

Exercise failed/partial reads, deadlines, no-op stops and restoration through confined production-shell fixtures and the existing signed transaction controls. Fix fixture path and manager observations so registered Go controls execute the actual source.

Refs: #2785
Change-source: pulse-maintainer
2026-10-10 12:06:24 +01:00
pulse-triage[bot] 4e79e047f4 Bind unattended updater service discovery before installer handoff
The helper selects and passes an explicit service name, bypassing installer discovery. Apply the same bounded exact-unit admission there and preserve its error before any prior-active query, backup, installer call or restart trap. Execute both producers and the real helper handoff in the registered unattended updater proof artifact.

Refs: #2785
Change-source: pulse-maintainer
2026-10-10 11:14:58 +01:00
pulse-triage[bot] 18df4c1b46 Require executable version evidence after unattended updates
Reject successful installers whose replacement cannot identify itself as the target community runtime. VERSION metadata and failed or unrecognised probes cannot establish acceptance; retain the existing verified rollback and prior-active restoration. Exercise the complete locally signed installer transaction and bounded executable read.

Change-source: pulse-maintainer
2026-10-07 20:04:44 +01:00
pulse-triage[bot] 01b910fcda Bind unattended updates to complete stable release objects
Replace line-oriented release admission with object-bound JSON maturity checks. Refuse missing flags, mixed sibling fields, incomplete payloads and redirect-only discovery; bound both API reads without ambient curl configuration. Preserve highest-stable selection, confirmed latest fallback and all existing installation/rollback gates.

Change-source: pulse-maintainer
2026-10-07 17:42:05 +01:00
pulse-triage[bot] 2dbee5639a Stop unidentified editions entering community auto-updates
Require a successful bounded executable identity probe before release discovery. Keep Pro and unknown runtime editions untouched even when VERSION offers a usable community version, and do not defer a broken primary binary to a legacy one. Exercise the real shell classifier and main boundary with adverse controls and a TERM-resistant deadline.

Change-source: pulse-maintainer
2026-10-07 16:39:25 +01:00
pulse-triage[bot] eafd744e1e Require complete top-level consent before unattended updates
Text matching admitted truncated configuration, nested opt-in and padded RC channels. Parse one configuration object with the installed jq dependency and fail closed before downloads when consent cannot be verified. Preserve the legacy no-config timer opt-in, manual updates and disabled-timer gate; add executed-shell regression cases and the deployment contract.

Change-source: pulse-maintainer
2026-10-07 14:31:37 +01:00
pulse-triage[bot] 3e69c6706c Preserve archive metadata during verified updater recovery
Keep the original archive-copy metadata semantics while checking every snapshot and restore. A content-only copy would lose extended attributes. Exercise that recovery and reject a non-regular restored destination before byte comparison or activation; qualify the restart backstop comments for incomplete recovery.

Change-source: pulse-maintainer
2026-10-06 03:35:00 +01:00
pulse-triage[bot] 79d6ad642a Verify restored destinations before completing updater recovery
A successful rename is not by itself the recovered-byte postcondition. Keep the snapshot and suppress activation when the recorded destination is still a link or no longer matches the saved bytes; connected no-op and changed-destination controls exercise that boundary.

Change-source: pulse-maintainer
2026-10-06 03:09:38 +01:00
pulse-triage[bot] cf92426ec1 Keep rollback replacement portable and model its stop boundary
Reject directory destinations before the same-directory file rename, use portable mode inspection in the connected transaction tests, and teach the existing service fakes that stopping and failed activation are separate operations. The recorded first candidate proof remains bound to its own source.

Contract-Neutral: Preserve the reviewed backup and rollback semantics; portable utility invocation and faithful test boundary only.
Change-source: pulse-maintainer
2026-10-06 03:07:35 +01:00
pulse-triage[bot] 329f2b00c4 Keep a verified recovery path through unattended update failures
The conditional updater caller disables errexit, but binary and VERSION backups and restore copies were best-effort and their only backup was deleted even when recovery failed. Require a private verified snapshot before installer execution, consolidate the three rollback branches, stage exact original paths and absence, and retain the backup without automatic activation when recovery is incomplete. Exercise the complete signed offline path and prior-active-only service recovery.

Change-source: pulse-maintainer
2026-10-06 03:05:00 +01:00
pulse-triage[bot] 564c235e32 fix(update): disarm perform_update RETURN trap after it runs
A RETURN trap is not scoped to the function that installs it. perform_update
left its trap referencing function-local installer_tmp/signature_tmp (and
service_name/service_was_active) installed, so it re-ran when a later function
returned. With those locals gone and 'set -u' active, the updater aborted with
'installer_tmp: unbound variable' immediately after logging 'Auto-update check
completed' — pulse-update.service entered failed state even though the update
had succeeded (reported #2128, affects v6.3.2/v6.4.1).

Disarm the trap with 'trap - RETURN' on its first invocation, and use
${installer_tmp:-}/${signature_tmp:-} so a stray invocation cannot abort the
script. Add a regression test asserting no RETURN trap remains after both the
successful and the prerelease-refusal paths.

Change-source: pulse-maintainer
2026-09-20 17:42:19 +01:00
courtmanr@gmail.com 806cbe83dc Fix auto-update leaving service down after installer failure
Two bugs from #1630 that combined to take installs down silently:

1. perform_update()'s install-failed rollback branch restored the backup
   but never restarted pulse.service. Since the generated
   pulse-update.service gates on ExecCondition=systemctl is-active,
   every later timer run was then skipped and the install stayed down
   until manual intervention. Restart is now guaranteed by a
   service_was_active-guarded restart in that branch plus an
   ensure_service_restarted RETURN trap so no exit path can miss it
   (re-fix of #1323, originally c0b3a0e66, lost in 778a2577b and only
   partially restored in 672e81985).

2. install.sh aborted under errexit when writing the /bin/update helper
   on a read-only filesystem - after the new binary was installed and
   the service stopped, landing in bug 1's no-restart branch. The stock
   pulse-update.service uses ProtectSystem=strict, so /bin and
   /usr/local/bin are read-only on stock unattended updates; transient
   read-only remounts hit the same path. The helper write, PATH
   appends, and the /usr/local/bin/pulse symlink are now idempotent and
   non-fatal with a warning (install_binary_symlink).

Contract: deployment-installability now pins fail-closed service
availability for unattended updates and non-fatal writes outside the
hardened unit's writable set, with proofs in pulse_auto_update_test.go
and root_install_sh_test.go plus shell regression coverage in
scripts/tests/test-pulse-auto-update.sh (installer-exits-nonzero path)
and scripts/tests/test-install-update-resilience.sh (read-only helper
and symlink paths, verified under set -e, root-safe via ENOTDIR).

Fixes #1630

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 09:38:37 +01:00
rcourtman 6351fd6526 fix(updates): select releases by highest version, not GitHub list order
Production telemetry (7d, 2026-07-17) shows a persistent tail of live
installs on 6.0.0-rc.x and 6.0.3/6.0.4 while 6.0.5 has been stable since
2026-07-09. Root cause for the reachable stranding class: release
selection trusted GitHub's created_at ordering, and this repo interleaves
v5-line maintenance releases with v6 releases (v5.1.36 was created the
day before v6.0.5). Whenever a v5.1.x release is the most recently
created stable:

- stable channel (getLatestReleaseForChannel) returned the first
  non-prerelease in list order -> "no update" for every v6 install
  until the next v6 release ships
- the RSS rate-limit fallback returned the first feed entry matching the
  channel, same failure, both channels
- the unattended updater trusted /releases/latest, which GitHub defines
  as most-recently-created stable -> timer no-ops in the same window

All three now select the highest eligible version: the API path tracks
newest stable + newest prerelease in one pass (prerelease = GitHub flag
OR tag shape), the feed fallback picks the max matching the channel, and
pulse-auto-update.sh scans /releases pairing each tag with its own
draft/prerelease flags before the fail-closed shape filter, keeping
/releases/latest as fallback. helm-chart-* tags fail semver parsing and
are dropped everywhere.

Verified not broken (pinned by new tests): rc-channel installs are
offered the newer stable (6.0.0-rc.6 -> 6.0.5) and move onto the next rc
line when one opens (-> 6.1.0-rc.2); the auto-update prerelease filter
(fail-closed is_prerelease_tag, metadata-flag refusal) still refuses
prerelease targets on stable. Go tests fail on the pre-fix code
(returned 5.1.37 / "no update").

Contract: deployment-installability now pins version-max release
selection with proofs in manager_stranded_upgrade_test.go and
pulse_auto_update_test.go.
2026-07-17 23:21:49 +01:00
rcourtman 93bccaff18 Update the Pro binary in-app from the license server download broker
The in-app updater and the unattended timer both target the public
rcourtman/Pulse community assets, so a Pro install that used them was
silently downgraded to community. Guard 2 (983a89326) blocked in-app
apply on the Pro edition, which stopped the downgrade but left Pro
installs with no update path except manual portal downloads. That
friction is a plausible driver of the runtime split: as of 2026-07-08
only 10 of 66 active paid licenses have any Pro-runtime install.

Root fix: the compiled Pro binary now checks and applies updates
through the license server download broker (GET /v1/downloads/pulse-pro
with the installation token and instance fingerprint). The check
compares against the broker's pinned private release instead of GitHub,
respecting the stable/rc channel guard. Apply re-resolves fresh signed
R2 URLs at apply time, verifies the archive against the same pinned
pulse-installer SSHSIG key plus the broker manifest sha256, and refuses
GitHub-shaped download URLs outright. An unactivated Pro binary still
refuses with the portal fallback. The community edition path is
unchanged.

The update banner restores in-app apply for auto-updatable Pro
deployments and keeps the portal instructions for deployments the
updater cannot drive (Docker). scripts/pulse-auto-update.sh now skips
when the installed binary reports Pulse Pro so the unattended timer can
never reinstall community over Pro.

Note: internal/updates/pro_update.go and manager_pro_update_test.go for
this change landed one commit early inside 313552deb via a parallel
session committing a shared staged index; this commit completes the
wiring they belong to.
2026-07-08 23:39:37 +01:00
rcourtman 672e819850 Verify service restart in unattended auto-update; roll back if down (#1323)
Back-port the pulse-auto-update.sh half of v5 fix 0f2982ce3 to v6. After a
verified update, if Pulse was running beforehand, wait_for_service_active
polls up to 20s, tries one explicit start, and if it still does not come
back up restores the backup binary/VERSION, restarts, and returns failure
instead of leaving Pulse stopped (common on unprivileged LXC where the
installer's restart silently fails). Adds a BASH_SOURCE guard so the
script can be sourced, plus scripts/tests/test-pulse-auto-update.sh.

Note: the install.sh start_pulse STOPPED_PULSE_SERVICE guard (interactive
installer path) still needs the stop-tracking infrastructure wired into
v6's update flow; tracked as a follow-up.
2026-06-04 09:07:24 +01:00
rcourtman d6e96ebeca Fix v6 demo release signing key deployment 2026-05-05 21:40:14 +01:00
rcourtman a2c101379a Guard stable updater from prerelease tags
Refuse prerelease-shaped tags and explicit GitHub prerelease responses in the unattended stable updater before installer invocation.

Add installability tests and proof routing for the auto-update prerelease refusal guard.
2026-04-25 23:49:27 +01:00
rcourtman ce95ef1fc6 Require signed server installer updates 2026-04-22 15:41:54 +01:00
rcourtman 58ad221d47 Add governed v6 preview demo targets 2026-04-10 10:53:17 +01:00
rcourtman 2c1b90cc4e Reframe prerelease update copy 2026-03-25 11:25:41 +00:00
rcourtman 778a2577b6 feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
rcourtman c0b3a0e665 Restart Pulse service after failed auto-update (#1323)
The auto-update flow stops the Pulse service before applying updates.
If the update fails, the rollback path restored files but never
restarted the service. Since the main unit was explicitly stopped
(not crashed), systemd's Restart=always didn't rescue it.

Add restart-on-failure guards to both pulse-auto-update.sh and
install.sh so Pulse is always restarted after a failed update attempt.
2026-03-07 10:46:19 +00:00
rcourtman 6853a0ffd1 feat: serve install scripts from GitHub releases instead of main branch
Scripts like install.sh and install-sensor-proxy.sh are now attached
as release assets and downloaded from releases/latest/download/ URLs.
This ensures users always get scripts compatible with their installed
version, even while development continues on main.

Changes:
- build-release.sh: copy install scripts to release directory
- create-release.yml: upload scripts as release assets
- Updated all documentation and code references to use release URLs
- Scripts reference each other via release URLs for consistency
2025-11-26 08:59:59 +00:00
rcourtman 6eb1a10d9b Refactor: Code cleanup and localStorage consolidation
This commit includes comprehensive codebase cleanup and refactoring:

## Code Cleanup
- Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate)
- Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo)
- Clean up commented-out code blocks across multiple files
- Remove unused TypeScript exports (helpTextClass, private tag color helpers)
- Delete obsolete test files and components

## localStorage Consolidation
- Centralize all storage keys into STORAGE_KEYS constant
- Update 5 files to use centralized keys:
  * utils/apiClient.ts (AUTH, LEGACY_TOKEN)
  * components/Dashboard/Dashboard.tsx (GUEST_METADATA)
  * components/Docker/DockerHosts.tsx (DOCKER_METADATA)
  * App.tsx (PLATFORMS_SEEN)
  * stores/updates.ts (UPDATES)
- Benefits: Single source of truth, prevents typos, better maintainability

## Previous Work Committed
- Docker monitoring improvements and disk metrics
- Security enhancements and setup fixes
- API refactoring and cleanup
- Documentation updates
- Build system improvements

## Testing
- All frontend tests pass (29 tests)
- All Go tests pass (15 packages)
- Production build successful
- Zero breaking changes

Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
2025-11-04 21:50:46 +00:00
rcourtman b929fdcc6e feat: improve source build installation experience
- Remove confusing --main flag, use --source for clarity
- Fix timeout issues when building from source in LXC containers
  - Increase timeout from 5min to 20min for source builds
  - Add PULSE_CONTAINER_TIMEOUT env var for custom timeouts
  - Support PULSE_CONTAINER_TIMEOUT=0 to disable timeout
- Fix misleading "Latest version: vX.X.X" message during source builds
- Update documentation to use --source instead of --main
- Simplify auto-update script logic for source builds

Changes:
- install.sh: Check BUILD_FROM_SOURCE early to skip version detection
- install.sh: Adaptive timeout (300s binary, 1200s source builds)
- install.sh: Better timeout error messages with recovery instructions
- README.md: Replace --main with --source in examples
- docs/INSTALL.md: Replace --main with --source in examples
- scripts/pulse-auto-update.sh: Remove --main special case
2025-10-21 08:57:29 +00:00
rcourtman f46ff1792b Fix settings security tab navigation 2025-10-11 23:29:47 +00:00