Commit Graph

6689 Commits

Author SHA1 Message Date
rcourtman 05abf07219 Add Kubernetes, TrueNAS, and vSphere alert targets 2026-05-28 18:23:14 +01:00
rcourtman 75d1a0477b Enforce upgrade readiness before v6 updates
Refs #1476
2026-05-28 17:22:01 +01:00
rcourtman e1d1ec1d7c Add update readiness checks for v6 upgrades
Surface server upgrade readiness on update plans so v5 agent continuity and agent token scope issues are checked before install.
2026-05-28 16:47:49 +01:00
rcourtman 94992685d1 Capture continuous discovery reconciliation 2026-05-28 16:42:01 +01:00
rcourtman aa4a5fa631 Add agent provisioning capabilities 2026-05-28 16:31:19 +01:00
rcourtman f7a40f3a22 Add Proxmox setup doctor repair flow 2026-05-28 15:51:31 +01:00
rcourtman 79a501e092 Lighten AI intelligence handler test setup 2026-05-28 15:10:39 +01:00
rcourtman 7297aae4af Fix late issue triage regressions
Refs #1341

Refs #1429

Refs #1469

Refs #1472

Refs #1476

Refs #1481
2026-05-28 14:49:20 +01:00
rcourtman 47e9eb9aea Reconcile Ceph pool alert identity
Refs #1341
2026-05-28 14:42:43 +01:00
rcourtman bbf047f7c4 Reduce API chart contract seed volume 2026-05-28 14:32:19 +01:00
rcourtman 88c3e7b3b2 Run ceph pool alerts for agent-sourced clusters
Fixes #1341

Forward-port of the release/5.1 fix (ce1607694).

When a Pulse host-agent reports Ceph data, ApplyHostReport upserts the
cluster into state but only the Proxmox-API polling path ran
checkCephPoolStorage. Users with agent-reported Ceph (instance prefix
"agent:hostname") saved per-pool overrides under agent-prefixed IDs
that the alert manager never evaluated. The threshold appeared to
save (and showed Custom in the UI), but the polling cycle was
checking a different storage ID, so the alert silently stayed
dormant. Run checkCephPoolStorage right after the agent upsert so
the override key actually drives evaluation.
2026-05-28 14:16:14 +01:00
rcourtman 5a22b04c4c Harden audit log store failures
Refs #1464
2026-05-28 13:44:20 +01:00
rcourtman 80aab47da6 Stop swallowing alert config persistence errors
Forward-port of the release/5.1 fix (2c46c6c2d).

UpdateAlertConfig used to log SaveAlertConfig failures and still tell
the client "saved successfully", leaving the in-memory state with the
new override but the on-disk file untouched. On the next config reload
or process restart, the override silently vanished and the user saw
their threshold "revert" with no surfaced error. Return HTTP 500 with
the persistence error so the frontend can show a real save-failed
toast instead of false confidence.
2026-05-28 13:15:55 +01:00
rcourtman a7b12a6d3e Single-toolbar consolidation on multi-section platform pages
Docker storage, Kubernetes workloads/services/configuration each
stacked 2-4 PlatformTableToolbar instances, one per child section.
The toolbars looked like duplicate controls of the same shape even
though they were scoped to different datasets — same RC6 amateur
look as the WorkloadsFilter duplicate, just with multiple narrow
scopes instead of two identical states.

Extend createPlatformTableFilterState to take optional external
search/status accessors plus matching change callbacks so a page
can own the shared signals and drive every embedded table through
one toolbar. Add externalSearch / externalStatus props to each
affected table and switch the page surfaces to render exactly one
PlatformTableToolbar with showToolbar={false} on the children.
The shared counter reflects the union: total = sum of section
inventories, visible = sum of per-section filtered counts.
2026-05-28 13:11:48 +01:00
rcourtman 82ce72f20b Stabilize script smoke checks 2026-05-28 12:55:33 +01:00
rcourtman c05eed4306 Fix TrueNAS unavailable SMART disk health
Refs #1474

Separate TrueNAS native disk state from SMART health so null or unavailable smart_status projects as UNKNOWN without replacement risk, while explicit SMART failure and native failure states still alert.

Proof:

- go test ./internal/truenas ./internal/unifiedresources ./internal/storagehealth

