Commit Graph

5180 Commits

Author SHA1 Message Date
pulse-triage[bot] 73b236c70b Merge guarded provider MSP recovery with installer guidance
Carry the prior source candidate onto the reviewed installer guidance tip so ownership-isolated recovery can receive exact-head proof.

Change-source: pulse-maintainer
2026-09-24 05:01:05 +01:00
pulse-triage[bot] f3518d9b9b fix(provider-msp): qualify installer purchase guidance
Keep first-run evaluation and summary guidance conditional on actual Plan availability and confirmed active limits. Remove the ordinary manual-key purchase prompt while retaining the separate custom-license binding path, and update the installability contract and focused assertions in the same commit.

Change-source: pulse-maintainer
2026-09-24 04:52:30 +01:00
pulse-triage[bot] d7b6b62051 Merge guarded provider MSP recovery with current main
Change-source: pulse-maintainer
2026-09-24 04:41:04 +01:00
rcourtman 9b16aeac9c Point provider MSP setup at the portal Plan tab to buy
setup.sh still told an evaluating provider to "request an upgrade" at
/msp.html#request, a form that waited on a human reply with a checkout
link. The portal now sells plans itself (Plan tab, Stripe checkout,
applied in seconds), so both the evaluation log line and the closing
summary send the provider there. The summary also stops printing the
lease signing public key as something the licence "must bind": the
portal purchase binds it without a copy step, and the key is still
available through --print-lease-signing-public-key for a custom licence.
2026-09-24 03:52:09 +01:00
pulse-triage[bot] 4f7718a27f fix(cloudcp): reject unowned tenant networks during provisioning
Require exact tenant and runtime labels before adopting an existing network, share that check with support-container recovery, and cover wrong or absent labels. Update the cloud-paid and deployment contracts to state the provisioning boundary.

Change-source: pulse-maintainer
2026-09-24 03:50:21 +01:00
pulse-triage[bot] 8430764009 fix(cloudcp): isolate provider MSP recovery per ingress
Merge the reviewed recovery candidate onto current main while retaining the already landed PR implementation. Filter shared support roles by the configured provider network, verify tenant-network ownership before attachment, and cover two same-host providers plus startup reconciliation.

Change-source: pulse-maintainer
2026-09-24 03:21:59 +01:00
pulse-triage[bot] 0f7406695c Merge upstream provider MSP client recovery
Combine the already published #2216 recovery with the local first-run setup correction; preserve both release-control contract notes.

Change-source: pulse-maintainer
2026-09-24 03:12:51 +01:00
rcourtman a27a7d07f1 Merge pull request #2216 from rcourtman/claude/msp-support-network-reconcile
Keep provider MSP clients running across upgrades
2026-09-24 03:04:48 +01:00
pulse-triage[bot] 31cb12117e Merge provider MSP client recovery onto current main
Combine the current provider setup correction with the isolated-network recovery candidate. Retain both deployment contracts and preserve the client-restart and support-container ownership guards.

Change-source: pulse-maintainer
2026-09-24 02:41:14 +01:00
pulse-triage[bot] 12ffa72a96 fix(provider-msp): leave first-run platform running
Start the provider services after licensed compose validation so the printed bootstrap and portal link have a live control plane. Correct the first-run prompt to name only operator-provided values and retain an install contract regression test.

Change-source: pulse-maintainer
2026-09-24 02:24:21 +01:00
pulse-triage[bot] 82f07453f8 fix(cloudcp): recover provider MSP clients after support recreates
Reconcile PR #2216 with current main and retain the paid-plan contracts. Reattach support containers to active tenant networks at monitor startup and before checks, and restart unhealthy clients rather than stopping them under Docker unless-stopped.

Require exact tenant-network ownership labels and select support containers on the configured provider ingress network to preserve isolation. Cover startup recovery, restart behaviour, missing networks and wrong-owner networks.

