Commit Graph

6557 Commits

Author SHA1 Message Date
rcourtman cfb16e6da1 Retire legacy settings infrastructure aliases 2026-05-25 14:07:17 +01:00
rcourtman 3c0bd12fc6 Retire aggregate route-state path builders 2026-05-25 13:42:26 +01:00
rcourtman 3f9c8168fb Retire legacy top-level browser aliases 2026-05-25 13:16:42 +01:00
rcourtman 8b0b1b0c6e Retire aggregate top-level workspace routes 2026-05-25 12:34:57 +01:00
rcourtman c9be4c86f2 Clarify aggregate workspace routes 2026-05-25 11:43:35 +01:00
rcourtman e38f0b8e1f Remove legacy infrastructure route 2026-05-25 11:04:38 +01:00
rcourtman 48017e349a Surface endpoint monitoring in active infrastructure settings 2026-05-25 10:41:18 +01:00
rcourtman 3d7e5aba77 Use source language for infrastructure filters 2026-05-25 10:27:05 +01:00
rcourtman 052e344e1b Add Kubernetes RBAC inventory to the agent + canonical + UI
Closes the only API-coverage gap from the Docker / Kubernetes IA
maturity review: Roles, ClusterRoles, RoleBindings, and
ClusterRoleBindings now flow from the Kubernetes agent through the
canonical resource registry into the Kubernetes platform-page
Configuration tab.

Agent: pkg/agents/kubernetes/report.go gains four new report struct
types that carry summary counts plus subject-kind sets; individual
subject names and full PolicyRule contents are deliberately omitted
so Pulse stays a "what permissions exist where" surface, not an RBAC
enumeration tool. internal/kubernetesagent/agent.go gains four
collectors that call rbacv1.RoleList/ClusterRoleList/etc. through the
existing runKubernetesCallWithRetry wrapper, matching the
ServiceAccount collector's RBAC-forbidden retry pattern.

Canonical: internal/models mirrors with NormalizeCollections coverage;
convert* funcs in internal/monitoring/kubernetes_agents.go translate
agent report -> model; ResourceTypeK8sRole / K8sClusterRole /
K8sRoleBinding / K8sClusterRoleBinding join the canonical type set;
registry ingest* + adapter resourceFrom* functions emit one Resource
per RBAC object with ruleCount / roleKind / roleName / subjectCount /
subjectKinds / aggregationLabels on the K8s meta; search mapping in
internal/api/resources.go and the privacy allow-list in
internal/api/org_handlers.go pick up the four new type tokens; the
K8s privacy category in unifiedresources/policy_metadata.go classifies
them like the rest of K8s.

Frontend: ResourceType union + ResourceKubernetesMeta carry the new
kinds and RBAC summary fields; KubernetesPageSurface query asks for
them; the page model buckets them into the Configuration group;
KubernetesConfigTable renders Role / ClusterRole rule counts and the
aggregated flag, plus RoleBinding / ClusterRoleBinding role refs and
"N subjects · Kind1, Kind2 +overflow" subject summaries.

Curated demo seeds per-namespace Roles + RoleBindings plus an
aggregated ClusterRole + ClusterRoleBinding for pulse-demo-monitoring
in each cluster so the Configuration tab renders 18 RBAC rows across
the three demo clusters.

Contracts updated for the canonical-shape guard: monitoring,
api-contracts, unified-resources, frontend-primitives,
organization-settings (canonical) plus agent-lifecycle and
storage-recovery (dependent via Extension Points). Verification
proofs extended: kubernetes_registry_test.go, kubernetes_agents_test.go,
agent_inventory_test.go (new TestCollectRBACInventoryReportsSummaryCountsOnly
that pins the subject-name-omission contract), demo_scenarios_test.go,
adapter_coverage_test.go, contract_test.go, org_handlers_test.go,
resourceIdentity.test.ts, reportingResourceTypes.test.ts,
KubernetesConfigTable.test.tsx, and the
subsystem_lookup_test.py line-anchor bumps that the contract edits
shifted (api-contracts 246 -> 253, organization-settings 92 -> 93).