- npm --prefix frontend-modern test -- src/features/storageBackups/__tests__/diskPresentation.test.ts
2026-05-28 12:53:46 +01:00
rcourtman d8389d9adc Refresh frontend bundle size baseline 2026-05-28 12:44:43 +01:00
rcourtman 25e5952a22 Stabilize runtime bootstrap tests 2026-05-28 12:35:59 +01:00
rcourtman 127e454834 Restore storage subtabs and guardrail headroom 2026-05-28 12:24:14 +01:00
rcourtman 1234f9140e Use shared header for pricing handoff 2026-05-28 11:57:47 +01:00
rcourtman a84867c044 Expand anonymous telemetry adoption coverage 2026-05-28 11:39:30 +01:00
rcourtman cd278bf5e2 Surface alert override identities in diagnostics
Forward-port of the release/5.1 fix (9ac7df976). buildAlertsDiagnostic
previously emitted only cooldown/grouping flags, so triaging support
cases like #1341 where a user suspects an override key mismatch
required asking them to paste alerts config from inside their
container. Add an Overrides slice that names each persisted key with
its thresholds and disabled flags. Sanitize mode in the frontend
redacts the keys to override-N while keeping thresholds visible.
2026-05-28 10:56:21 +01:00
rcourtman 5181c489bf Collapse duplicate Storage / Physical Disks switch on Proxmox storage
The Proxmox storage tab rendered two separate switches between the
"Storage" and "Physical Disks" views: a Subtabs strip at the top of
StoragePageControls and a segmented control inside the
StorageContentCard header, both bound to the same view state. The
Subtabs label "Storage" also collided with the section nav label one
level above, making the IA read as Proxmox / Storage / Storage.

Drop the Subtabs strip from StoragePageControls and rely on the
segmented control in the table card, matching Pulse's pattern for
binary view-mode choices (Bars/Trends, Grouped/List). Update the
storage page boundary test to forbid Subtabs / StorageViewSwitcher
from creeping back into StoragePageControls.
2026-05-28 10:01:02 +01:00
rcourtman be2f6324f0 Guard against duplicate WorkloadsFilter on platform overview pages
Add a platformOverviewLayout guardrail that asserts the Proxmox and
vSphere overview surfaces each render exactly one <WorkloadsFilter>
and pass suppressFilterToolbar to the embedded <WorkloadsSurface>.
This is the regression that shipped in 6.0.0-rc.6: both pages owned a
shared page-level filter and the embedded surface still rendered its
own, producing two stacked toolbars wired to the same state.
2026-05-28 09:42:09 +01:00
rcourtman d66d774c0e Collapse duplicate filter bar on Proxmox + vSphere overview
The Proxmox and vSphere overview tabs rendered the WorkloadsFilter
twice: once at the page level (driving both the top hosts/nodes table
and the embedded workloads surface) and once inside WorkloadsSurface
itself, since the surface always rendered its own toolbar regardless
of the shared state passed in.

Add a suppressFilterToolbar prop on WorkloadsSurface so callers that
own a shared toolbar can opt out, and pass the previously surface-only
controls (savedViewsKey, hostFilterConfig) through the page-level
toolbar so the Node and Saved views chips remain available.
2026-05-28 09:28:51 +01:00
rcourtman f21d2681d5 Frontend consistency sweep Tier 7: Proxmox inline drawers adopt section + DrawerSubjectHeading
ProxmoxCephClusterDrawer and ProxmoxMailGatewayDrawer were rendering as `<div class="space-y-4">` with a handrolled `<StatusDot> + <h3> + trailing pill` heading row. The canonical drawer pattern is a `<section aria-labelledby>` root wrapping `<DrawerSubjectHeading>`, with `space-y-3` between sections.

Both drawers now:
- Use `<section>` as the root with a stable `aria-labelledby` id derived from the resource identifier
- Pass the cluster health pill (Ceph) / version pill (PMG) through `DrawerSubjectHeading.trailing` instead of rendering it inline
- Drop the inline StatusDot in favor of the one DrawerSubjectHeading renders internally (size sm, canonical)
- Adopt the canonical space-y-3 rhythm to match GuestDrawer
2026-05-28 09:19:52 +01:00
rcourtman a55ab68276 Frontend consistency sweep Tier 6: hidden-CSS drawer tabs in NodeDrawer + DockerHostDrawer
Match the canonical pattern from GuestDrawer / ResourceDetailDrawer where tab panels stay mounted and toggle via the `hidden` class plus `overflow-anchor: none` on the wrapping div. Previously these two drawers used `<Show when={activeTab() === ...}>` which unmounts the subtree on every tab switch, losing scroll position and forcing re-fetches.