Change-source: pulse-maintainer
2026-09-24 02:24:14 +01:00
rcourtman bd4cad1bb9 Merge remote-tracking branch 'origin/main' into claude/msp-support-network-reconcile
# Conflicts:
#	docs/release-control/v6/internal/subsystems/cloud-paid.md
#	docs/release-control/v6/internal/subsystems/deployment-installability.md
2026-09-24 02:23:30 +01:00
pulse-triage[bot] 08b4fa835c fix(cloudcp): apply shortened provider MSP licence periods
A billing-cycle change can retain the licence ID and plan while moving the signed paid period earlier. Compare the full signed expiry, replace the old token and restart, with regression coverage and the matching cloud-paid contract guarantee.

Change-source: pulse-maintainer
2026-09-24 01:47:02 +01:00
rcourtman 5c2b4de313 Apply a plan changed in Manage billing on return
A sandbox run of the purchase path showed that a provider who changed
plan in the Stripe billing portal came back to the portal's Clients page
still on the old plan. It stayed that way until the next six-hourly
refresh, unless they found the "Just paid? Apply my purchase now" button,
whose wording does not fit a plan change. Manage billing now returns to
?provider_msp_checkout=billing, and the Plan panel checks the licence
twice on the way back, which is enough for the plan-change webhook to
land without polling on every visit. In the same run Solo to Starter and
back applied about ten seconds after returning.

The paid panel also dropped "Licence valid to <date>". That date is the
paid period end plus 14 days of grace, so a buyer read it as the date they
had paid until. It now appears only once the licence is inside that grace,
as a warning that the subscription has not renewed.
2026-09-24 00:28:19 +01:00
rcourtman 4daf0df92c Keep provider MSP clients running across upgrades
Every upgrade.sh run recreates the control plane, and a recreated support
container is no longer attached to any client's isolated tenant network.
The health monitor then could not reach the clients, counted three
failures, and stopped each one, expecting the unless-stopped restart policy
to bring it back. Docker never restarts a container stopped through the
API, so every client workspace stayed down until someone started it by
hand. A Traefik recreate also left client routes returning 504.
Reproduced on a v6.4.1 provider bundle with two clients.

The monitor now reattaches Traefik and the control plane to each active
client's network once at startup and on every pass, and recovers an
unhealthy client with a single restart instead of a stop. With the fix on
the same install, a control-plane recreate rejoined both networks within a
second, a Traefik-only recreate had its routes back on the next pass, and
no client was stopped.
2026-09-24 00:06:49 +01:00
rcourtman 15ffacab59 Merge remote-tracking branch 'origin/main' into claude/msp-portal-plan-panel
# Conflicts:
#	docs/release-control/v6/internal/subsystems/cloud-paid.md
#	docs/release-control/v6/internal/subsystems/deployment-installability.md
2026-09-23 23:47:42 +01:00
rcourtman edda116236 Show a provider-hosted platform its plan and let it buy one
The portal had no billing surface in provider-hosted mode, so a provider
on the free evaluation could not see when it expired, how many client
slots it had left, or any way to pay. Provider-hosted mode now shows the
billing section as Plan. It lists the evaluation or paid plan, its
expiry and the workspaces in use, and on an evaluation it offers the
plans above the current cap at the licence server's Stripe prices.

Owners and admins get Buy, Manage billing, and "Apply my purchase now";
read-only members are told who can buy. After Stripe returns to the
portal the panel keeps refreshing the licence until the purchase lands,
then polls until the restarted control plane serves the new plan,
without reloading the page.

Exercised on a fresh v6.4.1 provider bundle running this build against
a stand-in licence server: the tab, the evaluation expiry and slot
usage, monthly and annual pricing, Buy reaching checkout with the
platform's licence ID and portal return URL, the periodic refresh
signed with the lab's lease key, and a 390px layout with no horizontal
overflow.
2026-09-23 23:45:28 +01:00
rcourtman 205785b655 Merge pull request #2209 from rcourtman/claude/msp-hosted-install-token
Mint agent install tokens in hosted client workspaces
2026-09-23 23:44:20 +01:00
rcourtman 9ff9387c59 Merge pull request #2210 from rcourtman/claude/msp-status-health
Judge client health from Docker when status runs out of band
2026-09-23 23:39:48 +01:00
rcourtman 185c6ac80b Let a provider-hosted platform buy and renew its own licence
A provider could stand the MSP bundle up and evaluate it without asking
anyone, but paying still meant emailing its public key to Pulse and
copying a licence file onto the host by hand. With the licence server's
self-serve purchase path (pulse-pro license-server/provider_msp_purchase),
the control plane can do the whole thing itself.

