Commit Graph

734 Commits

Author SHA1 Message Date
pulse-triage[bot] b6618c19a3 Preserve each configuration-backup safety control's deadline
The containing installer suite exhausted a single 30-second Python-class budget after eleven controls and killed the last. Use the existing serial discovery runner with all twelve required methods, retaining each control's 30-second bound and the existing inner shell bounds rather than treating cumulative class time as a safety deadline.

Change-source: pulse-maintainer
2026-10-25 06:49:45 +00:00
pulse-triage[bot] 5d748986b3 Keep native recovery proof aligned with bounded manual downloads
Admit only the manual helper's exact new curl envelope in the existing closed transport fixture. Require a signed emitted-helper round trip and reject altered deadlines, retries and TLS flags through the registered installer suite; do not widen the adapter or execute a native journey.

Change-source: pulse-maintainer
2026-10-25 06:38:18 +00:00
pulse-triage[bot] b239891b75 Bound signed manual-update bootstrap downloads
Keep both bootstrap requests within curl's connection and whole-request deadlines, without ambient retry settings. Arm cleanup before allocation so a second mktemp failure cannot strand the first input. Exercise the emitted helper's signed success, partial download failures, allocation failures and signature rejection without native or production execution.

Change-source: pulse-maintainer
2026-10-25 06:33:50 +00:00
pulse-triage[bot] 7b64d9b66d Keep real NAS process-inventory controls serial
The first exact-source parallel attempt failed the generated Unraid and QNAP watchdog control. Its real machine-wide process observation is not isolated by private fixture files. Preserve the entire NAS class's serial execution and make concurrency explicit only for the seven modelled-inventory classes. The regression now proves that the serial helper still preserves ordering, as well as bounded parallelism and complete failure/skip/cleanup evidence.

Contract-Neutral: Test-only fixture scheduling; real NAS observations, production manager deadlines, process ownership checks and required test coverage are unchanged.
Change-source: pulse-maintainer
2026-10-25 01:15:42 +00:00
pulse-triage[bot] d291080a8f Run isolated installer safety controls within Go's parallel budget
Current successful public CI puts the installer package on the backend critical path for 683-764 seconds. Each registered Python method already owns a separate process and private fixtures; run those methods through the existing Go parallel scheduler, starting their unchanged deadlines only after admission. Keep exhaustive discovery and exact non-skipped method verdicts, with connected parallel, serial, failure, skip and cleanup controls.

Contract-Neutral: Test-only scheduling of already isolated fixture processes; no installer, runtime, service deadline, source selection, required check or native acceptance contract changes.
Change-source: pulse-maintainer
2026-10-25 01:51:34 +01:00
courtmanr@gmail.com c4486a177a Keep a real change out of the Highlights example
The Highlights guidance used "Resource Overview shows alerts, recent
trends and longer history together" as its example. That is a real
v6.6.0 change, and a test draft of the v6.6.0 notes copied it almost
word for word, so a later release could repeat it as if it were new.