Discovery tab in both drawers needs an additional data-readiness guard (NodeDrawer narrows `props.discoveryTarget?.agentId`, DockerHostDrawer narrows `discoveryConfig()`); kept those outside the hidden-CSS div so the inner subtree only renders when its data is available, matching how GuestDrawer handles the same case.
2026-05-28 09:19:35 +01:00
rcourtman 6de33e3e4b Frontend consistency sweep: AnimatedNumber for live patrol token counter
The patrol banner's token counter streams during a live LLM run — every
token the model emits bumps the displayed count. Rendering raw
`toLocaleString()` makes that increment jump in steps; AnimatedNumber
tweens between values over 320ms so the count reads as flowing rather
than flickering. Other counter sites flagged by the audit (TrueNAS
event totals, mail counts, Ceph pool objects) update too slowly for the
animation overhead to be worth it, so they stay on raw display.
2026-05-28 08:37:48 +01:00
rcourtman 1200eeac49 Frontend consistency sweep Tier 5: drawer tabs use canonical Subtabs
The four detail drawers (ResourceDetailDrawer, GuestDrawer, NodeDrawer,
DockerHostDrawer) duplicated a bespoke tab pattern — native <button>
elements with `text-blue-600` on the active label and an absolutely-
positioned animated underline div — diverging from the canonical Subtabs
primitive used on StoragePageControls and ProLicensePanel. Subtabs renders
the same disclosure pattern with `role="tab"` + `aria-selected` + a
`border-b-2 border-blue-600` active treatment.

Three changes:

- Extend Subtabs with an optional `trailing` slot. The three drawers that
  surface a history-range select alongside the tabs (Guest/Node/DockerHost)
  used to put it in the same border-b row; the new slot preserves that
  layout for them without forcing every Subtabs caller through the more
  complex shape. Existing single-row callers (Storage, ProLicensePanel)
  render unchanged.
- Replace ~50 lines of inline tab JSX in each of the four drawers with one
  <Subtabs> call. Dropped the duplicate active-state class strings and the
  manual underline div. Active tab is now blue-border-underline + standard
  text color, matching the rest of the app.
- Update three test files to query the tabs by `role="tab"` instead of
  `role="button"`. The previous queries worked only because native
  <button> defaults to role=button; the new Subtabs buttons set
  `role="tab"` because that is the semantically correct role for a
  tablist member.
2026-05-28 08:30:29 +01:00
rcourtman 2012fb55b7 Frontend consistency sweep Tier 4: skeleton uses Card primitive
Replace the three bespoke `rounded-lg border border-border bg-surface p-6`
skeleton blocks in AlertDestinationsLoadingState with the Card primitive
(`padding="lg"`). Aligns the loading state to canonical rounding and
border tokens.

Other Tier 4 audit findings did not survive verification:
- Inline progress-bar divs in ProxmoxMailGatewayDrawer are stacked-segment
  bars (mail volume) and a two-segment In/Out comparison; the canonical
  ProgressBar is single-value only, so neither is a fit.
- PatrolIntelligenceSummary's bespoke `<section>` shells are semantically
  intentional landmarks; migrating to `Card` would render `<div>` and
  drop the landmark role.
- Custom date formatters in DockerAlertsTable and TrueNASAlertsTable
  diverge on edge-case behavior (year < 2000 handling, null-vs-dash
  fallbacks). Consolidation risks regressions that outweigh the
  duplication win.
- Native `<button>` usages and bespoke `<span>` badges in
  DockerAlertsTable / AgentsMachinesTable / TrueNAS tables are 30+
  sites that warrant their own focused refactor with tooltip-coverage
  evaluation, not a shotgun pass.
2026-05-28 08:12:47 +01:00
rcourtman 0f3e2aad15 Frontend consistency sweep Tier 2: drawer heading and search-input parity
Tier-2 audit revisited: the seven flagged detail drawers (Resource, Guest,
Node, DockerHost, K8sNamespaces, K8sDeployments, SwarmServices) are NOT
overlay modals — every one renders inside an expanded TableRow as the
content of a disclosure. The original audit's "wrap in Dialog" recipe was
wrong; Dialog brings focus trap and backdrop, neither of which applies
to inline section content. The trigger rows already expose `aria-expanded`
and `aria-controls`, so disclosure semantics are intact.