The control plane now signs a challenge with its lease signing key to
fetch the licence its subscription entitles, validates it exactly as
startup does, requires it to bind this platform's key, and keeps it in
the data directory, because the host licence is a read-only secret
mount. Startup prefers that renewed licence while it validates, so a
paying provider keeps starting after the self-issued evaluation on the
host expires. A changed licence restarts the control plane through the
existing graceful shutdown, since the plan version is read at load by
every workspace-limit, backup and status path; client workspaces keep
running. Preflight, proof, recovery and backup accept either signed
source.

The portal gains owner and admin routes for plan state, checkout, the
Stripe billing portal and an immediate licence refresh, and the plan list
comes from the licence server so it shows only what can be bought, at
Stripe's price. Adds the msp_solo plan: 3 client workspaces, the first
paid step above the 2-workspace evaluation.
2026-09-23 23:30:34 +01:00
rcourtman 05dfff8431 Merge remote-tracking branch 'origin/main' into claude/msp-hosted-install-token
# Conflicts:
#	docs/release-control/v6/internal/subsystems/agent-lifecycle.md
#	docs/release-control/v6/internal/subsystems/storage-recovery.md
2026-09-23 22:55:00 +01:00
rcourtman f338bd4765 Judge client health from Docker when status runs out of band
provider-msp status, which upgrade.sh and the install proof gate on,
runs in a one-off `docker compose run` container attached only to the
provider ingress network. Its health check dialled each client's
container on the client's isolated network, which that container cannot
reach, and an unreachable client counts as unhealthy. So on any install
with a real client, status failed with "unhealthy active workspaces" and
./upgrade.sh --dry-run exited 1: the backup-gated upgrade path refused to
run as soon as a provider onboarded anyone. CI proofs never saw it
because they only ever run against an empty install. Reproduced on a
fresh v6.4.1 provider bundle with one client whose container Docker
reported healthy.

The runtime image declares a HEALTHCHECK that probes the same
/api/health inside the container, and Docker records the result where
any caller with the socket can read it. Use that when it exists and keep
the HTTP probe for images without one. With the change the same install
reports healthy_tenants=1 and upgrade.sh --dry-run plans cleanly.
2026-09-23 22:46:47 +01:00
rcourtman adf07a370a Mint agent install tokens in hosted client workspaces
Every provider MSP client workspace runs in hosted mode, where users sign
in through the control plane handoff. The install endpoints decided
whether to mint a token from the workspace's own config, which on a fresh
client has no local credential, API token, proxy secret or SSO provider.
So Settings > Infrastructure > Generate token answered 200 with an empty
token and the Proxmox flow built a command without one: a provider could
not install a single agent from the client workspace. Found on a fresh
v6.4.1 provider bundle.

The router's configTransferAuthenticationConfigured already counts hosted
mode as enforced authentication; the agent-lifecycle copy of the rule
never gained that term. Add it. Self-hosted runtimes with no auth keep
the token-less command.
2026-09-23 22:23:20 +01:00
rcourtman 4d47504331 Offer org owners the settings their own org's routes serve
A provider opening a client workspace from the Pulse Account portal
arrives in that client's organization as its owner. ensureAdminSession
admits an org manager to the org-bound settings routes, but the security
status snapshot reported every settings capability as false for any
org-scoped session. Since the Settings navigation started hiding gated
panels in August, the owner saw only General: no Infrastructure page to
connect the client's Proxmox or install agents, and no Reporting page
for the client reports. The portal's handoff to
/settings/infrastructure fell through to General. Found on a fresh
v6.4.1 provider bundle, where /api/config/nodes answered 200 for the
same session that /api/security/status said could reach nothing.