The generator and the release-notes template now describe the shape
instead, the page or feature and then what it now does, and say to
describe only changes in this release. The slogan counterexamples stay,
and the release-assets test pins the new sentence.
2026-10-24 20:43:52 +01:00
rcourtman 97f55638c9 Prove demo auto sign-in in the public browser smoke (#3204)
Since v6.5.0 demo mode signs a fresh visitor in with the published
demo credentials, so the login form never stays on screen for a first
visit. The browser smoke still waited two minutes for that form and
failed, which blocked every stable demo convergence once the Tailscale
step worked again. It went unnoticed because the demo update had not
got past Tailscale since v6.5.0 shipped.

The smoke now proves the visitor's real path, a fresh tab reaching the
connected workspace, when the server reports demo mode. A second
context sets the frontend's own pulse-demo-auto-login marker to keep
proving the login form and a manual demo sign-in. Against the live
demo the old script times out and the new one passes both phases. The
policy test pins the marker to localStorage.ts so a rename fails in
source checks rather than on the live demo.
2026-10-24 15:06:41 +01:00
rcourtman 572930fded Make release Highlights name concrete changes (#3203)
Make release Highlights name concrete changes

The generator only asked for "one to three plain-text outcomes", so it
produced slogans such as "See problems, recent trends and longer
history together" that tell a user nothing about what changed. These
lines are what the update banner shows before someone installs.

The generator prompt and the release-notes template now ask for the
release's biggest specific changes and where users find them, with an
example and named anti-examples, and the release-assets test pins that
wording. Their description of the post-update modal also follows the
new plain changelog, which no longer collapses upgrade notes or puts
Highlights above the changes.
2026-10-24 14:45:36 +01:00
rcourtman df79b7716a Prove demo auto sign-in in the public browser smoke
Since v6.5.0 demo mode signs a fresh visitor in with the published
demo credentials, so the login form never stays on screen for a first
visit. The browser smoke still waited two minutes for that form and
failed, which blocked every stable demo convergence once the Tailscale
step worked again. It went unnoticed because the demo update had not
got past Tailscale since v6.5.0 shipped.

The smoke now proves the visitor's real path, a fresh tab reaching the
connected workspace, when the server reports demo mode. A second
context sets the frontend's own pulse-demo-auto-login marker to keep
proving the login form and a manual demo sign-in. Against the live
demo the old script times out and the new one passes both phases. The
policy test pins the marker to localStorage.ts so a rename fails in
source checks rather than on the live demo.
2026-10-24 14:31:21 +01:00
courtmanr@gmail.com 842dbda6b8 Make release Highlights name concrete changes
The generator only asked for "one to three plain-text outcomes", so it
produced slogans such as "See problems, recent trends and longer
history together" that tell a user nothing about what changed. These
lines are what the update banner shows before someone installs.

The generator prompt and the release-notes template now ask for the
release's biggest specific changes and where users find them, with an
example and named anti-examples, and the release-assets test pins that
wording. Their description of the post-update modal also follows the
new plain changelog, which no longer collapses upgrade notes or puts
Highlights above the changes.
2026-10-24 14:06:27 +01:00
rcourtman 1ffa17a10c Merge remote-tracking branch 'origin/main' into fix/demo-tailnet-ci-deploy-client 2026-10-24 13:28:42 +01:00
pulse-triage[bot] 06475a9d37 Keep bounded hosted provisioning overhead in chart SLO verdicts (#3199)
Retained hosted samples include both an over-budget failure and an
under-budget pass with one provisioning agent occupying about one
logical CPU. Attribute only that bounded Actions overhead; retain raw
CPU and absolute 90 ms latency, and keep other or unattributed CPU,
guest, steal and swap invalidating. Exercise the real CLI and workflow
shells with adverse controls; no timed workload or release acceptance is
claimed.

---
Fleet candidate `20261024T104012Z-delivery-trust` from the
`delivery-trust` lane. Reviewed tip
`fbe410e244f3d44b44de258c6f3db68dabd257da` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-24 12:27:42 +00:00
rcourtman bc39aa5908 Move demo deploys to the tag:ci-deploy Tailscale client
The demo update and recovery workflows still joined the tailnet with
the July 2026 tag:infra OAuth client. That client was revoked on 30
September, when the private repositories moved to narrow clients, and
the public repository was missed. Since then every demo convergence
step has failed with an OAuth 401, so stable releases cannot converge
and the hourly reconcile keeps retrying v6.5.0.

Both workflows now use the TS_CI_DEPLOY_OAUTH_* binding that the
browser update qualification already expects, restricted to
tag:ci-deploy. The tailnet policy already grants that tag SSH to
pulse-relay, the demo host, so no policy change is needed. One narrow
client now serves all three workflows, and the broad tag:infra
identity is gone from this repository.
2026-10-24 13:25:23 +01:00
pulse-triage[bot] fbe410e244 Compose chart SLO repair without dropping current administrative guarantees
Resolve adjacent contract append conflicts by keeping bounded hosted-agent classification in its chart section and preserving all newer SSO, RBAC and uninstall guarantees. Runtime, workflow and synthetic chart controls merge without conflict; no latency budget or customer journey changes.

Change-source: pulse-maintainer
2026-10-24 11:42:23 +01:00
rcourtman c7ac6ac86a Pin the Pro promotion terminal annotation where it now lives
The promotion caller now owns the terminal failure annotation, so a
re-dispatched refusal leaves none behind. The release-asset contract
test still pinned the old annotation inside wait_for_workflow. It now
pins the caller's annotation and the source-check refusal gate.
2026-10-24 11:42:17 +01:00
pulse-triage[bot] b25c22c00f Keep bounded hosted provisioning overhead in chart SLO verdicts
Retained hosted samples include both an over-budget failure and an under-budget pass with one provisioning agent occupying about one logical CPU. Attribute only that bounded Actions overhead; retain raw CPU and absolute 90 ms latency, and keep other or unattributed CPU, guest, steal and swap invalidating. Exercise the real CLI and workflow shells with adverse controls; no timed workload or release acceptance is claimed.

Change-source: pulse-maintainer
2026-10-24 10:48:40 +01:00
rcourtman 27f7e11e9b Refuse Unraid uninstall while the rc.local go shell is live
Uninstall treats a live Unraid go shell as an unknown boot owner and
refuses, because that shell may still hold later boot lines in memory.
Signalling the watchdog would release it to run them. The check only
looked for /boot/config/go in a process whose name is a shell. Unraid's
rc.local never runs that path: it writes a fromdos copy to /var/tmp/go
(go.safemode in safe mode) and executes that copy directly. The kernel
then names the process "go", with argv "/bin/bash /var/tmp/go", so the
check never matched it.

Hosts installed before the detached go entry still have this shell
blocked on the old foreground wrapper line. On those hosts uninstall
classified the shell as unrelated, stopped the watchdog, and let go run
the rest of its in-memory script. That is the case the live-shell
refusal was added to prevent.

The role check now covers a go or go.safemode process, or a shell, that
has /boot/config/go, /var/tmp/go or a .safemode form as a whole
argument. The old substring match is gone, so near-miss paths such as
/var/tmp/gopher.sh no longer block removal, and a Go toolchain process
named go still reads as unrelated. The NAS teardown control covers the
rc.local spellings, and a new role-table test pins Unraid and QNAP.
Both fail against the previous install.sh.

A go file without a #! line is still not recognised. Bash runs it in a
forked copy of rc.local, and the contracts now say so.
2026-10-24 10:26:45 +01:00
pulse-triage[bot] f19424f51a Complete credited chart evidence reporting on current main (#3169)
Isolate the retained PR3095 completion (7f4ec192 and 93d87118) without
importing unrelated history. Keep the exact proposed Python classifier
and maintained chart shells, real CLI/workflow controls and dependent
contracts. Inconclusive capacity never establishes the 90 ms budget;
child, cleanup and malformed-proof failures remain errors.

Source-PR: https://github.com/rcourtman/Pulse/pull/3095
Source-Commit: b31fabd778
Co-authored-by: rcourtman <8825017+rcourtman@users.noreply.github.com>

---
Fleet candidate `20261024T010002Z-delivery-trust` from the
`delivery-trust` lane. Reviewed tip
`7e7cea87a6bce2e7a2e00e888a676c571e141d92` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-24 02:26:12 +00:00
rcourtman 4f3e170612 Detach the Unraid boot entry so later go lines run
The Unraid installer appended `bash <wrapper>` to /boot/config/go. The
wrapper is an endless watchdog loop, so that line never returned, and
rc.local never reached anything the user had placed after the Pulse
block. On a maintainer host a reboot skipped swap, a memory logger and a
hosts entry the agent needed to reach its server, and Pulse showed the
host as down for two days while it was healthy.

The entry now backgrounds the wrapper with its output redirected, so go
returns and holds no boot output pipe open. Install-time cleanup used to
delete every go line containing "pulse-agent", including log directories,
hosts entries and a co-installed agent. It now removes only the
installer's marker and command lines that name a start-pulse-agent.sh
wrapper or this runtime binary outside a comment, so upgrades from the
foreground or hand-edited entry still leave exactly one launch. Kept
lines lose a trailing CR, as Unraid's fromdos does before running go, and
a removal that would leave go unparseable is refused with a warning.
Uninstall admits the detached entry as well as the earlier foreground
form.

The new tests execute the go file the installer writes and require it to
return, release its output pipe and run the next line, with a planted
foreground entry as the control, and pin the narrowed cleanup against
the removal filter. The NAS teardown controls now render their Unraid
entry through the same emitter.
2026-10-24 00:34:31 +01:00
pulse-triage[bot] 8478eac3ef Complete credited chart evidence reporting on current main
Isolate the retained PR3095 completion (7f4ec192 and 93d87118) without importing unrelated history. Keep the exact proposed Python classifier and maintained chart shells, real CLI/workflow controls and dependent contracts. Inconclusive capacity never establishes the 90 ms budget; child, cleanup and malformed-proof failures remain errors.

Source-PR: https://github.com/rcourtman/Pulse/pull/3095
Source-Commit: b31fabd778
Co-authored-by: rcourtman <8825017+rcourtman@users.noreply.github.com>
Change-source: pulse-maintainer
2026-10-24 00:26:11 +01:00
pulse-triage[bot] b79496219f Preserve prior installer snapshots on retry
Reconcile the retained snapshot publication repair with current main without importing unrelated containing history. Unique private staging, no-clobber publication and failure-before-mutation protect earlier recovery copies; retain zero-retention and hardened-unit fallback semantics.

Retained-source: 854ea3c81a94ffe88145d663d25d5040d4637a47, 91bd7393fc4413b6629ad851f90c2c7f6c2c0991
Change-source: pulse-maintainer
2026-10-23 22:39:08 +01:00
rcourtman c909b4db79 Bound Unix teardown fixture controls independently
The macOS Intel native job killed the DSM Upstart suite at its single
one-minute alarm after sixteen controls had passed (main 39883120153,
PR 39952586718). Passing runs take 41s on Intel, 23s on ARM and 14s on
Linux, so the budget measured runner speed, not a stuck teardown. The
Legacy suite sits at 35s against the same alarm.

Run each discovered systemd, OpenRC, legacy and Upstart control through
the shared helper under its existing bound, as the NAS and TrueNAS suites
already do. Required controls stay mandatory, and skipped, absent or
failed controls still fail. Installer deadlines are unchanged.
2026-10-23 15:45:44 +01:00
rcourtman 02e53bc777 build: move to Go 1.26.10 and Vite 6.4.5 for October advisories
Go 1.26.10 (20 October) distrusts the compromised eMudhra intermediate
CAs in crypto/x509 (CVE-2026-111943). Binaries built with 1.26.9 still
accept chains through them, so every verified outbound TLS connection
Pulse makes (licence, updates, webhooks, AI providers) stays open to
interception by a holder of those keys. govulncheck does not flag a
trust-store change as a called symbol, so the scheduled scan stayed
green while the gap existed.

Advance the governed toolchain floor and every pin together: go.mod,
the toolchain installer and release-script guards, the source-built
container stages (manifest-list digests for golang:1.26.10-alpine and
the Debian dev container image), the root-pair diagnostic, and their
tests.

Vite 6.4.3 bundles a launch-editor with three advisories
(GHSA-587h-7wmj-h5pm, GHSA-r825-w8mm-5pxw, GHSA-698v-4r3x-3vcv) that
failed the daily advisory watch. 6.4.4 bundles the fixed launch-editor
and 6.4.5 adds the dev-server server.fs query check. Both reach only
the local dev server, not the built product. The lockfile changes only
the vite entry, and dependencySecurity.test.ts now pins the floor.
2026-10-21 15:19:02 +01:00
rcourtman 266144de1f Share native installer execution controls with script smoke tests
Script smoke still asserted the removed grouped runner while native
verification used a separate suite. Share the canonical execution controls
so both entrypoints reject lost checks, false passes and changed deadlines.
2026-10-18 17:55:06 +01:00
rcourtman 79a35fbe2e Give every native installer check its own process budget
Compile and discover one exact test binary per native workflow phase, then
execute every discovered root check independently. This removes inventory
growth from another check's ten-minute Go alarm while preserving fixture,
installer and overall CI job deadlines.

Retain exhaustive phase coverage and reject missing completion, failed checks,
unexpected exit zero and timeouts using real compiled Go execution controls.
Register the runner with deployment installability and retain the failed Intel
and advisory benchmark evidence in the existing reliability record.
2026-10-18 17:17:52 +01:00
rcourtman 0b3261e1aa Bound native fixture controls independently
The NAS suite exhausts its aggregate alarm after fifteen successful
controls on macOS Intel. Run each discovered NAS and updater control
under its existing bound, retaining the native phase's ten-minute alarm
and all installer operation deadlines.

Keep required controls mandatory and reject skipped, absent or failed
execution. Exercise discovery and false-pass rejection with real Python
controls, including a newly added method.
2026-10-18 15:40:55 +01:00
rcourtman 2fc54a5a1f Merge pending maintenance repairs with current main
Preserve selected memory freshness and the VM/LXC interpretation.
Retain both native tool contracts and current API concurrency controls.
Qualify this source separately from release and installed recovery.

Contract-Neutral: Integrate already-governed parents without a new contract change. Incoming verification files already match main. Fresh integration tests and source-bound browser proof cover the combined memory and installer surfaces.
2026-10-18 15:11:28 +01:00
courtmanr@gmail.com 92b784bef2 Keep reliability checks tied to workflows and selected tools
Require the existing troubleshooting jobs and their destinations without
making additional help entries break unrelated safety checks. Keep the
opening backup warning scoped to its actual entry point.

Run closed service and middleware models through the containing fixture's
selected Python interpreter without site startup. Retain every safety
scenario and deadline while qualifying the pending maintenance source.

Refs #2888

Contract-Neutral: Test-only navigation assertions and confined model interpreter selection. Production behavior and safety deadlines are unchanged.
2026-10-18 14:28:37 +01:00
rcourtman cce5ca2a7e Supply GNU ln to macOS Linux installer fixtures (#3020)
The non-required **Unified Agent Native Verification** workflow has
failed on `main` (and most PRs) in both macOS jobs since 12 Oct (first
failing main run 38285211868 on c3524d373a; last green 38273335159 on
552e838749). The single cause is
`TestInstallSHUpstartTeardownRequiresObservedQuiescence`: 13 Python
subtests in `agent_upstart_teardown.py` fail with `ln: illegal option --
T`.

`scripts/install.sh` uses `ln -T -- <pending> <override>` and `ln -T --
<retired> <conf>` in the DSM Upstart teardown (added in the DSM
retirement series, a7271f5840 / b7b0eb0b01). That path only runs on
Synology DSM (Linux), so the installer is correct. The harness runs
those functions with the host `ln`, which on macOS runners is BSD `ln`
without `-T`.

The workflow already supplies GNU `stat/chmod/chown/mv/tar` (plus Bash
5) for Linux-only installer fixtures on macOS. This adds `ln` to that
set and extends `TestNativeInstallerFixtureToolsAreRealAndStepLocal` to
require it (missing/non-GNU scenarios, PATH binding, and real `ln -T`
no-replacement checks against file and directory targets).

Verification:
- Reproduced locally on macOS: the harness fails 13/15 with BSD `ln` and
passes 15/15 when `ln -T` is available.
- `TestNativeInstallerFixtureToolsAreRealAndStepLocal`: fails against
the old workflow (real tools, missing ln, non-GNU ln) and passes with
this change (Linux).
- The macOS jobs themselves are only exercised by this PR's CI run.
2026-10-17 10:16:53 +01:00
rcourtman 5c3c7b8baa Make the Upstart teardown harness independent of umask (#3026)
`scripts/installtests/agent_upstart_teardown.py` created its fixture job
directory with a bare `mkdir`. Under a caller umask of 002 (the default
on Ubuntu hosts with user-private groups, pulse-dev included) that
directory came out 775. The installer's `trusted_lifecycle_regular_file`
check then correctly refused the fixture config, and running the harness
directly failed 23 subtests. The Go driver
`TestInstallSHUpstartTeardownRequiresObservedQuiescence` still passed,
because the installtests package already pins umask 022 for its children
(`umask_unix_test.go`). So the bug only shows up when the harness runs
on its own.

The fix gives the job directory an explicit 0755 mode. The sibling
TrueNAS and uninstall-state harnesses already create their trust-checked
directories with explicit modes. The production functions under test
still run with the caller's umask. They `chmod 644` what they write, so
nothing in production depends on umask.

Checked on pulse-dev (python3 3.12, go 1.26.5):

| run | umask 0002 | umask 0022 | umask 0077 |
| --- | --- | --- | --- |
| harness before | FAILED (failures=23, errors=1) | OK (15) | OK (15) |
| harness after | OK (15) | OK (15) | OK (15) |
| Go driver after | ok | ok | — |

The other Python harnesses in `scripts/installtests/` (legacy, OpenRC,
systemd, TrueNAS, uninstall-state) already pass under umask 0002, so
they are unchanged.

Test-only change.
2026-10-17 03:18:22 +01:00
rcourtman 0a7a9490d5 Fix action-runner setup after collector TLS trust recovery (#3010)
An existing collector can retain its legacy TLS bypass after the host
trusts the Pulse certificate. Updating it with action-runner enrollment
then incorrectly rejects normal system-root trust and enters recovery
before creating the runner service.

Keep collector/download settings separate from verified runner TLS.
HTTPS runner configuration continues to use system roots, a configured
CA or an exact certificate pin and never inherits the collector bypass.
Activation, cancellation, revocation and service recovery retain their
existing boundaries.

Validation: the new executable regression fails against the previous
installer and passes with the fix. It covers recovered insecure state,
private configuration persistence and the real runner credential
lifecycle binary over TLS. System roots, custom CA and exact pin
succeed. Untrusted certificates and incorrect pins receive no
credential-bearing request. The installer Action Runner suite, runner
binary tests and hostagent Action Runner suite pass.

Agent Doctor enrollment also passes in the current built app at 1440,
820 and 390 pixels wide, covering details disclosure, issue
failure/pending/success, private command copying, one-time reveal,
clearing and reload. Browser endpoints use synthetic fixtures. No native
installed-host or published-release acceptance is claimed.

The additional native workflow passes on Linux x64 and ARM64. Its macOS
Intel and ARM64 jobs fail the unchanged Upstart retirement contract
because the host `ln` rejects `-T`. The same failure occurs in [the
earlier main
run](https://github.com/rcourtman/Pulse/actions/runs/38899584939). This
change does not touch that fixture or the exercised retirement
functions.
2026-10-17 02:33:07 +01:00
rcourtman 327ef6a100 Make the Upstart teardown harness independent of umask
agent_upstart_teardown.py created its fixture job directory with a bare
mkdir, so under a caller umask of 002 (the default on pulse-dev and other
Ubuntu user-private-group hosts) the directory came out 775. The
installer's trusted_lifecycle_regular_file check correctly refuses a
config whose parent is group-writable, and 23 subtests failed when the
harness ran directly. The Go driver only passed because the
installtests package pins umask 022 for its children.

Give the job directory an explicit 0755 mode, matching the sibling
TrueNAS and uninstall-state harnesses, which already create their
trust-checked directories with explicit modes. The production code
under test still runs with the caller's umask; it sets 644 on the files
it writes, so the harness now passes under 002, 022 and 077.
2026-10-17 01:10:19 +01:00
rcourtman 1591af6c1e Supply GNU ln to macOS Linux installer fixtures
The DSM Upstart removal path links its manual override and restores a
retired job config with GNU `ln -T --`, a hard link that never replaces
or descends into an existing target. Its Python harness executes those
production functions with the host's ln. On the macOS runners that is
BSD ln, which rejects -T ("illegal option -- T"), so 13 subtests of
TestInstallSHUpstartTeardownRequiresObservedQuiescence have failed on
both macOS jobs since the DSM retirement series landed on 12 Oct.

The production code is right: that path only runs on Synology DSM
(Linux), never on a macOS agent host. The gap is the macOS fixture
toolset, which already supplies GNU stat/chmod/chown/mv/tar for these
Linux-only installer contracts but not ln. Add ln to that step and make
the fixture-tool contract test bind it and exercise real `ln -T`
no-replacement semantics (file and directory targets).

Contract-Neutral: CI fixture tooling only; macOS runners gain the GNU ln the existing DSM Upstart harness already assumes, no installer or lifecycle contract change
2026-10-17 00:36:19 +01:00
rcourtman 6dc43d298c Stage server update archives on the install filesystem, not /tmp
The server installer downloaded the release archive and extracted it
under /tmp. Debian 13 and many LXC templates mount /tmp as tmpfs, whose
pages are charged to the container's memory cgroup. A v6.5.0 archive is
~280 MB and extracts to ~750 MB, so an unattended update on a 1 GiB LXC
filled the cgroup with ~820 MB of shmem; the kernel OOM-killed the
container's systemd and Proxmox stopped the container mid-update.

Download and extract into owner-only hidden directories under the
install directory instead. It is always writable from the hardened
pulse-update.service sandbox, it is where the staged binary already
lives, and the disk headroom preflight now measures the filesystem the
update actually stages on. The Go updater already prefers its data
directory over /tmp for the same reason.

Unlike /tmp, the install filesystem keeps an interrupted run's staging
across reboots. Staging setup now removes stale staging directories that
match only the exact owner-only names, never symlinks or files, and only
once their ctime is over six hours old: install.sh has no update lock,
so age is what proves no live run still owns them. Every recursive
pulse chown of the install directory now goes through one helper that
skips staging, so the payload root still reads is never handed to the
service account and the ~750 MB tree is not rewritten for nothing.

The "Failed to print table: Broken pipe" line in the report was
systemctl list-unit-files | grep -q in v6.5.0's service discovery; main
already reads that inventory in full, and it was not the failure.

Contract-Neutral: Defect fix inside the existing private server-installer inputs and update-space boundaries; staging moves from tmpfs-prone /tmp to the install filesystem with no public contract change
2026-10-16 23:49:36 +01:00
rcourtman 630bf897be fix(agent): separate runner trust from collector TLS bypass
Legacy updates recover the collector's insecure setting even after the host
trusts the server certificate. Do not reject verified runner system trust
because of that unrelated setting. Keep HTTPS runner verification enabled
and preserve custom CA and exact fingerprint trust.

Exercise recovered configuration and the real credential lifecycle client
against TLS, including untrusted certificates and mismatched pins that must
receive no credential-bearing request.
2026-10-16 23:22:42 +01:00
pulse-triage[bot] 81d614e937 Make native NAS cleanup proof portable and observable
Require a kernel absence observation for the recorded timeout child instead of treating missing /proc or missing PID evidence as cleanup. Exercise live, reaped, missing and refused observations. Bind repeated stdlib-only process/flash/signal models to the runner's selected isolated Python, preserving every existing adverse control. Record cumulative and per-control timing so the unchanged two-minute suite limit cannot be mistaken for a particular hung case.

Contract-Neutral: Native NAS test harness only; production installer behaviour, process ownership, safety deadlines and public contracts are unchanged.
Change-source: pulse-maintainer
2026-10-14 22:46:41 +01:00
pulse-triage[bot] 0c08f9b4b3 Integrate reviewed Actions refresh and coupled trust controls
Preserve exact Delivery candidate identity, current public frontend receipts and additive canonical validation corrections.

Change-source: pulse-maintainer
2026-10-14 18:39:45 +01:00
pulse-triage[bot] 203b91b051 Reconcile validation with accepted helper guidance and Helm recovery
Exact PR2888 jobs 115988808038 and 115991110679 exposed obsolete documentation/workflow markers and formatting in composed tests. Assert the shipped socket-free discovery, confined command boundary and incomplete-inventory limits; verify authenticated immutable release-packet admission instead of an expired live-run requirement. Preserve production source, native deadlines and all accepted history.

Contract-Neutral: Test-only integration and formatting correction; no runtime, documentation, dependencies, qualification deadline or permission changes.
Change-source: pulse-maintainer
2026-10-14 18:22:04 +01:00
pulse-triage[bot] 246646090a fix(ci): qualify the Actions patch and minor refresh
Own PR2936's stale pin and download-admission failures at b7e774d4. Refresh all current workflow consumers, including the newer pre-token issue-label job, with their exact static expectations and lifecycle/deployment contracts. Preserve Node 24, scoped lockfile caching, credential isolation and artifact identity/retention; reject old, mutable and arbitrary download pins.

Contract-Neutral: Immutable Actions pin refresh and coupled consumer/trust expectations only; workflow inputs, permissions, cache and credential controls, artifact identities and application/runtime contracts are unchanged.
Change-source: pulse-maintainer
2026-10-14 17:38:18 +01:00
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] 1740bccd61 Test issue metadata on proposed source before publication
Run the locked parser and silent triage policy on their complete input changes in a credential-free Build and Test job. Retain issue-event pre-token checks, existing runtime and strict dependency gates; exercise admission and original install/test failure exits.

Change-source: pulse-maintainer
2026-10-14 11:12:45 +01:00
pulse-triage[bot] e1cd6843e9 Preserve native updater failures across cleanup
Keep the original failed transaction command distinct from any later cleanup command. Retain fixed operation labels and require portable controls for command, timeout, assertion, cleanup-only and successful receipts, without changing update transactions or disclosing command output.

Change-source: pulse-maintainer
2026-10-14 09:16:19 +01:00
pulse-triage[bot] 10e7a1c727 Keep NAS result inventory bound to the native-basename control
Require the renamed native process-field assertion in the complete NAS removal oracle; retain all twenty controls and their strict executed verdicts.

Contract-Neutral: Update only the required test identity after the fixture assertion rename; no production or acceptance-contract change.
Change-source: pulse-maintainer
2026-10-14 07:23:20 +01:00
pulse-triage[bot] fd0754d7c3 Keep containing recovery proof faithful to current helpers
Current exact-head CI exposes outdated PBS proof inventory, omitted bounded-download helper extraction, closed transport rejecting the production HTTPS flags, and Darwin's truncated comm column in Linux NAS fixtures. Preserve exact transport and process ownership, restoration and migration safety assertions while binding the controls to the actual producer.

Contract-Neutral: Test and offline CI-fixture alignment only; no installed runtime, trust, credentials, deadlines, source safety or public contract changes.
Change-source: pulse-maintainer
2026-10-14 07:22:52 +01:00
pulse-triage[bot] ece7e958f1 Keep the recorded beta packet on its exact cumulative wording check
The accepted beta.2 packet uses the earlier explicit cumulative introduction, while the new upstream general helper recognises the metadata tools standard introduction. Keep that historical packet on its strict existing stable-base introduction and heading checks; later numbered packets use the new incremental-or-cumulative helper. All remaining packet/signing/mobile checks remain shared and unchanged.

Contract-Neutral: Integration test branch reconciliation only; release source, notes, workflow behavior and publication rules are unchanged.
Change-source: pulse-maintainer
2026-10-14 00:34:48 +01:00
pulse-triage[bot] e114ccafd7 Retain published cumulative beta packet checks in the reviewed batch
Merge exact upstream 1844f6c0ed after completed bounded refresh 4ced96dc6a4e6278a4bba6fb79fb21cf68d954d95d49d67c27d425621a7d9f3f. Preserve every reviewed commit and the specific beta.2 cumulative-list assertions while using the new general incremental/cumulative-base validation for other packets. Only installer release-packet tests change; final frontend bytes remain identical.

Change-source: pulse-maintainer
2026-10-14 00:34:10 +01:00
rcourtman 14cbaaad9c fix(release): accept cumulative prerelease changelog bases
The release train explicitly compares the full beta range with the previous stable. Accept that supported base as well as the default previous numbered prerelease, while rejecting missing, ambiguous and unrelated comparison bases.

Contract-Neutral: Align release packet checks with the existing metadata contract. No public install or runtime contract delta.
2026-10-13 23:32:10 +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] a3679d6a43 Use a native-built inert collector in NAS watchdog controls
The private NAS fixture copied /bin/sleep and relied on its renamed process identity. Build a bounded Go collector instead and require its fixed readiness marker through the generated wrapper's retained stderr, as well as exact kernel process ownership. Preserve actual wrappers, teardown/parser, all stop and cleanup assertions, and existing deadlines. This removes a platform-owned executable assumption; it does not diagnose or clear the preceding macOS failures or establish native appliance recovery.

Contract-Neutral: Private fixture executable and readiness proof only; production installer, process ownership, safety deadlines and wire contracts are unchanged.
Change-source: pulse-maintainer
2026-10-13 15:20:17 +01:00
pulse-triage[bot] 254d7762a2 Observe NAS removal controls before native frontend preparation
Move the existing generated watchdog and collector contract to an early, fail-closed native CI phase. Discover the complete inventory in both phases, execute every check exactly once, and preserve the remaining group assignments, native runtime tools and safety deadlines. Exercise phase admission, omission, duplicate and failure controls.

Contract-Neutral: Native CI phase ordering and inventory partition only; production installers, runtime behaviour, required checks and safety deadlines are unchanged.
Change-source: pulse-maintainer
2026-10-13 11:14:52 +01:00