The actual drift was style duplication and a weak close label:

- Extract `DrawerSubjectHeading` for the `StatusDot + truncated <h2>`
  header repeated verbatim across GuestDrawer, NodeDrawer, and
  DockerHostDrawer. Migrating the three drawers removes ~30 lines of
  copy-pasted layout and pins the heading style in one place.
- Tighten ResourceDetailDrawer's close button aria-label from `Close` to
  `Close resource drawer`, matching what the platformResourceTableDrawers
  test already asserts via its mock.
- Migrate K8sNamespacesDrawer and SwarmServicesDrawer from SearchField to
  SearchInput, picking up `/`-focus and clear-on-escape and matching the
  K8sDeploymentsDrawer fix from Tier 1.

Drawer tab styling (4 drawers duplicate a custom blue-underline pattern
distinct from the canonical `Subtabs` primitive) is a real UX change and
is deferred to a follow-up so it can be verified visually.
2026-05-28 08:03:07 +01:00
rcourtman d608e0aaca Frontend consistency sweep Tier 1: stat-cards, legacy filter helper, redirect splash
- Replace AlertOverviewStatsCards' three bordered stat-tile Cards with a
  compact Table (rows=metrics, leftmost status dot). Removes the "big number
  + label + icon" vibe-dashboard pattern that violates Pulse's no-stat-cards
  policy.
- K8sDeploymentsDrawer: drop the deprecated LabeledFilterSelect import (the
  last production usage) and migrate the search input from SearchField to
  SearchInput, picking up `/` focus and clear-on-escape. The namespace
  filter inlines a <label>+<select> with the canonical filterGroupClass /
  filterLabelClass / filterSelectClass utilities, matching the existing
  GuestDrawerHistory pattern.
- PricingHandoff: render a plain h1+p instead of PageHeader. The shared
  header hides its description with `hidden sm:block` and mutates
  document.title in createEffect; both are wrong for a transient redirect
  splash whose description IS the manual-recovery link. Tests updated to
  reflect the deliberate bypass.
2026-05-28 07:53:53 +01:00
rcourtman 52fd847ac6 Let install.sh smoke harness opt past Docker-environment refusal
install.sh refuses to run inside Docker (correct behavior for end
users), but the install-sh-smoke gate runs the documented systemd
install path inside a privileged systemd-in-Docker container — the
one legitimate bypass case. Added PULSE_INSTALL_ALLOW_DOCKER=1
escape hatch in check_docker_environment() and set it on the docker
exec in the smoke workflow. Takes effect on the next RC; v6.0.0-rc.6's
published install.sh predates this and is signed-frozen, so its
post-publish smoke gate will remain red until the next prerelease.
2026-05-27 22:12:17 +01:00
rcourtman 7c35977fcb Fix post-publish pipeline failures for v6.0.0-rc.6
promote-floating-tags.yml waited on rcourtman/pulse-agent:${TAG} and
promoted floating tags for it, but publish-docker.yml never pushes the
agent image — Pulse Agent ships as GitHub Release binaries
(publish-docker.yml line 199 confirms). The wait timed out after 5
minutes on every release since the pulse-agent push step was removed,
leaving floating tags unpromoted. Stripped the vestigial wait block,
the agent promote step, and the agent line in the summary. Updated
header comments in both files to drop the past-tense reference.

install-sh-smoke.yml booted jrei/systemd-debian:12 without
--cgroupns=host, so on GHA ubuntu-24.04 (cgroup v2 unified hierarchy)
the container's systemd PID 1 exited before mounting the cgroup tree
and the container disappeared during readiness polling. Added
--cgroupns=host, an explicit /run/lock tmpfs, and dropped --rm so the
container persists for diagnostic capture on failure (trap handles
cleanup). Added an "is container still running" probe inside the
readiness loop and richer diagnostic output on timeout.
2026-05-27 22:08:15 +01:00
rcourtman b0a1937106 Rename Docker runtime navigation label 2026-05-27 21:02:19 +01:00
rcourtman c25e95cb2b Drop keyboard shortcut listings from rc.6 release docs
The Cmd/Ctrl+K command palette and the / global search shortcut are
the navigation affordances worth calling out. The g-chord shortcuts
are not a notable customer-facing feature for the rc.6 prerelease
notes; the keyboard shortcut modal already documents them in-product
for anyone who wants to discover them.
v6.0.0-rc.6
2026-05-27 20:46:51 +01:00
rcourtman 1407996e58 Drop Standalone framing from release docs; describe rename as Hosts → Machines
The internal rename chain in rc.1-rc.5 went Agents -> Standalone ->
Machines but neither Agents nor Standalone shipped as user-visible
labels for the Pulse Agent inventory page. Users coming from v5 know
the page as Hosts. The rc.6 release docs incorrectly framed the
change as 'Standalone surface renamed to Machines' which references
an internal name no public release ever exposed.