Route and snapshot now share one settings-admin rule,
sessionUserHasSettingsAdminPrivileges. The snapshot keeps it out of
sessionIsAdmin: it widens only infrastructureRead, availabilityRead and
reportingRead, whose handlers read the organization's own config and
monitor state. Instance administration, detailLevel, authUsername and
billingAdmin stay withheld from org-scoped sessions, as the scoped
local session contract requires.
2026-09-23 22:11:03 +01:00
pulse-triage[bot] ffee736872 build: refresh Node 24 builder digest
Keep the canonical release and provider-MSP frontend builders on the proposed immutable amd64 Node 24 digest. Bind the same-commit change to the deployment contract, release-build metadata proof and provider-MSP rollout-control proof; hosted build and installed rollout remain separate evidence.

Change-source: pulse-maintainer
2026-09-23 18:46:18 +01:00
pulse-triage[bot] 72a76ae06e Merge pull request #2177 from jamincollins/fix/disable-proxmox-peer-sensors
feat(agent): allow disabling Proxmox peer sensor collection
2026-09-23 16:35:41 +01:00
Jamin W. Collins 410134450d feat(agent): allow disabling Proxmox peer sensor collection 2026-09-23 08:18:44 -06:00
rcourtman c03be57f0d docs(release): make releasing the default and define an achievable soak
The 2026-09-05 direction left release timing to open-ended judgment. Since
then no line has been cut from main and no stable has shipped, while every
candidate that passed qualification was withdrawn. Restore a fixed cycle
with a closed list of stop reasons, and point at the maintainer's one-page
release policy.