Verified:
- go build ./internal/... ./cmd/... clean
- go test ./internal/unifiedresources/..., ./internal/mock/...,
  ./internal/kubernetesagent/..., ./internal/api/...,
  the K8s subset of ./internal/monitoring/... all clean (three
  pre-existing unrelated monitoring failures noted earlier remain
  unchanged by this commit)
- npm run type-check, lint:eslint, lint:theme,
  lint:canonical-platforms clean
- vitest: 70 K8s frontend tests pass including the new RBAC render
  coverage in KubernetesConfigTable.test.tsx
- browser proof on /kubernetes/configuration: 36 config rows
  including 18 RBAC rows across three clusters; ClusterRole
  "pulse-demo-monitoring" shows "12 rules · Aggregated";
  ClusterRoleBinding shows "3 subjects · Group, ServiceAccount +1"
2026-05-25 09:25:03 +01:00
rcourtman 1460a069bc Surface availability endpoints in infrastructure 2026-05-25 09:11:45 +01:00
rcourtman 29b5a9cc00 Give each curated Kubernetes demo cluster a distinct story
Per-cluster node profiles, kubelet versions, and degraded scenarios
replace the global rotation that made every demo cluster look like a
copy of the same one. Production EU keeps its prod-euw1-k8s-{01..05}
nodes and the NotReady worker on prod-euw1-k8s-03 (preserving the
existing host-posture test contract). Staging EU runs
stage-euw1-k8s-{01..05} and carries the payments-worker
CrashLoopBackOff. Development EU runs dev-euw1-{01..05} and carries
an ImagePullBackOff on cron-nightly-backfill (re-labelled from the
previous "Pending / PodInitializing" rotation so the curated
reconciler doesn't recover it). The unused Edge profile gets distinct
edge-pop-{lax,nrt,fra,iad,sin}-01 names + k3s version for when the
cluster count is bumped above three.

A new TestKubernetesDemoClustersTellDistinctStories test guards the
slice goal: each cluster's nodes use its own prefix, exactly one
cluster carries each degraded scenario, and every cluster has a
unique kubelet version. The monitoring subsystem contract is updated
to reflect the new three-cluster cast (Production EU + Staging EU +
Development EU) plus the per-cluster scenario distribution.

Side effect: with distinct node names per cluster, the K8s page
model's cluster-to-node matching now resolves all five nodes for
each cluster (previously two clusters showed "0 nodes" because every
cluster's nodes shared the same prod-euw1-* names, breaking
buildKubernetesClusterChildCounts' clusterId lookup).

Verified:
- go vet ./internal/mock/..., go test ./internal/mock/... clean
- browser proof on /kubernetes/overview: three clusters render with
  distinct versions (v1.30.4 / v1.31.2 / v1.32.0-rc.1) and 5 nodes
  each (vs the previous 5/0/0 split)
- /kubernetes/nodes: 15 rows across the three clusters with three
  distinct name prefixes; one red NotReady dot on Production EU's
  prod-euw1-k8s-03; fourteen green Ready dots elsewhere
2026-05-25 08:28:20 +01:00
rcourtman 93e1dc8d65 Surface Docker / Kubernetes incident rollups on Overview
dockerPageModel and kubernetesPageModel now expose
buildDockerIncidentRows / buildKubernetesIncidentRows + filter helpers
that walk resource.incidents[] for each row and synthesize a rollup
row when only the rollup-level incident fields (incidentCount,
incidentSeverity, etc.) are populated. Both builders sort
critical -> warning -> info, then by priority, then by resource name.
Mirrors buildVmwareIncidentRows and buildTrueNASIncidentRows.

New DockerAlertsTable and KubernetesAlertsTable render the rows as
a domain-coloured StatusDot list with an expandable per-row detail
grid (host / runtime / swarm cluster for Docker; cluster / namespace
/ node / owner for Kubernetes). DockerPageSurface and
KubernetesPageSurface render the alerts table under the hosts /
clusters table on Overview, wrapped in <Show when=incidents.length>
so a clean estate stays clean. No new tab — the rollup sits beneath
the existing inventory the same way TrueNAS's AlertsTable does.

Verified:
- npm run type-check, lint:eslint, lint:theme, lint:canonical-platforms clean
- vitest: 155 tests pass across docker / kubernetes / platformPage suites,
  including 12 new page-model tests pinning incident builder + filter
  behaviour and 2 new alerts-table render tests pinning row order
  (critical -> warning -> info) and StatusDot variants
- browser proof on /docker/overview and /kubernetes/overview with a
  clean estate: alerts table correctly hidden when incidents.length == 0
2026-05-25 08:06:17 +01:00
rcourtman 51efea045b Lift Docker / Kubernetes search haystacks into the page models
frontend-modern/src/features/platformPage/sharedPlatformPage.tsx
carried ~90 lines of resource.docker?.* and resource.kubernetes?.*
field knowledge inside matchesPlatformSearch. That coupled the
cross-platform helper to two specific platforms — every new docker.*
or kubernetes.* field anyone wanted searchable had to be edited in a
shared file, and the same fields were duplicated inside
DockerContainersTable's bespoke search-candidates helper.

dockerPageModel now exports dockerResourceSearchHaystack +
filterDockerResources, and kubernetesPageModel exports
kubernetesResourceSearchHaystack + filterKubernetesResources, each
covering the platform's own generic + meta fields and the composite
labels operators are likely to paste (e.g. "0.0.0.0:8080->80/tcp" on
container rows). All 12 Docker tables and all 12 Kubernetes tables now
import the per-platform filter; the bespoke DockerContainersTable
filter helper disappears since the page-model haystack subsumes it.

matchesPlatformSearch in sharedPlatformPage drops every docker.* and
kubernetes.* reference. The shared helper still serves the four
providers that consume it directly without a domain-specific haystack
(TrueNAS systems, Proxmox Mail Gateway, vSphere hosts, Agents), so
generic + pmg.* + vmware.* + tags stay. Existing sharedPlatformPage
test coverage of docker/k8s native metadata moves to the per-platform
page-model tests.

Verified:
- npm run type-check, lint:eslint, lint:theme, lint:canonical-platforms clean
- vitest: 138 tests pass across docker / kubernetes / platformPage suites
- browser proof on /docker/containers searching "traefik" trims 70 -> 6
  by docker.image; on /kubernetes/workloads searching "payments" trims
  42 -> 9 by kubernetes.namespace, "production-eu" trims to 14 by
  kubernetes.clusterName
2026-05-25 07:47:47 +01:00
rcourtman ec2bd4007f Lift Kubernetes cluster child counts into the page model
KubernetesClustersTable used to walk the entire resource scope inline
to count Nodes / Pods / Deployments per cluster, with a comment
apologizing for the cluster-id matching being brittle. That rollup now
lives on the page model as buildKubernetesClusterChildCounts(scope,
clusters), reusable by future Overview surfaces (incident rollups,
"active issues" cards) and pinned by tests on the model side.

The formula is unchanged: each resource looks up its owning cluster by
matching kubernetes.clusterId or kubernetes.clusterName against the
cluster row's own kubernetes meta, then increments the corresponding
counter. Agent rows that report a Kubernetes source still count as
nodes. The table now just memoises a call into the model helper.

No backend changes. Browser proof on /kubernetes/overview shows the
clusters table renders identical Nodes/Pods/Deployments counts as
before the lift.
2026-05-24 21:37:05 +01:00
rcourtman 9332397b7c Lift Docker status mappers into the page model
Container, Swarm service, Swarm task, and Swarm node rows now derive
their StatusDot variant from Docker-specific state instead of the
generic resource.status triad. Dead/OOMKilled containers, unhealthy
running containers, exited-non-zero containers, services with running
< desired replicas, paused service rollbacks, failed/rejected Swarm
tasks, and unreachable Swarm managers all escalate to attention
without depending on what the unified-resource pipeline happened to
set as the row's overall status.

Each affected table also consumes a rank comparator (danger ->
warning -> muted -> success, tie-broken by display name) so attention
rows float to the top regardless of input order, and the corresponding
page-model buckets (containers, services, tasks, nodes) ship
pre-sorted so any consumer that bypasses the table-local sort still
gets the right ordering.

DockerResourceNameCell now accepts an optional indicator so
table-side mappers can drive the dot variant and tooltip without
re-doing the layout. Mapper truth tables and comparator order are
pinned in dockerPageModel.test.ts; the containers native-table test
pins rendered StatusDot variant plus row order on a four-row mixed
input.
2026-05-24 21:28:50 +01:00
rcourtman d724528caf Lift Kubernetes status mappers into the page model
Pod, node, deployment, and controller (ReplicaSet / StatefulSet /
DaemonSet / Job / CronJob) rows now derive their StatusDot variant
from kubernetes-specific state instead of the generic resource.status
triad. CrashLoopBackOff, ImagePullBackOff, OOMKilled, NotReady nodes,
and under-replicated controllers escalate to attention without
depending on whatever the unified-resource pipeline happened to set as
the row's overall status.

Each affected table also consumes a rank comparator (danger ->
warning -> muted -> success, tie-broken by display name) so attention
rows float to the top regardless of input order, and the corresponding
page-model buckets (pods, deployments, nodes, workloads) ship
pre-sorted to keep Overview and Workloads consistent.

Mapper truth tables and comparator order are pinned in
kubernetesPageModel.test.ts; KubernetesPodsTable and
KubernetesDeploymentsTable tests pin the rendered StatusDot variant
plus row order on synthetic three-row inputs.
2026-05-24 21:14:08 +01:00
rcourtman 080c38a066 Fix Kubernetes event ordering 2026-05-24 20:57:05 +01:00
rcourtman 27e72ec8b4 Fix platform IA review findings 2026-05-24 20:37:52 +01:00
rcourtman 6d7ee5d732 Tighten platform overview IA 2026-05-24 19:41:29 +01:00
rcourtman c713027379 Normalize Kubernetes workflow tab contracts 2026-05-24 19:26:04 +01:00
rcourtman a590024ca0 Consolidate container and Kubernetes platform tabs 2026-05-24 19:20:14 +01:00
rcourtman 3403104662 Expose Docker and Kubernetes API tab fields 2026-05-24 18:47:55 +01:00
rcourtman 223b11185f Add native Docker containers table 2026-05-24 17:41:35 +01:00
rcourtman a76a75bdf6 Split Kubernetes workload tabs 2026-05-24 17:13:26 +01:00
rcourtman f59ec0ceaf Add Kubernetes controllers native table 2026-05-24 16:38:49 +01:00
rcourtman a353d11493 Split Docker inventory into native tables 2026-05-24 15:54:23 +01:00
rcourtman eab8f0969b Add Kubernetes events native table 2026-05-24 15:32:19 +01:00
rcourtman ad844ece90 Add Kubernetes autoscaling native table 2026-05-24 15:20:59 +01:00
rcourtman 65e7147f2e Add Kubernetes policy native table 2026-05-24 15:10:36 +01:00
rcourtman 9d149ac11a Add Kubernetes config native table 2026-05-24 14:53:03 +01:00
rcourtman aa14a96644 Add Kubernetes services native table 2026-05-24 14:34:13 +01:00
rcourtman ecd3e4d377 Add Kubernetes networking native table 2026-05-24 14:21:25 +01:00
rcourtman 0d22db1a27 Add Kubernetes storage native table 2026-05-24 14:05:34 +01:00
rcourtman c8380613d7 Seed native platform tab fixtures 2026-05-24 13:16:00 +01:00
rcourtman 7c58ca0f79 Promote Kubernetes nodes to platform tab 2026-05-24 12:52:54 +01:00
rcourtman 49c9ca7656 Use metadata-only Kubernetes config inventory 2026-05-24 12:36:50 +01:00
rcourtman 120dd5353a Expand Docker Swarm metadata inventory 2026-05-24 12:07:10 +01:00
rcourtman 0d67ca1b4a Expand Kubernetes API-native inventory surfaces
Collect native Kubernetes config, policy, and autoscaling objects.
Project the new resource types through API filters, unified resources, mock fixtures, and Kubernetes tabs.
Keep Secret inventory metadata-only and route k8s-secret policy as restricted local-only.
2026-05-24 11:12:33 +01:00
rcourtman 89abed099c Expand Docker runtime inventory coverage 2026-05-24 10:24:42 +01:00
rcourtman f18502fc24 Expand Kubernetes native inventory coverage 2026-05-24 09:40:58 +01:00
rcourtman 6346929328 Expand Docker and Kubernetes platform projections 2026-05-24 08:58:02 +01:00
rcourtman d3934e19e3 Harden repository advisory boundaries 2026-05-24 08:15:29 +01:00
rcourtman db3cbf3952 Recognize 'network' as a canonical resource type
Without an explicit case for `network`, `canonicalizeFrontendResourceType`
returned `undefined` and `resolveType` fell through to its `'agent'`
default, which is why REST-normalized vSphere network resources briefly
appeared in the vSphere Hosts table on Overview. The WS snapshot then
corrected the type to 'network' and they vanished, producing the
"lots of entries that disappear" flicker.
2026-05-23 21:51:10 +01:00
rcourtman 6252f7d302 Use canonical MetricBar for TrueNAS Storage usage cell
The TrueNAS Storage table was hand-rolling a thin emerald slab below
the used/total text, which read as cosmetic and didn't match any other
v6 platform table. Swap for ResponsiveMetricCell type="disk", which
renders the canonical MetricBar with the percentage label inside the
fill, severity-aligned coloring, sparkline support, and "used / total"
as the sublabel — the same primitive used by vSphere Datastores,
Proxmox Storage/Nodes, Docker Hosts, Kubernetes Nodes, and the other
TrueNAS tables (Apps, Systems).

Physical-disk rows have no used/total, so they fall back to a plain
"4.00 TB" size label rather than rendering a degenerate bar.
2026-05-23 21:42:57 +01:00
rcourtman 5454f4e15b Tighten TrueNAS Storage page to peer pattern
Bring TrueNAS Storage table in line with Kubernetes/Docker/Proxmox
peers on the canonical platform primitives.

- Add coloured leading dots to Healthy/Attention/Offline chips so the
  filter toolbar matches PLATFORM_HEALTH_FILTER_OPTIONS.
- Drop the redundant State column. Health was being signalled three
  times (row status dot, raw ZFS/SMART text, Health pill); raw state
  still surfaces in the resource drawer.
- Drop the Shares column, which printed 0 on nearly every row; share
  count remains available in the dataset detail.
- Rename TableCardHeader title to "Storage" to match peer titles
  ("Nodes", "Services", "Deployments").
2026-05-23 21:39:34 +01:00
rcourtman 2bec995c10 Normalize provider-first status summaries
Update release-control status summaries to point at the provider-first platform landing decision instead of the superseded Infrastructure default.
2026-05-23 21:21:09 +01:00
rcourtman f1a29681ce Hide overview-only platform section tabs 2026-05-23 21:17:40 +01:00
rcourtman e2b7920f9d Normalize provider-first landing docs
Remove stale Infrastructure-default landing language from frontend and performance contracts after the provider-first platform landing decision.
2026-05-23 21:15:42 +01:00
rcourtman e96b046fc3 Keep platform landing provider-first
Keep authenticated platform landing and shell ordering provider-first, with Agents reserved as the fallback for agent-only estates.
2026-05-23 21:10:27 +01:00
rcourtman 4c422aa2a2 Keep Agents secondary in platform navigation
Prefer provider and runtime platform pages ahead of Agents for landing, primary navigation, mobile ordering, preloading, and command palette ordering.
2026-05-23 20:45:40 +01:00