Reframe in the shipped v6 docs and the rc.6 packet drafts as
'Hosts page renamed to Machines'. Top-level page listings updated
to use Machines (not Standalone). Keyboard shortcut listing
updated to 'g s Machines' (not Standalone). 'Standalone-to-Machines
surface evolution' rewritten as 'Hosts-to-Machines rename'.

Touches:
- docs/releases/RELEASE_NOTES_v6.md
- docs/releases/V6_CHANGELOG.md
- docs/releases/V6_RC_OPERATOR_SUPPORT_PACK.md
- docs/releases/RELEASE_NOTES_v6_RC6_DRAFT.md
- docs/releases/V6_CHANGELOG_RC6_DRAFT.md
- docs/releases/V6_RC6_OPERATOR_SUPPORT_PACK_DRAFT.md

The internal route path /standalone is unchanged because that is a
code-level identifier, not a user-facing label.
2026-05-27 20:44:29 +01:00
rcourtman 7cb5f74db8 Bump WebSocket read deadlines from 2s to 15s in router integration tests
The four ReadDeadline(time.Now().Add(2 * time.Second)) calls in
router_integration_test.go (lines 1496, 1543, 1573, 1682) were
producing 'read tcp: i/o timeout' failures in CI under -race while
passing locally. The 2-second window is enough to read the welcome
+ initialState messages on a quiet dev workstation but too tight
once the runner is loaded with cumulative test work and the race
detector overhead. rc.5 cleared the same tests in CI but recent
fixture-size growth (k8s clusters 1->3 in 7938f28de plus the SMART
disk-temperature mock data added in 23ea4e487) pushed the
end-to-end server-start-to-welcome-message latency past the 2s
budget. Bumping to 15s gives CI breathing room without affecting
local test duration (the deadline only takes effect when the read
is genuinely stuck).
2026-05-27 18:36:33 +01:00
rcourtman 89a1740241 Reset sessionPresentationPolicy signal between useAppRuntimeState tests
vi.resetModules() drops the module cache but the freshly-imported
sessionPresentationPolicy module-level Solid signal still starts at
its default value only in isolation. In the CI parallel test runner,
a sibling test that imports the same module path can leave the
signal in a demoMode=true state that survives across beforeEach
because the running test's loadOrganizations closure already
captured a reference to the policy module before our doMock chain
ran. When that happens, useAppRuntimeState.loadOrganizations takes
the presentationPolicyHidesOrganizationSurfaces() early-return
branch instead of the multi-tenant branch, and the three sub-tests
that assert setOrgID('default') / orgs.list() behavior count zero
calls because the mocked code path never executes.

Explicitly reset the policy via syncSessionPresentationPolicy(null)
both at the end of beforeEach (after our doMock + dynamic import
of useAppRuntimeState) and in afterEach (before vi.resetModules)
so the signal is at defaults regardless of sibling pollution.
Tests pass locally before and after; failure was reproducible only
in CI parallelism.
2026-05-27 18:23:28 +01:00
rcourtman e327e09945 Fix KubernetesCluster RBAC slice race and align SECURITY.md sensor-wrapper guidance
KubernetesCluster RBAC slices were not deep-cloned

cloneKubernetesCluster cloned Nodes, Namespaces, Pods, Deployments,
and 20+ other slices via dedicated helpers but left Roles,
ClusterRoles, RoleBindings, and ClusterRoleBindings aliased to the
source slice through the dest := src shallow copy. The final
dest.NormalizeCollections() call then iterates over those four
slices and writes c.Roles[i] = c.Roles[i].NormalizeCollections()
via index assignment, which races with any concurrent clone (or
read of the same source). The race detector caught it once the
k8s cluster count was bumped from 1 to 3 in 7938f28de, which made
the contention window wide enough to hit under -race. Fix by
deep-cloning the four RBAC slices with append([]T(nil), src...)
following the same pattern as the inline slice copies elsewhere
in cloneKubernetesCluster.

