Report entry still treated sanitized exports as sufficient and named an obsolete Diagnostics action. Warn before live collection during backups or an unresponsive host, reuse displayed results, and require local privacy review of files, screenshots and echoed errors without adding intake requirements.
Contract-Neutral: Community intake guidance only; release, installation and diagnostic runtime contracts are unchanged.
Change-source: pulse-maintainer
PR #2456 run 37179468966 failed TestNodeToolchainParity because the new workflow selected a patch version instead of the existing governed Node 24 line. Match the other workflows and add a focused trust regression without weakening the parity contract.
Contract-Neutral: Correct a workflow toolchain selector to the existing repository contract; no application, permission or release gate changes.
Change-source: pulse-maintainer
Use a dedicated Auth Keys write client restricted to tag:ci-deploy, never the broader demo registration. Reject missing configuration and validate the actual running Self tag and DNS before Serve. Keep exact-source, denial-stop, no-replay and cleanup contracts, with connected offline registration and Serve controls.
Change-source: pulse-maintainer
Use the established setup-node disable contract: no explicit cache backend and package-manager-cache false. The empty cache value was rejected by the workflow trust guard; retain the guard and add an omission check.
Contract-Neutral: The exact published-RC browser, credential isolation and cache prohibition contract is unchanged; this fixes its setup-node representation.
Change-source: pulse-maintainer
Live stable and RC archive metadata exceed 256 MiB; retain a streaming bounded 512 MiB archive/16 KiB signature/1 GiB binary contract instead. Disable automatic setup caches in the CI credential job and encode derived command outputs with the reviewed writer. Add regressions; do not relax workflow or release guards.
Change-source: pulse-maintainer
Reuse the signed-install lifecycle assertions on a fresh public hosted VM without Docker identity overrides. Bind immutable release assets/control, observe one real UI apply/SSE/modal journey, retain sanitised terminal evidence and stop access refusals without reauthentication. Update the deployment contract and execute its recovery-access guard; release judgment and gates are unchanged.
Change-source: pulse-maintainer
Merge exact upstream 99927467f5. Resolve only the agent-lifecycle contract append conflict by retaining both monitor recovery ownership and AI usage export clauses. Frontend auto-merges preserve reviewed final bytes; no runtime conflict correction or browser receipt rebinding.
Change-source: pulse-maintainer
Preserve the exact backup witness and both owning histories, including upstream opacity, trusted-peer help and portable demo fixtures. The existing full-state and guest-safety contracts remain intact.
Change-source: pulse-maintainer
The helper could repersist legacy entitlement secrets and clear billing integrity while granting demo fixtures. Require the existing demo capability before mutation, leave all billing/key material untouched, and keep verification and encrypted legacy migration with the canonical application. Preserve full-state recovery, service ownership and the existing native route; seed only non-secret admitted fresh-runner fixtures. Add real canonical encrypted/legacy/HMAC connected controls and malformed or unprovisioned refusal-before-mutation coverage.
Change-source: pulse-maintainer
Both macOS installer jobs failed the connected recovery controls because their temporary estate retained the /var symlink prefix. Resolve only the fixture root and exercise both paths under a real alias; keep production symlink rejection and complete observation windows unchanged.
Contract-Neutral: Test fixture path canonicalisation and a connected portability control only; no demo runtime, workflow, release or installation contract changes.
Change-source: pulse-maintainer
GHSA-vfj7-8cjw-p6xm (braces <= 3.0.3, no patched release) reached the
frontend graph only through dev-only tailwindcss 3 and jscpd 4, and from
3 October it failed the required Frontend check on every open pull
request, Go-only ones included. The production audit is clean, and a
change that leaves package.json and package-lock.json untouched has the
base commit's graph, so it can neither add a finding nor remove one.
Failing it blocked every fix and made nothing safer.
The runner now applies the split it already used for an unreachable
endpoint to findings too. A change that moves the graph, or edits the
runner, still fails on any finding at any severity. A change whose graph
is the base commit's warns, naming every finding. Only an explicit
NPM_AUDIT_REQUIRE_RESULT=false selects that mode; an empty or
unrecognised value, as a missing workflow output would give, stays
strict, which also tightens the outage path.
The scheduled npm-audit scan and the daily dependency advisory watch
keep the strict default, so an inherited advisory still fails somewhere
every day until the dependency graph is fixed. No severity threshold,
allowlist or suppression is added.
The direct writer-interface control also checks the fixed failed phase. Report the attempted terminal, not the preceding in-memory recovery phase.
Contract-Neutral: Correct the fixed diagnostic label and its existing contract control; restoration, evidence-failure exit and authority remain unchanged.
Change-source: pulse-maintainer
Exercise direct recovering and terminal OSError injection as well as atomic receipt faults. Preserve the real restored estate and complete watches while evidence loss remains failed and unverified.
Change-source: pulse-maintainer
Keep evidence loss failed and unverified, preserve snapshots and complete recovery watches, and bind terminal collection and subsequent mutations to the original writer exit. Retain the exact returned candidate and its failing control without expanding production privileges.
Change-source: pulse-maintainer
Retain the rejected VERSION rollback result. Replace general installer execution with pinned-signature archive selection and atomic binary/VERSION swaps, preserve unrelated distribution assets, and fail closed on missing matching native acceptance before production mutation.
Change-source: pulse-maintainer
Current operational source exposes healthz and takes the shared deployment lock. Pin that route and make the disposable service return 404 for unknown paths so native acceptance cannot manufacture a healthy cohost observation.
Change-source: pulse-maintainer
Exercise actual systemd and Caddy with a changed executable, distinct persistent data, delayed synthetic failure, observer loss and TERM during full rollback. Keep 300-second clocks, exact-source and cleanup receipts; no production credential or worker system privilege is added. Update the connected recovery contract and policy assertions, and retain bounded service identity observations.
Change-source: pulse-maintainer
Keep new source paths on their own connected proof policy after the full lookup suite exposed six broadened metadata expectations. Preserve terminal no-op cancellation evidence and the runtime file owner.
Contract-Neutral: Correct connected observation and verification routing within the existing demo operations and authority.
Change-source: pulse-maintainer
Compose the existing signed stable demo paths with the Relay host lock, durable systemd ownership, full persistent estate capture and five-minute forward and recovery watches. Preserve uncertain attempts and failed rollback, refuse destructive headroom pruning, and keep native installed acceptance separate from connected source controls.
Change-source: pulse-maintainer
On 2 Oct 2026 v6.4.6-rc.1 failed notarization because the Apple developer
agreement was unsigned, about an hour into the release. The maintainer's
nightly release rehearsal now dispatches release-signing-preflight.yml from
main on a hosted macos-15 runner. It imports the Developer ID certificate
into a throwaway keychain, requires the identity to be valid and at least 30
days from expiry, signs and verifies a probe binary with a secure timestamp,
and reads the notary submission history with the release key, which Apple
refuses while an agreement is unsigned or the key is revoked. The four
checks are independent and each reports one titled outcome, so one night
names every broken credential. It builds, uploads and publishes nothing.
Governance run 37016171545 rejected the original malformed timestamp even though a later reviewed receipt corrected it for identical runtime bytes. Use the existing fail-closed integration-range guard in CI while retaining per-commit canonical checks. Exercise the workflow shell with valid additive correction and invalid missing-base or unverified-content fixtures.
Change-source: pulse-maintainer
First step of the release simplification plan. create-release.yml loses
candidate_qualification and release_readiness, which only restated other
jobs' results. Their exact predicates move into publish_release_tag,
publish_docker, publish_helm_chart, activate_release and
release_commit_verdict, with cancellation unchanged.
recover-release-activation accepts both run shapes, so v6.4.6 and older
runs recover exactly as before. Failure-only diagnostics and the chart
artifact nobody downloads keep 3 days instead of 14 or 90. Only lines
cut from main after this land use it (release/v6.6 from 7 Oct). Reviewed
with gpt-6.1-sol, SAFE TO MERGE; predicate equivalence sampled over
2,784 cases.
Preserve every accepted commit while incorporating the published setup-node advisory-cache repair. Upstream changes a separate workflow; retain the proved runtime and documentation candidate bytes.
Change-source: pulse-maintainer
The scheduled watch reads each release line's lockfile in the default
branch's cache scope, so it deliberately writes no dependency cache.
It sets no cache input, but the pinned setup-node enables npm caching
on its own once package.json names npm as its packageManager. Nothing
declares that today; adding it later would silently reopen a
default-branch cache write here. Set package-manager-cache: false, as
five release workflows already do, assert it in the workflow test, and
say how the contract's no-dependency-cache promise is kept.
Chain signed installer downloads, verification and execution in the English, German and Spanish landing pages so a failed trust step cannot run stale or unverified bytes. Keep the pinned signer, namespace and release URLs, preserve real installer exits, and correct the existing plan and paired-app retirement guidance. Exercise the copyable Bash gate with offline command stubs and run those documentation regressions in Public docs CI.
Contract-Neutral: Public documentation and its secret-free CI validation only; no runtime, entitlement, release-selection or subsystem contract delta.
Change-source: pulse-maintainer
candidate_qualification and release_readiness only restated other jobs'
results. publish_release_tag, publish_docker, publish_helm_chart and
activate_release now each carry the exact candidate predicate in their own
needs and if, guarded by !cancelled() with the same allowed integration
skip, and activation joins the tag and both registry publications directly.
The commit verdict restates every candidate result in place of the
readiness join.
recover-release-activation.yml accepts both shapes. A source run that has
release_readiness still has to prove only that join, as before. A run
without it has to prove publish_release_tag and at least one, and only
successful, jobs under the publish_docker and publish_helm_chart caller IDs.
Failure diagnostics and the inspection-only Helm chart artifact, which
nothing downloads, are kept for three days instead of 14 and 90.
Failed setup now yields local-only, topology-free diagnostics. Require recognised Running state and successful tailnet ping before TCP, retain probe exits without raw private output or fallback probes, and exercise twenty synthetic readiness/privacy cases. Parent controls expose false success and private output on both channels. Keep workflow identities, secrets, action pins, mutation gates and release scope unchanged.
Change-source: pulse-maintainer
On 30 Sep-1 Oct 2026 GHSA-q2hr-2g5m-vwhr (brace-expansion) and
GHSA-p98j-92pf-mc4p (DOMPurify) failed the required "Audit complete
frontend dependency graph" step on every pull request to main,
release/v6.4 and release/v6.5. That held the v6.4.6 preparation PR and
the v6.5 RC for days with no owner. The scheduled audit in
security-scan.yml only informs and runs on the default branch, so
release lines were never checked.
dependency-advisory-watch.yml runs daily and on dispatch. It lists main
plus every release/v<major>.<minor> line at or newer than the latest
stable's line (all lines if that lookup fails), then audits each in a
fail-fast-free matrix. Each job fetches only that line's
frontend-modern/package.json and package-lock.json with git and runs
scripts/npm-audit-retry.sh all on them under the same Node.js pin that
build-and-test requires. npm audit reads the lockfile, so nothing is
installed. The job never checks out or runs the audited branch's code,
because a scheduled run holds the default branch's cache scope and
CodeQL flagged running npm ci there as cache poisoning.
A job fails when the audit fails, and its step summary and annotation
name the branch, the GHSA ids and the fix (npm audit fix
--package-lock-only plus raised floors in dependencySecurity.test.ts).
Read-only, hosted-only, no secrets, no uploads.
Install a published release (latest stable by default) with its signed
install.sh, seed auth, a webhook and a PVE node through the API, upgrade with
the installed /bin/update --version helper, then roll back with the documented
/bin/update --version command. Each step checks /api/version and the binary
version, /api/health, unit state, the seeded settings against fixed
expectations and the pre-upgrade read-back, and data-dir survival, then
reports a phase table in the step summary.
The workflow is read-only, hosted-only, uploads nothing and no release job
depends on it.
The exact no-mutation watchdog failed at published 6.4.5 because the release line has pending repairs but still declares its stable VERSION. Observe that governed source and its preceding stable reference without inventing a new promotion, while keeping candidate resolver gates unchanged and watchdog artifacts out of promotion-readiness records.
Change-source: pulse-maintainer
Replace two stale schema assertions with explicit watchdog omission and ordinary candidate rollback requirements. The actual workflow admission/source-selection shell tests preserve the fail-closed distinction.
Contract-Neutral: Tests and explanatory comments reflect the already recorded watchdog admission contract; no further runtime contract change.
Change-source: pulse-maintainer
Retain the scheduled governed-source selection and no-mutation demo verdict in a separate fixed dispatch mode. Check its control SHA and candidate-free envelope before checkout, preserve ordinary rehearsal rollback and exact event-source guards, and skip candidate builds.
Change-source: pulse-maintainer
The feedback form forced screenshots into shell code fences and conflated a running container image with a non-container release asset. Preserve rendered attachments, ask for the Pulse image only on running containers, and keep failed-install evidence truthful.
Contract-Neutral: Community issue intake only; release and installation contracts unchanged.
Change-source: pulse-maintainer
The bug and v6 pre-release forms previously required reproduction steps even when a retry could cause a host outage, duplicate update, alert storm or data loss. Ask for the original sequence and safe evidence instead, and mirror the guidance in the public triage document.
Contract-Neutral: Community intake wording only; release and installation contracts unchanged.
Change-source: pulse-maintainer
Ask for the attempted release and installer provenance when Pulse never started, without forcing a false running-version attestation or a token-bearing command. Keep public triage guidance aligned and pin both forms in tests.
Contract-Neutral: Issue form provenance and wording change community intake only, not release promotion or artifact dispatch
Change-source: pulse-maintainer
Retain the verified #2321 source and its original receipt while incorporating upstream release and browser range validation.
Change-source: pulse-maintainer
Preserve upstream browser verification for the newer Relay retirement surface; earlier action recovery proof remains in reviewed ancestry. Include current CI sharding and qualification canary without rewriting accepted commits.
Change-source: pulse-maintainer
With the host-interface canary in place, v6.4.5-rc.4 passed the
schema-v7 systemd and rootful Docker lab (run 36594651903), but the
attestation step then failed with Permission denied on receipt.json,
which the privileged lab writes as root into the bind-mounted evidence
directory. Hand that directory to the runner user after a passing lab
and before attestation, without touching its content.
The immutable RC systemd lab failed before installed acceptance because
its --network none container had no non-loopback IPv4 address to prove
the helper's private network cannot reach. Add a veth canary wholly
inside that namespace and assert no default route before the lab runs.
Also check out the repository in the demo resolver before it calls
scripts/write_github_output.py, so verification-only dry runs reach
their demo checks.
Split out of #2323 so the v6.4.5 promotion is not held behind the
unrelated action-review UI work in that PR.
The weights from #2324 came from one local run and left the api shards at
4.5, 8.8, 17.1 and 12.5 minutes on CI. Most of the 17.1 was not test time.
That shard ran `-run . -skip <1231 names>`, and the test binary caches only
its last compiled pattern, so alternating the two recompiled the 62 KB skip
regex for every test and subtest (about 50 ms each under -race locally, 30s
against 1.3s for 300 trivial tests). Two runs put that shard at 887s and
875s against roughly 450s of tests. The skip path now passes -skip alone.
Every api shard now runs go test -json through
.github/scripts/record-internal-api-test-seconds.py. It prints what plain go
test would (package lines and the output of failing or unfinished tests),
exits non-zero on any failure behind pipefail, and writes each top-level
test's seconds to an internal-api-test-seconds-N artifact that is uploaded
even when the shard fails. .github/scripts/refresh-internal-api-test-seconds.py
rebuilds the weights file from those artifacts (gh run download, median
across runs, DEFAULT_WEIGHT set to the mean of the unlisted tests, which the
selector now reads from the file).
Until those artifacts exist, the weights are a local -race -json run with
each region of go test's order scaled to what CI reported for it.
Equal-count quarters averaged 107, 437, 100 and 787s over four runs, and the
weighted cut gave 131s for the first 1187 tests, 350s for the next 23 and
608s for the last 21 over two. The last quarter and the last 21 tests
disagree on how the tail splits, so the tail takes the midpoint of an exact
fit and a pooled factor.
With these weights four shards still predict a slowest shard near 10
minutes, and a 20% slower runner on the tail would take it past the 11
minutes of Frontend and rest-1. Five shards predict about 131, 325, 280-340,
330-355 and 330-365s of tests, or 4.5 to 8.5 minutes a job with about 2.3
minutes of setup, so API_SHARD_COUNT goes to 5. Every test still runs
exactly once in contiguous go test order, and all five slices passed locally
from their new starting points. The required Backend tests (api) verdict
keeps its name.
An empty form field or unrelated edit cannot prove comment-raised topics were dispositioned. Only label newly declared topics, leaving removal to whole-thread triage and respecting a completed manual disposition.
Change-source: pulse-maintainer
Ask for the failing running version and a container image only where one exists. Accept symptom-appropriate screenshots or logs without forcing irrelevant log text, and state the matching triage rule.
Change-source: pulse-maintainer
The four Backend tests (api-N) shards took equal-count quarters of go
test's list, which left them at 4.0, 10.6, 4.0 and 16.8 minutes on the
first PR run, and at 1.9, 8.0, 1.5 and 10.3 minutes of go test time on
the following main push (run 36560070496). Almost all of it sits in a
few tests. One contract mock chart test runs about six minutes on the
runner, and the 28 integration server tests at the end of the list take
about twenty seconds each, so the fourth quarter held nearly half the
package.
Shards are still contiguous runs of go test's own order, since some
tests depend on package state from their neighbours, but the cut points
now come from estimated seconds.
.github/scripts/select-internal-api-shard.sh weighs each test from
.github/scripts/internal-api-test-seconds.txt (the 199 tests at 0.5s or
more, seeded from a local -race -json run scaled to that main run's
shard totals, with a 0.05s default for anything unlisted), binary
searches the smallest per-shard budget that fits the list into four
slices, and fills up to it. The weights only move cut points. Every test
is assigned exactly one shard in a single pass, so a stale file can
unbalance shards but never drop or repeat a test, and no shard is ever
empty.
With today's list the slices hold 1187, 23, 2556 and 21 tests, estimated
at 1.9, 6.9, 6.5 and 6.7 minutes of tests, or about 9.5 minutes per job
with the roughly 2.6 minutes of setup and race compile. The 2556-test
slice would need a 124 KB -run pattern, so a shard passes -skip of the
other shards' tests whenever that is shorter, which runs the same tests
in the same order.
Across the last 25 bot PRs the median open to merge time was about 33
minutes for one PR and about 45 when three opened together. The critical
path was the required Backend tests (api) check, where one go test -race
./internal/api step took about 27 of its 31 minutes. Every other required
check finishes within about 12 minutes.
internal/api now runs as four Backend tests (api-N) shards. Each shard
lists the package's tests with go test -race -list from the commit under
test and runs one contiguous quarter of that list in go test's own order,
so every test, including ones added later, runs in exactly one shard, and
a shard that resolves no tests fails. The split is contiguous rather than
interleaved by name because some internal/api tests depend on package
state left by the tests just before them. A round-robin split by sorted
name failed dozens of tests locally (admin bypass and session store
globals), while the four contiguous slices and the full run all pass. A
Backend tests (api) verdict job keeps the required check name and fails
unless every shard succeeded. Backend tests (rest-0) and (rest-1) keep
their names and package split. Local non-race timings put the heaviest
slice at about 42 percent of the package, so the api check should drop
from about 31 minutes to roughly 14.
Core E2E no longer runs the non-gating probation tier on pull requests.
It could not gate a PR and the promotion rule counts only main runs, so
on a PR it only held each of the eight shard runners about eight minutes
longer, which fed the runner queueing seen with concurrent PRs. Push and
manual runs still execute it.
Go test steps still run for frontend-only changes. Go tests read
frontend sources directly (internal/api contract tests,
internal/unifiedresources walking frontend-modern/src, and the
internal/telemetry repository-wide wording scan), so skipping them by
path would drop real coverage.
Create the non-loopback veth canary only inside the no-network disposable systemd container before running the immutable release lab. Preserve packet authentication and fail closed when the local interface or no-default-route assertion is absent. Bind the workflow, source contract and installtests guard in one reviewed candidate.
Change-source: pulse-maintainer
The scheduled release dry run reached its reusable demo resolver before checkout, so the output helper was absent and the no-mutation demo check failed. Move the credential-free checkout ahead of resolution, guard the ordering in install tests, and record that precondition in the deployment-installability contract.
Change-source: pulse-maintainer
Dispatch the post-publication check from protected main while binding its packet to the immutable RC tag. Accept only canonical Pulse checkout origins before normalising the spelling required by the attester, and document the deployment contract and source guard together.
Change-source: pulse-maintainer
The resolver refused a stable promotion until its candidate had soaked for
72 hours, or 168 for a minor. Few installs run previews: 35 of about 7,900
active installs ran v6.4.5-rc.3 in the week to 2026-09-28, so a longer
soak saw little the first day did not, while 75 percent of installs sat on
a stable build a month old. Richard set a 24 hour soak for every release
on 2026-09-28.
The minimums drop to 24 hours for minor and patch alike, the error text
reads the constants instead of repeating numbers, and the workflow and
trigger prompts, the promotion policy and the deployment contract say the
same. The content-drift check and the hotfix exception are unchanged.
The isolated coverage-v8 5 proposal cannot install beside Vitest 4 because its peer range requires Vitest 5. Ignore only version majors for both packages until a reviewed frontend migration can update and prove the pair together; retain grouped security updates and minor/patch updates.
Change-source: pulse-maintainer