Compose the useful Kubernetes, storage and Proxmox table improvements from four proposals against current main, preserving organisation-safe History and newer recovery/drawer work. A fresh guest snapshot no longer masquerades as the latest independent backup; controller timestamps and full disk health reasons remain reachable from phone rows.
History consent names the running version separately and declares missing restore-scope metadata rather than promising an active-data rewind. Distinguish installation-only and legacy recovery and link the stopped-service full-state instructions. Add substantive dependent contracts, connected tests and a fresh production-component desktop/phone browser receipt, including the SMART wrapping correction found during validation.
Original-PR: https://github.com/rcourtman/Pulse/pull/2417
Original-PR: https://github.com/rcourtman/Pulse/pull/2418
Original-PR: https://github.com/rcourtman/Pulse/pull/2421
Original-PR: https://github.com/rcourtman/Pulse/pull/2425
Original-Commit: 3149ec61d8
Original-Commit: c02b2d81cc
Original-Commit: d33d6a4fd3
Original-Commit: 572ea0158b
Original-Commit: c5e89849bd
Original-Commit: 3f2715e3f3
Original-Commit: 852ebdca08
Original-Commit: 083cd070fe
Co-authored-by: rcourtman <8825017+rcourtman@users.noreply.github.com>
Change-source: pulse-maintainer
Preserve exact 2dda2e6653 and the newer recovery, help and drawer fallback work. Fetched disk History must not retain observations across organisation switches with identical resource IDs. Keep the existing receipt unchanged; both original non-merge receipts remain bound to their own parents. The frontend dependency audit remains a separate unresolved delivery gate.
Change-source: pulse-maintainer
Final facet access failures must not re-display embedded or unfiltered history. Retain transient snapshots, and show failed action reads with an available retry rather than false empty/loaded states. Preserve the existing unavailable-plan client boundary. Add rejecting parent controls and desktop/touch browser proof.
Change-source: pulse-maintainer
Remove unconfigured Docker and Helm shorthand from the deployment overview. Preserve target edition, existing service and storage scope, and the limits of snapshots and rollback; exercise the maintained help links and regression guards.
Change-source: pulse-maintainer
Replace HistoryChart request and polling ownership on org changes, even when resource IDs match. Withdraw old readings and inspection without changing same-org outage retention or caller-supplied sample ownership. Preserve touch compatibility-focus suppression. Add original-source controls, production browser verification and the primitive contract.
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
Compose the exact returned candidate on the current assigned main base; retain independent review defect evidence and all newer source.
Change-source: pulse-maintainer
Replace the destructive hardcoded restore recipe with path and backup-scope checks, the existing history control and reversible recovery guidance. Keep Compose image selection persistent and recreate only Pulse after a successful pull. Verify shipped mirrors, source/UI scope, synthetic command failures and desktop/phone Docs rendering.
Change-source: pulse-maintainer
Retain exact Core candidate and its grouping, persistent-delivery and shutdown proof; no notification source changed on the intervening canonical frontier.
Change-source: pulse-maintainer
Coalesce repeated firing callbacks before delivery into the newest complete occurrence snapshot, retaining distinct and unknown identities and the original grouping deadline. Discard the transient index on cancellation, flush, disable and stop; cancel abandoned firing timers before queue shutdown. Verify ordering, concurrency, routing, persistent restart and actual loopback firing/recovery delivery without changing escalation or retry policy.
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
Retain the independently rejected distribution-state rollback evidence and repair the operation in this assigned worktree; canonical publication remains separate.
Change-source: pulse-maintainer
Treat final HTTP 401/403 as access failures rather than transient refresh outages. Clear displayed samples and inspection, invalidate retained query ranges and remounts, and keep bounded access guidance through scoped recovery. Preserve ordinary outage retention, current-value labelling, abort ownership and license gates with runtime and real-client desktop/touch browser controls.
Change-source: pulse-maintainer
The queue discovers one concurrent batch at a time; the first HTTP control incorrectly expected another batch to start while the held response was unfinished. Admit both snapshots through the deferred bootstrap owner and then use normal queue activation. Preserve the runtime policy and timeout, and verify each received message explicitly.
Change-source: pulse-maintainer
A late provider completion must retain its own firing receipt without replacing a newer occurrence’s repeat-delivery cooldown. Preserve the latest completion and highest delivered severity within one occurrence, keeping genuine new occurrences and severity increases eligible. Exercise reverse HTTP completion, duplicate admission and durable recovery receipts alongside legacy ordering controls.
Change-source: pulse-maintainer
Candidate preflight rejected three path lists that used ASCII or insertion order instead of the registry's case-insensitive order. Sort only those lists and exercise the committed registry in the audit suite so fixture-only passes cannot miss the same mistake.
Contract-Neutral: Canonical registry path-list ordering and regression coverage only; ownership, verification requirements and runtime behaviour are unchanged.
Change-source: pulse-maintainer
Preserve reviewed b6a42d8a and upstream 74fd189f ancestry. Runtime files merge unchanged; resolve the browser manifest conflict using the retained drawer receipt for the newly proposed UI range. Upstream table evidence remains in its original committed history; no new browser run is claimed.
Contract-Neutral: Additive reviewed-source composition and evidence conflict resolution only; no API, persistence, access or retention contract changes.
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
Use stable disk-family chart entries so missing current SMART or temperature fields cannot hide stored observations, and matching snapshots do not remount charts or restart reads. Preserve existing identity, live collection status and entitlement boundaries; cover cancellation, measured zero, empty series and desktop/phone presentation.
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
A cancelled retry and a lost RAM cooldown marker do not mean that no destination received the old firing. Keep quiet-hours and recovery controls, then let persistent occurrence/destination receipts select the actual recipients. Add an HTTP 200/503, restart and recurrence control so the newer firing survives and only the previously informed destination receives the old recovery.
Change-source: pulse-maintainer
## What changed and why
Alert cleanup now retires an expired flapping episode together with its
suppression deadline. Previously either cleanup owner could remove the
deadline but leave the episode latched, suppressing notifications
without a newly bounded cooldown. Active alert identity, unexpired
suppression and ordinary repeat-notification cooldown remain unchanged.
TrueNAS troubleshooting now distinguishes stale polling, missing
telemetry, authentication failures and session turnover. The existing
guides preserve polling evidence before a manual connection test updates
timestamps, use the actual 60-second default and avoid credential resets
or destructive reproductions. This addresses the diagnostic gaps exposed
by #2382, #2396 and #2400; it does not claim those native incidents are
all resolved.
## Reviewed source included
Complete unpublished range:
`0e90236d3bb901dc84d4d07e70d4d2a09d5e6705..971ebde8afdc0f55dd0ea77a0358467caf62ea73`
(five commits, including additive integration history).
- TrueNAS guide candidate `4b0f23e0a7a7d03df391f83896cbf4b48657bd24` (2
October).
- Alert cleanup candidate `d813c936e464eb09bb9ae7e6c7ac33716acde378` (2
October).
- Integration tips `e9294420`, `71382de0`, `971ebde8` preserve the
original candidates and published main ancestry without rewriting them.
## Validation
- Accepted alert candidate evidence: six parent-failing cleanup cases
pass on final; full alerts correctness/races, ten focused race repeats,
notification correctness, library vet/build and 132 governance checks
pass. The integrated alert files are identical to that candidate. These
proofs used Go 1.26.7; declared Go 1.26.8 CI remains required.
- Accepted guide evidence: seven guide checks, three polling controls
and 25 Docs/viewer tests; desktop Chromium and phone WebKit
navigation/readability checks. Integrated guide/test files are unchanged
from that candidate.
- Exact combined head: seven guide checks pass in offline source proof
`source-x4fm8fxy`, exit 0, complete output and completed guest shutdown.
The preceding confined lightweight attempt could not create loopback
sockets (five errors); it is an execution-context limitation, not a
pass.
- Publication provenance and whitespace checks pass; live main matches
the range base.
Required exact-head CI and independent source review still gate landing.
Real-duration alert queue/HTTP acceptance remains with its existing
owner after an interrupted proof; native monitoring acceptance and
containing-release delivery remain separate. No release, tag or
deployment is changed by this PR.
[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
Preserve exact candidate 0d8d5beb5f and its browser-bound parent. Retained full frontend proof and desktop/phone regressions cover this existing monitoring-trust repair.
Change-source: pulse-maintainer
Capture the resolved alert before asynchronous callbacks and carry its start/end identity through monitor recovery. Cancel only that occurrence in grouping, cooldown and persistent firing rows, retaining newer incidents, operational links, destination receipts and failed attempts. Keep the explicit identifier-wide cancellation API and legacy callback IDs. Add snapshot, restart and connected queue-to-HTTP regression controls.
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
TableCell and TableHead composed `px-2 sm:px-3 py-*` ahead of the
caller's class, but Tailwind emits every padding utility at the same
specificity in spacing-scale order, so a caller's `px-1` lost to the
base `px-2` and `sm:px-1.5` lost to `sm:px-3` wherever it sat in the
string. Measured on 2026-10-02: DiskList cells carried 16px of
horizontal padding on a 390px phone although their class asked for
8px, and 24px at 640-1023px although it asked for 12px; the Workloads
header cells sat at 8/12px above data cells at 6/8px; the platform
helper's `px-1.5 sm:px-2` had never taken effect on a cell since it
was introduced in May. PR #2409 and PR #2418 worked around it with
layout-mode `!px-1` overrides.
Apply the convention TableHeader already uses for borders and
TableBody for dividers to padding: when the caller's class names a
side's padding (`p-*`, `px-*`, `pl-*`, `pr-*`, `py-*`, `pt-*`, `pb-*`,
with or without `!`), the base padding for that side is left out, so
the caller's utility is the only one on the element. Sides the caller
leaves alone keep the base, so a `pr-2` column still gets its left
inset, and prefixed-only variants such as `lg:px-0` keep layering on
the base as before. The base is unchanged when nothing is passed, and
the class is resolved inside the JSX attribute so layout-mode class
switches stay reactive.
Platform tables pick up the helper's declared 6/8px cell padding,
which lines data cells up under the 6px headers the stylesheet already
pins, and their header rows drop to the helper's 2px vertical padding.
Give existing help readers scoped process/container samples, honest units and unchanged-workload baselines. Exercise the exact copied recipes, including stopped services, missing counters and failed or empty container reads, without touching a database or service.
Contract-Neutral: Existing-guide documentation and recipe tests only; no runtime, API, persistence, access or retention change.
Change-source: pulse-maintainer
Read replacement snapshots reactively through the existing drawer state and Overview. Key local state and reads by canonical resource ID, and keep availability selections on the current fleet rather than a clicked snapshot. Preserve same-ID History range and tab continuity while withdrawing lost targets. Parent regressions and Chromium/WebKit controls reproduce stale headings, history targets and false Up details; retain scoped tests, browser proof and the unified-resources contract.
Change-source: pulse-maintainer
Both cleanup owners removed only the deadline, leaving a latched episode that could suppress notifications without a new cooldown. Share dispatch expiry with cleanup, preserve unexpired policies and active occurrence identity, and verify renewed delivery, bounded rearming, diagnosis and one-shot callbacks without bypassing ordinary repeat-notification cooldown.
Change-source: pulse-maintainer
Preserve existing polling evidence before a connection test updates its ledger. Explain freshness, optional telemetry and session turnover using the read-only projection, correct the 60-second default, and keep diagnostic steps free of credentials and destructive reproductions.
Contract-Neutral: Documentation and existing-guide checks only; no runtime, API, transport, identity, access or retention change.
Change-source: pulse-maintainer
Retain both History/storage and Reporting contracts; keep the upstream browser receipt unchanged. Earlier accepted receipts remain in history, with runtime blobs preserved.
Change-source: pulse-maintainer
Recognise matching notify_unsubscribed events before and after acknowledgement, preserve unrelated streams and clean log completion, and retain only numeric errno with fixed diagnostics. Keep nonempty Apps inventory and poll-ledger progress while rejected stats recover on the next ordinary poll. The reporter supplied a source-derived envelope, not a retained capture; native acceptance and delivery remain separate.
Change-source: pulse-maintainer
The patrol_digest report schedule kind has been on main since early
September, but only the API could create one: the Settings > Reporting
form had no way to choose it, so the weekly "what Patrol did" email never
reached the customers it was built for, the ones who have stopped opening
Pulse. The schedule form now has a Report type choice between the
performance report and the Patrol weekly summary. The choice shows only
while the session reports Patrol can run (AI on with a provider), and an
existing summary schedule keeps showing its type so it stays editable
after AI is switched off.
Choosing the summary reduces the form to a name, weekday, time, timezone
and optional recipients. Cadence is pinned to weekly and delivery to
email, and the format, resource picker, tag filter, retention, attach and
save-copy controls are hidden because the server fixes those values; the
save path no longer demands a resource scope for this kind. The schedules
table describes a summary as "Patrol activity, last 7 days". Model, hook
and panel tests cover the gating, the pinned fields and the saved
payload, and the browser receipt records a Pro-licensed pass at 1280 and
375 pixels, including a run without an email destination that surfaces
the server's message naming the missing setting.
The existing drawer fetches all metrics without a metric query field. Explain metrics-object and single-metric points responses so readers do not wait for an absent CPU request or mistake missing CPU and measured zero for the same result.
Contract-Neutral: Clarify existing History diagnostics and protect mirrored documentation; no runtime, API, identity, access, retention or response-shape change.
Change-source: pulse-maintainer