SECURITY.md sensor-wrapper alignment

The SMART/SSH feature shipped in 8769f07ee updated the shipped
public security doc at frontend-modern/public/docs/SECURITY.md to
document the new Pulse-owned /usr/local/sbin/pulse-sensors wrapper
forced-command shape for the legacy SSH temperature collection
flow, but the source SECURITY.md at the repo root still described
the prior command="sensors -j" forced command. The docsLinks
test (which compares the two for byte equality) flagged the drift.
Align root SECURITY.md and re-sync the shipped copy so both
describe the wrapper contract that the setup-script and runtime
collector now own.
2026-05-27 18:13:44 +01:00
rcourtman e0569e510c Sync shipped public docs after MIGRATION_UNIFIED_NAV revert banner
The docs/MIGRATION_UNIFIED_NAV.md edit in df7934936 added the
post-rc.6 revert banner but did not refresh the shipped copy at
frontend-modern/public/docs/MIGRATION_UNIFIED_NAV.md that the
in-product docs route serves. The
src/utils/__tests__/docsLinks.test.ts 'keeps shipped docs content
synced with repo docs' assertion caught the drift in CI even
though the docs-route runtime itself was unaffected. Re-running
frontend-modern/scripts/sync-public-docs.mjs brings the shipped
copy back in line.
2026-05-27 18:00:07 +01:00
rcourtman 802b3aac49 Fix VMware inventory metric clone race and exempt docker-swarm-node from legacy-host-label assertion
Two real bugs that surfaced once the 20m test timeout let the
internal/api and internal/monitoring packages run to completion.

cloneVMwareInventoryMetrics omitted four fields:

Commit 23ea4e487 (Surface vSphere VM uptime and guest disk usage)
added UptimeSeconds, DiskUsedBytes, DiskTotalBytes, and DiskPercent
to vmware.InventoryMetrics but did not extend
cloneVMwareInventoryMetrics. The clone left those pointer fields
aliased to the source struct, so the mock fixture refresh path
(refreshVMwareInventoryMetrics writing through metrics.UptimeSeconds
via ensureInt64Ptr) and the snapshot read path
(inventoryUptimeSeconds dereferencing metrics.UptimeSeconds) raced
on the same heap-allocated int64.

TestMonitorBuildBroadcastFrontendStateUsesCanonicalMockUnifiedResources
exemption:

The test asserts broadcast state does not publish the lowercase-
hyphenated legacy docker host label so canonical docker hosts
surface their human-readable DisplayName. Commit 89abed099
(2026-05-24) added the docker-swarm-node resource type whose Name
is the swarm node hostname (matching how Docker Swarm identifies
node members), which collided with the legacy-label rejection.
Refine the assertion to apply only to host-type resources
(docker-host, agent, node).
2026-05-27 17:47:09 +01:00
rcourtman 3e61849242 Drop standalonePageModel snippet from agentless contract test; bump test timeout to 20m
TestAgentlessAvailabilityTargetKindStaysCanonical was pinning the
former agentless-machine classification in
frontend-modern/src/features/standalone/standalonePageModel.ts
(resource.availability?.targetKind,
availabilityTargetKindFor(resource) === 'machine'). Commit 1e16cf34f
intentionally narrowed the Machines surface to Pulse Agent resources
only, removing that classification, but did not update the test. The
server-side contract for availability targetKind across
config/availability.go, monitoring/availability_poller.go, types.go,
and frontend-modern/src/api/availabilityTargets.ts is preserved and
still pinned by the same test for any future consumer.