The clean-soak rule required the stable dogfood instance and demo server to
run the candidate, but both run the current stable release by design, so
no candidate could ever soak clean. Define the soak from open regression,
security and data-loss reports, preview telemetry and the candidate
observation guest where it is operational.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015AHsrZFUgqmohpszCMpaPx
2026-09-23 14:10:42 +00:00
pulse-triage[bot] 5d831b8765 fix(web): retain PBS host target across transient snapshots (#1723)
The Backups drawer's Identity and History target is the merged PBS host resource. Correlation was recomputed from each snapshot with no memory, so a live refresh that briefly omitted the correlated host row made the drawer fall back to the PBS service target (agent/<service key>), which has no host history. The target flicked between the host series and the service key until the host row returned.

Retain the last resolved correlation per PBS server and reuse it only across such an omission, and only while the remembered host is still fresh relative to the server, so a genuinely removed or replaced host is not advertised indefinitely. A host row that is present but ambiguous still declines, as before.

Adds unit coverage for retention, staleness and pruning, a drawer regression test, and extends the real-browser guard and fixture to omit the host row and assert the identity rows and History chart survive.

Change-source: pulse-maintainer
2026-09-23 10:27:45 +01:00
pulse-triage[bot] 8654c837ee build(deps): land the reviewed @types/node 26.6.2 refresh
Dependabot npm-minor-patch #2189 raises @types/node 26.6.1 -> 26.6.2 in frontend-modern and tests/integration, but Canonical Governance blocks the manifest/lock change for a missing deployment-installability contract entry and frontend dependency security proof. The portal frontend part of the same group is a separate ws override refresh that needs a portal bundle decision and is owned separately, so it is not carried here.

Carry the frontend-modern and tests/integration @types/node 26.6.2 bump with a Current State contract entry and a dependencySecurity floor raise. @types/node is a dev-only declaration package and does not enter the shipped bundle; @playwright/test stays pinned at 1.56.1, so browser-test parity is unchanged. The frontend-modern offline dependency snapshot is bound to 26.6.1, so npm ci --offline cannot resolve the 26.6.2 tarball in this assignment; a host dependency acquisition is required before the suite can run against the new lockfile.

Change-source: pulse-maintainer
2026-09-23 09:26:24 +01:00
pulse-triage[bot] c6546fce74 build(deps): qualify the go-minor-patch dependency group
Advance the managed go-minor-patch group with its required transitives:
golang.org/x/crypto 0.56.0->0.57.0, golang.org/x/term 0.45.0->0.46.0 and
modernc.org/sqlite 1.53.0->1.59.0 (libc 1.75.7, memory 1.12.1, x/text 0.42.0).
All other direct versions are unchanged.

Raise the dev-runtime dependency-manifest floors to the qualified releases and
add the storage-driver integrity floor so a silent downgrade fails. Record the
change in the deployment-installability contract.

The batch is routine managed dependency maintenance, independent of the excluded
6 September SQLite SIGSEGV investigation. The NormalizeSegment benchmark delta is
a code-layout measurement artifact (pure function; caller benchmarks do not
corroborate) and the failed advisory result is preserved.

Change-source: pulse-maintainer
2026-09-23 06:49:52 +01:00
pulse-triage[bot] 47cadcc188 fix(ai): serialize KnowledgeStore disk saves and track in-flight writes
SaveNote launched an untracked goroutine per note. Concurrent saves shared the fixed knowledge_store.json.tmp path, so the atomic temp+fsync+rename write could be defeated by an interleaved truncate/rename, and a still-running writer could recreate files in the data directory after a caller removed it (the flaky t.TempDir cleanup observed in TestKnowledgeStore_SaveLoad during release qualification).

Guard disk writes with a dedicated save mutex so only one save touches the temp path at a time, track in-flight saves with a WaitGroup, and add an unexported flush() the test uses to join them before cleanup. Add a concurrent SaveNote reload regression covering all entries, and record the persistence boundary in the ai-runtime subsystem contract.

Change-source: pulse-maintainer
2026-09-23 06:01:17 +01:00
pulse-triage[bot] 922626418c fix(installer): capture agent logs on FreeBSD/pfSense
The FreeBSD rc.d branch printed a log hint pointing at the system log,
but pfSense has no /var/log/messages (its system log is
/var/log/system.log). More importantly, daemon(8) does not capture the
child's stdout and rc.d has no journal, so the agent's zerolog output was
never written to any file: correcting the path alone would still point
users at a log with no agent entries.

Give the agent its own rotating log via --log-file on FreeBSD (both the
TrueNAS CORE and pfSense/OPNsense/vanilla FreeBSD branches) and point the
completion hint at it, matching the Unraid/QNAP/TrueNAS-Linux convention.

The shell installer is a canonical path shared by agent-lifecycle and
deployment-installability, so record the FreeBSD log-capture obligation in
both subsystem contracts.

Refs #2123.

Change-source: pulse-maintainer
2026-09-23 01:57:51 +01:00
pulse-triage[bot] 2c3a6b306a fix(web): keep the drawer tab across transient snapshot changes (#1723)
A live resource snapshot can briefly omit a field that gates a drawer tab, for example a merged metrics target during a refresh. The tab guard reset the active tab to Overview whenever the selected tab was missing, so the reported Proxmox -> Backups History tab silently jumped back to Summary on data refresh. Reset only when the drawer starts showing a different resource; each tab body already renders an availability notice while its tab is transiently unavailable. Adds a regression test covering a snapshot that drops and restores the metrics target, a source guard in ResourceDetailDrawer.history.test.tsx, the unified-resources contract update, and a fresh frontend browser-verification receipt from scripts/check-drawer-tab-retention.cjs (the same check times out on the pre-fix source).

Change-source: pulse-maintainer
2026-09-23 00:55:58 +01:00
pulse-triage[bot] f235fc37f2 fix(notifications): start queue processing after destination config
A persisted notification that was already due at startup could be terminally cancelled as 'delivery disabled'. NewNotificationManagerWithDataDir woke the queue worker during construction, before the owner had applied saved webhook/email/Apprise configuration, so the still-empty destination list looked like a removed destination.

Install the queue processor without waking it. The worker ticker and later enqueues start delivery once configuration is present. This removes the order/state-dependent failure in TestResolvedGroupingOrdinaryRestart and drops a persisted grouped recovery in production.

Also wait past the queue poll interval in the grouping contract test, add a regression test for the startup ordering, and update the notifications subsystem contract's processor-attachment semantics.

Change-source: pulse-maintainer
2026-09-23 00:01:56 +01:00
pulse-triage[bot] 50dc7f3e17 fix(truenas): request legacy reporting graphs in native shape
Omit the identifier key for device-independent legacy REST reporting graphs instead of sending an explicit null, matching the TrueNAS 13 middleware requests the reporter supplied for issue #2077. The null identifier is not the native contract and is a plausible whole-batch rejection that discards CPU and memory telemetry. Keep the existing per-graph failure isolation and add a request-validating synthetic regression that rejects any graph carrying an identifier key. Native CORE response schema and appliance acceptance remain unproved.

Change-source: pulse-maintainer
2026-09-22 23:26:53 +01:00
pulse-triage[bot] ee8de91eac fix(notifications): deliver severity increases through cooldown
Treat higher delivered severity as new information for the same occurrence without bypassing manager admission, grouping or destination routing. Keep the highest delivered level across late lower-severity completions. Include the contract and observation-to-HTTP/history regressions in this commit.

Change-source: pulse-maintainer
2026-09-22 20:37:00 +01:00
pulse-triage[bot] 873093134f fix(truenas): isolate legacy reporting graph failures
Keep usable system telemetry when an optional reporting graph fails, with bounded per-graph fallback that preserves terminal errors. Stop treating FreeBSD active pages as total used memory so free/ARC history agrees with live projection.

Request-validating synthetic regressions cover repeated snapshots, history and adverse responses. Native CORE schema and appliance acceptance remain unproved for issue #2077.

Change-source: pulse-maintainer
2026-09-22 18:26:17 +01:00
pulse-triage[bot] 702278cd8c Merge reviewed candidate 20260922T162030Z-core-runtime
Integrate the exact reviewed #2076 mixed-source disk correlation repair and regression coverage.

Change-source: pulse-maintainer
2026-09-22 18:14:11 +01:00
pulse-triage[bot] 064b28367a fix(resources): correlate linked disks with missing hardware IDs
Resolve issue #2076 mixed PVE/agent aliases only within the same parent and unique compatible device topology. Reject conflicting populated identities and controller-member fallback; preserve usable serials and WWNs over placeholders. Include snapshot and JSON regression coverage in the canonical registry verification artifact.

Change-source: pulse-maintainer
2026-09-22 17:27:50 +01:00
pulse-triage[bot] 097e3386e0 fix(agents): keep copied Unix install commands single-line safe
Use explicit shell separators instead of newline-dependent grammar for command fields. Preserve quoted values, private token files, TLS options and preflight ordering; cover paste normalization and execution failures in the owning regression suite. Refs #2123.

Change-source: pulse-maintainer
2026-09-22 17:27:29 +01:00
pulse-triage[bot] 9fbc4e7b3a fix(notifications): persist and group resolved alert deliveries
Prevent simultaneous recoveries from bypassing the configured grouping window. Preserve destination receipts and pending restart recovery, and keep PagerDuty incident keys separate. Include the notification contract and regression coverage with the runtime change.

Change-source: pulse-maintainer
2026-09-22 16:52:29 +01:00
pulse-triage[bot] da19341fcd fix(web): keep guest filesystem mount paths readable
Render complete wrapping paths above usage using an opt-in shared detail-row layout. Preserve compact rows and unknown-usage semantics. Include the typed regression fixture, registered primitive and Workloads guardrails, substantive owning contracts and the content-bound five-layout browser receipt in the same candidate commit. Recompose the rejected unshared candidate without changing its browser-tested runtime bytes. Addresses #2121.

Change-source: pulse-maintainer
2026-09-22 14:42:22 +01:00
pulse-triage[bot] e9a426aeeb fix(web): correlate PBS host history across guest and agent rows (#1723)
A standalone source=pbs host row and the PVE guest carrying the same agent are one machine. Collapse correlation candidates that share an agent identity and prefer the guest metrics target, whose persisted host series the Backups drawer renders; the PBS service target names the service key and has no host history. Distinct agent identities, or rows without a provable identity, still decline to choose so the drawer cannot substitute an unrelated host. Re-compose the reviewed runtime change with its three subsystem contracts, offline browser fixture, check script and a content-addressed browser receipt in one governed commit.

Change-source: pulse-maintainer
2026-09-22 09:43:00 +01:00
pulse-triage[bot] efeac6cb72 Merge reviewed candidate 20260922T074002Z-delivery-trust (pulse d5de3e26fc)
Change-source: pulse-maintainer
2026-09-22 09:12:22 +01:00
pulse-triage[bot] 1026f5293b docs(monitoring): record #2148 LXC linked-agent-memory contracts
Complete the #2148 runtime change with the monitoring and unified-resources contract sections its canonical subsystem paths require, so the combined change satisfies the canonical completion guard without rewriting reviewed history.

Change-source: pulse-maintainer
2026-09-22 08:46:29 +01:00
pulse-triage[bot] 50405af743 fix(alerts): skip backup-age alerts for PBS host backups (#2136)
A PBS host/config backup (backup-type host) is keyed by the node name, not a guest VMID, so CheckBackupsWithInventory raised a guest backup-age alert under a node-named subject (for example 'nas backup via proxmox-pbs') that never advanced while the node's guests were backed up, notifying repeatedly. Skip backup-age alerts for PBS subjects with no guest VMID: they are host/config backups, not guest workloads, and the Backups overview already keeps them out of guest coverage. PVE host backups already produce no subject and no alert, restoring consistency. Genuine orphaned PBS guest backups (numeric VMID) and PMG node backups still alert. The recovery point and rollup are retained, so inventory and artifact display are unchanged; only the spurious alert is cleared. Includes the alerts subsystem contract record and the regression tests.

Change-source: pulse-maintainer
2026-09-22 08:01:27 +01:00
pulse-triage[bot] d5de3e26fc fix(release-control): qualify release-line RCs against their own branch
The secure-runtime RC qualification workflow (commit 79d87a4a2c) resolves the branch the control plane maps the version to and passes it as --main-ref, but secure_runtime_attestation_v6.verify_canonical_main_identity still required origin/main and required the candidate to be an ancestor of origin/main. Every release-train candidate therefore failed the pre-authentication step before any check ran; v6.4.5-rc.1 failed at 'Pre-authenticate exact qualification packet' with 'committed-main classification requires canonical origin/main' (run 35680955017), and all three historical runs failed.

Accept exactly origin/main or the release train's origin/release/vX.Y, verify the ref against the canonical origin's live branch tip, and check candidate ancestry against that same ref. The release-candidate classification is unchanged. Update the deployment-installability contract and the v6 unit tests, including a mapped-release-branch acceptance case.

Change-source: pulse-maintainer
2026-09-22 04:28:39 +01:00
rcourtman 2856bd16b3 Recover saved Patrol objectives without observers
Saved objectives could remain uncovered indefinitely after their in-memory
setup trigger was lost or rejected. Reconcile missing or invalidated
observers from retained intent and recheck its revision at run admission.

Persist attempt timing before provider work so restart and history pruning
cannot erase pacing. Keep coverage dependent on actual observer validation,
installation and health evidence.

Support case patrol-objective-recovery.
2026-09-21 17:18:32 +01:00
pulse-triage[bot] 9fa81dee8f docs(release-control): complete #2140 TLS-preservation contracts
Record the #2140 node TLS-preference fix in the contracts its runtime commits touch: agent-lifecycle, api-contracts, security-privacy and the dependent storage-recovery contract, with the node API payload and persisted-field proofs in internal/api/contract_test.go and internal/config/config_load_test.go. The canonical completion history registers these contract and proof files as the completion of the auto-register and consolidation runtime commits.

Change-source: pulse-maintainer
2026-09-21 11:54:39 +01:00