Makefile go test timeout bumped from 10m to 20m. The rc.5 backend
test run cleared 10m with slack; the rc.6 backend test run hit 13m
in internal/api before the binary panic-killed itself. 20m gives
headroom without hiding regressions for the rc.6 release path while
the package-size growth is tracked separately.
2026-05-27 17:17:13 +01:00
rcourtman 3e4cc1a198 Bump install pins to 6.0.0-rc.6
docker-compose.yml and scripts/install-docker.sh both still pinned
rcourtman/pulse:6.0.0-rc.5. The TestDeploymentDefaultsPinVersionedImagesAndHelmDocsChecksum
/ TestRepoDockerComposeDefaultPinsCurrentVersion / TestInstallDockerScript*
tests in scripts/installtests/ read VERSION (now 6.0.0-rc.6) and
require these install entry points to match.
2026-05-27 16:52:46 +01:00
rcourtman 58a24eeb77 Update header audit for platform-shaped IA
Drop the four deleted-page entries (Ceph, Infrastructure, Recovery,
Workloads) from REQUIRED_PAGE_HEADERS since those pages were retired
in the rc.6 IA revert.

Add PlatformSectionTabs to HEADER_PRIMITIVES. The post-rc.6
platform-shaped top-level pages (Proxmox, Docker, Kubernetes,
TrueNAS, Vmware, Standalone) use PlatformSectionTabs from
features/platformPage/sharedPlatformPage as their canonical chrome
rather than PageHeader; the audit was missing this recognition,
causing Docker/Kubernetes/Standalone/TrueNAS to fail with 'must use
at least one shared header primitive' while Proxmox and Vmware
passed only by accidentally reaching SectionHeader through their
WorkloadsSurface->WorkloadsTable->ErrorBoundary import chain.
2026-05-27 16:29:06 +01:00
rcourtman 6043224997 Rename infrastructureNavigation to platformNavigation and restore visual-crawl spec
Two cleanups left over from the rc.6 IA revert that lived as
untracked scratch in the working tree until now.

Rename infrastructureNavigation -> platformNavigation

The internal feature name infrastructureNavigation predates the rc.6
revert and assumed an Infrastructure top-level page existed. Post-
revert the frontend is platform-shaped (Proxmox / Docker / Kubernetes
/ TrueNAS / vSphere / Standalone) and the model's purpose is to gate
visibility of each *platform* nav slot from resource evidence, not
gate visibility into a unified Infrastructure surface.

- frontend-modern/src/features/infrastructureNavigation/ -> .../platformNavigation/
- buildPrimaryInfrastructureNavigationVisibility -> buildPrimaryPlatformNavigationVisibility
- PrimaryInfrastructureNavId -> PrimaryPlatformNavId
- InfrastructureNavigationVisibility -> PlatformNavigationVisibility
- PRIMARY_INFRASTRUCTURE_NAV_IDS / _SCOPE_IDS -> PRIMARY_PLATFORM_NAV_IDS / _SCOPE_IDS
- primaryInfrastructureNavigationIsVisible -> primaryPlatformNavigationIsVisible
- selectFirstVisiblePrimaryInfrastructureNavigationId -> selectFirstVisiblePrimaryPlatformNavigationId
- filterInfrastructureNavigationShortcuts -> filterPlatformNavigationShortcuts
- createEmptyInfrastructureNavigationVisibility -> createEmptyPlatformNavigationVisibility
- infrastructureNavigationVisibilityFromResources -> platformNavigationVisibilityFromResources
- buildNavigableResourceInfrastructureScopeSet -> buildNavigableResourcePlatformScopeSet

Callers updated: App.tsx, AppLayout.tsx, useKeyboardShortcuts,
commandPaletteModel, useCommandPaletteState, KeyboardShortcutsModal,
CommandPaletteModal test, App.architecture test. Local variable and
prop names (infrastructureVisibility -> platformVisibility,
infrastructureNavigationVisibility -> platformNavigationVisibility,
infrastructureNavigationResolved -> platformNavigationResolved)
renamed for consistency.

The standalone visibility key is preserved. Standalone (Machines)
is a real evidence-gated nav slot in this model: AppLayout and
commandPaletteModel both consume isVisible('standalone') to hide
the Machines nav item when no Pulse Agent resources or availability
endpoints exist.

Visual crawl spec restored at tests/integration/tests/99-visual-crawl.spec.ts

The previous version of this spec crawled the unified IA routes
(/workloads, /infrastructure, /storage, /recovery, /operations) that
were retired in the rc.6 revert. Restored with a refreshed URL list
that targets the platform-shaped top-level pages and their
representative sub-routes (Proxmox PVE/PBS/Backups/Storage/Ceph,
Kubernetes nodes/deployments/config), plus Alerts, Patrol, and the
existing Settings routes. The DOM analysis body (headings, inputs,
tables, raw-color violations, screenshots, JSON report) is
unchanged.
2026-05-27 15:47:03 +01:00
rcourtman 8769f07eea Land SMART/SSH temperature feature, rc.6 finalization, and post-IA-revert governance reconciliation 2026-05-27 15:27:25 +01:00
rcourtman affc1c76ed Add rc.6 operator support pack and prerelease index pointers
Stages the doc-only subset of rc.6 packet prep work on top of
df7934936. Holds VERSION bump and the registry/contract governance
reconciliation back for a focused later pass since the IA revert
created broader subsystem-contract debt than the packet prep can
absorb.

- docs/releases/V6_RC6_OPERATOR_SUPPORT_PACK_DRAFT.md: new 300-line
  operator support brief mirroring the rc.5 pack with rc.6 themes:
  pre-release for testing framing, platform-shaped frontend revert
  explanation, vSphere as a first-class platform, Machines surface,
  TrueNAS native detail UX, FilterBar adoption, Patrol capacity-
  forecast and PDM bridge, free-first self-hosted posture, install.sh
  smoke gate. Carries the rc.5 free-first paid-continuity wording
  through unchanged so the operator-support-pack policy test holds.
- docs/releases/RELEASE_NOTES_v6_RC6_DRAFT.md,
  docs/releases/V6_CHANGELOG_RC6_DRAFT.md: fill in the SHA audit
  numbers (v6.0.0-rc.5..df7934936, 616 commits, 1379 files / 139185
  insertions / 67870 deletions). Add the licensing-continuity
  paragraph carrying the rc.5 Pulse Mobile pairing for handoff
  copy through unchanged so the discovered-packet policy test holds.
- docs/RELEASE_NOTES.md: link the rc.6 draft packet as current, push
  rc.5 to historical.
- docs/UPGRADE_v6.md: round out the prerelease packet pointer block
  with the rc.6 operator support pack path alongside the release
  notes and changelog already pointed at in df7934936.
- docs/releases/V6_PRERELEASE_RUNBOOK.md: add 6.0.0-rc.6 to the
  version-examples list and bump the RC_VERSION export shown in the
  RC release steps to rc.6.

Out of scope for this commit and intentionally held back until
governance reconciliation can land coherently:

- VERSION bump to 6.0.0-rc.6 (triggers deployment-installability
  shape-guard which cascades into registry/contract audits against
  72 dead-file references left over from the rc.6 IA revert).
- docs/release-control/v6/internal/status.json,
  docs/release-control/v6/internal/subsystems/registry.json, and the
  10 subsystem contract .md files that need post-IA-revert cleanup.
- scripts/release_control test fixture refreshes.
- The rc-to-ga-promotion-readiness-blocked record regen (gated on
  VERSION bump landing).

Working copies of the held-back files are preserved at
/tmp/rc6-prep-backup-2026-05-27/ with a MANIFEST.md describing each.
2026-05-27 13:37:24 +01:00
rcourtman ed8a9652b2 Add Machines row actions 2026-05-27 12:09:44 +01:00
rcourtman df79349368 Document rc.6 frontend IA revert in v6 release docs
rc.1-rc.5 shipped a unified /infrastructure /workloads /storage
/recovery top-level layout; rc.6 reverts the frontend to platform-
shaped pages (Proxmox / Docker / Kubernetes / TrueNAS / vSphere /
Standalone) on the same unified resource backend.

Updates the shipped v6 release docs to match:

- RELEASE_NOTES_v6.md and V6_CHANGELOG.md rewritten to describe the
  v6 layout as platform-shaped on a unified backend, with a paragraph
  in each explaining the rc.6 revert and the operator feedback that
  drove it.
- UPGRADE_v6.md prerelease packet pointer bumped from rc.5 to rc.6.
- MIGRATION_UNIFIED_NAV.md gets a top-of-file revert banner that
  redirects bookmarks targeting the unified routes to their platform-
  shaped equivalents; the original content is preserved below as a
  Historical Context section so the 19 tracked references into that
  doc still resolve.

Also adds the rc.6 draft packet:

- docs/releases/RELEASE_NOTES_v6_RC6_DRAFT.md
- docs/releases/V6_CHANGELOG_RC6_DRAFT.md

Validation SHAs in both drafts are left as <populate at packet
finalisation> markers; they fill in when the release-control packet
runs.
2026-05-27 11:50:59 +01:00