Skip to content

Share the workspace building blocks extracted from the CloudNativePG workspace - #1969

Merged
nadaverell merged 27 commits into
feature/cnpg-actions-runtimefrom
feature/cnpg-workspace-kit
Oct 4, 2026
Merged

nadaverell merged 27 commits into
feature/cnpg-actions-runtimefrom
feature/cnpg-workspace-kit

Conversation

@nadaverell

@nadaverell nadaverell commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The CloudNativePG workspace (#1921, #1922) carried a generic layer under CNPG names: the facts and problem list on every summary, per-kind coverage, the reviewed-action contract, grants, Prometheus series attribution, and screen layout borrowed from Capacity's internals. This PR moves that layer into shared, integration-neutral modules, so the next workspace-style integration (Velero is the likely one) imports it instead of copying CNPG.

Nothing here is released yet, so the three CNPG wire shapes that every future workspace would copy are fixed now:

  • grants are structured objects, not sentences;
  • "not cached by Radar" is told apart from "no access";
  • each object's GitOps manager comes from the server.

It also adds the version-skew gate the CNPG endpoints were missing.

Only mechanisms whose interface is already evident in today's code are shared: each has two or more consumers, or is a contract every workspace must follow. The rest is listed below as not shared yet.

What changed

Shared UI (@skyhook-io/k8s-ui)

  • components/facts/, for any surface that shows observed values (single-kind renderers included):
    • Fact, with FactGrid/FactRow/FactValue/FactSource
    • CertaintyGlyph, moved from Capacity; CapacityCertainty stays as the same type
    • ManagedByText
  • components/problems/: WorkspaceProblem<Category> and ProblemCallout/ProblemList/ProblemMeta, which take the workspace's rootKind instead of a hard-coded 'Cluster', plus OpenIssueContext.
  • ui/FoldSection: SectionHeading, FoldSection, FoldSummary.
  • Elsewhere in k8s-ui:
    • ui/RefLink now uses the existing ResourceRef.
    • toneTextClass and worseTone live in ui/status-tone.
    • utils/grant adds Grant, formatGrant and grantParts.
    • issueReasonTitle gives a reason one title on both the Issues page and the workspace.
  • Kept CNPG-specific: categories, ordering, wording and builders. CNPG binds WorkspaceProblem to its own categories.
  • Badges: CNPG badges now use healthToSeverity like the rest of the app.
  • Buttons: secondary buttons use a new .btn-secondary class (documented in DESIGN.md) instead of ten hand-rolled class strings.
  • Sidebar: SidebarCategoryDestination.countLowerBound renders a count over partly read data as ≥N, and its zero as unknown rather than none.

App (web/)

  • components/workspace/ holds the screen primitives Capacity and CNPG share: ScreenBody, ScreenEmptyState, Notice, Segments, FilterChips, SectionTable and its table classes, RefreshFailedNotice, GrantText, and the text helpers. CNPG no longer imports from capacity/shared.tsx.
  • api/actions.ts is the client half of the action contract:
    • the ActionCapability and ActionRequest types
    • actionErrorCode, which an integration widens with its own codes
    • actionOutcomeLocked and actionCompleted
    • capabilityReason, now the one "why is this disabled" wording
  • Utilities: utils/drawer-trail.ts holds the ?drawer= codec, and utils/page-links.ts the back label and the subject-filtered Issues link.
  • Kind table: CNPG's detail kinds derive kind and group from the workspace kind table.

Server

  • internal/server/actions.go: the reviewed-action contract.
    • ActionCapability, ActionRequest, decodeActionRequest and decodeActionParams
    • refusals: changedAction, blockedAction, partialAction and writeActionError
    • the permission decision: grantPermission and capabilityVerdict, with a real SelfSubjectAccessReview in local mode
    • mergePatchAtVersion
  • Grants: Grant lives in internal/auth and carries In(ns) and String().
  • Kind access: kind_access.go covers per-kind access and coverage (readWorkspaceKind, typedKindScope, KindCoverage); cache_scope.go has namespacesWithinCache.
  • Other shared helpers:
    • read_source.go: one ReadSource shape for HA, recovery and storage
    • fanout.go: the bounded per-namespace fan-out
    • internal/prometheus/series_scope.go: SeriesIsolation, already used by the PVC usage charts
  • Kept CNPG-specific: facts, guards, runners and the extra refusal codes.
  • Exported manager detection: pkg/topology now exports ManagedByFromMeta. This is additive.

Wire changes (CNPG endpoints, unreleased)

  • grant is {verb, group?, resource, subresource?, namespace?} (no namespace means cluster-wide) on every capability, read source, chart and report item. The wording is unchanged and comes from Grant.String() / formatGrant.

  • Kind coverage gains:

    • a state uncached, for a scope Radar's cache does not cover at all;
    • uncachedNamespaces, named under the same rule as deniedNamespaces.

    Before, a namespace the caller can read but Radar does not cache was reported as denied, and the UI said "No access". It now says "Radar does not cache Pods in db".

  • /api/cnpg/workspace gains managedBy, keyed Kind/ns/name.

    • "Declared in" now uses the server's manager detection and links to the Argo CD application or Flux object.
    • Before, the client parsed labels itself. That misnamed Argo CD applications living outside Argo CD's namespace (ns_app) and ignored the Flux namespace label.

Version skew

New FeatureCapabilities flags: cnpgWorkspace (every /api/cnpg/* route except the two image-catalog lookups that predate it) and gitopsWriteEvidence. Each has a radarFeatures entry.

Every CNPG query, mutation, log stream, report download and the write-evidence query goes through useRadarFeature. Mutations are never retried. On a Radar without the workspace:

  • the sidebar offers no workspace destinations;
  • /workload links and drawer Expand stay on the standard views;
  • a Cluster's Logs tab shows its Pods' logs;
  • a workspace screen opened directly says it needs a newer Radar.

Vocabulary

On screen these areas are named by their subject. The block above a sidebar category's kinds reads Views, and the copy says "CloudNativePG views" and "CloudNativePG data", never "workspace", because Radar Hub uses "workspace" for the customer's account. "Workspace" remains the internal term for an integration with several kinds and its own screens (the integration guide, SidebarCategoryWorkspace, /api/cnpg/workspace).

Docs

  • DESIGN.md: the rules for unknown, partial and denied values are written once. capacity.md and cnpg.md link to them and keep their per-value tables.
  • docs/INTEGRATION_GUIDE.md: a new "Workspace integrations" chapter covering when a workspace is warranted, the pieces to import, and what is not shared yet. CLAUDE.md points to it.

Not shared yet

These have one consumer, and their interface should come from the second:

  • the workspace registry / App wiring
  • the operation tracker
  • the generic action runner
  • the fixed-path pods/proxy reader
  • the merged log stream
  • the report bundle
  • operator diagnosis
  • a TTL-memo helper

Rollouts' capabilities answer "allowed" in local mode without asking the apiserver. That is a real bug, but Rollouts returns bare booleans and hides denied actions, so it needs its own PR.

Public surface

Testing

  • Go: go build ./...; go test ./... in both modules. The cmd/desktop env test is flaky and passes alone. gofmt -l is clean.
  • Frontend:
    • type checks pass for web and k8s-ui;
    • vitest: k8s-ui 236 files / 4,369 tests, web 182 files / 2,028 tests;
    • eslint: 0 errors, and no new warnings.
  • Live on the kind CloudNativePG demo, full access and a view-only identity:
    • every CNPG page rendered with structured grants and no "[object Object]" or "undefined";
    • a namespaced Argo CD tracking ID on a demo Cluster showed "Declared in: Argo CD application argocd/payments", linked;
    • with the capability flags removed from /api/capabilities (an older Radar behind Radar Hub), the sidebar workspace, redirects, composed summaries and actions fell back to the standard views, and /cnpg showed the upgrade note.

Stacked on #1922 (which is stacked on #1921). Merge order: #1921, #1922, then this PR, before a release ships /api/cnpg/*.


Note

Medium Risk
Touches CNPG API shapes, RBAC/coverage semantics, and cluster write paths via the shared action layer; behavior is intended to be equivalent with clearer grant and cache messaging.

Overview
Extracts the generic workspace layer that CloudNativePG had under CNPG-specific names into shared modules, so future integrations (e.g. Capacity-style screens) import one contract instead of copying.

Server: Adds internal/auth.Grant (structured RBAC on the wire), internal/server/actions.go (reviewed ActionRequest, capabilities, 409/partial errors, mergePatchAtVersion), cache_scope.go / kind_access patterns, and prometheus/series_scope.go (shared Prometheus isolation). CNPG handlers now use these; history/PVC denial fields expose *Grant instead of strings. FeatureCapabilities adds cnpgWorkspace and gitopsWriteEvidence. CNPG workspace coverage gains uncached / uncachedNamespaces (distinct from denied) and managedBy from server-side GitOps detection.

UI: New k8s-ui facts/, problems/, fold sections, formatGrant, and app components/workspace/ plus api/actions.ts. CNPG is rewired to structured grants and shared action types; secondary buttons use .btn-secondary.

Docs: DESIGN.md documents unknown/partial/denied values once; INTEGRATION_GUIDE adds a workspace-integrations chapter; CLAUDE.md points builders at it.

Reviewed by Cursor Bugbot for commit 5af6ed1. Bugbot is set up for automated code reviews on this repo. Configure here.

Facts, sections and the problem list become components/workspace in
k8s-ui (Fact, FactGrid/Row/Value/Source, SectionHeading, FoldSection,
FoldSummary, WorkspaceProblem with a rootKind prop, OpenIssueContext),
RefLink moves to ui/ on the existing ResourceRef type, and toneTextClass
and worseTone join toneFillClass in ui/status-tone. CloudNativePG keeps its
categories, ordering, wording and builders, and binds WorkspaceProblem to
its own categories.

Badges read health through healthToSeverity like the rest of the app, and
secondary buttons use a new .btn-secondary class instead of hand-rolled
class strings.
The cluster-identity scope that keeps a query to this cluster's series
already serves PVC usage and the single-claim chart, so it moves to
series_scope.go under neutral names: SeriesIsolation, ErrScopeAmbiguous,
ErrScopeMismatch, ClaimSelectors. JSON tags and decisions are unchanged.
namespacesWithinCache, cacheCoversNamespace and the informerScope interface
move from capacity_auth.go to cache_scope.go: Capacity and CloudNativePG
both use them to tell what Radar's informer holds from what the caller
asked for. Behaviour, including nil (all namespaces) versus empty, is
unchanged.
web/src/components/workspace holds what both workspaces' screens are built
from: Notice, ScreenEmptyState, ScreenBody, Segments, FilterChips,
SectionTable, the shared table classes, text helpers and the
refresh-failed notice. CloudNativePG no longer imports Capacity's internals,
and keeps only its own header, gate and coverage wrappers.

The drawer-trail URL codec moves to utils/drawer-trail, the back label and
the subject-filtered Issues link to utils/page-links, and CloudNativePG's
detail kinds take kind and group from the workspace kind table.
listScope, typedKindScope, accessFromScope, kindAccess (with covers and
coverage), KindCoverage and its states, readWorkspaceKind and keepGroups
move to kind_access.go so the next workspace reads its kinds the same way.
The group filter takes its groups as a parameter; CloudNativePG passes its
two groups through cnpgWorkspaceReadKind and filterCNPGGroup. kindAccess
now carries its denied namespaces instead of returning them alongside.
Group filtering, the namespace-disclosure rule and every state are
unchanged.
A grant arrives as {verb, group, resource, subresource, namespace} instead
of a sentence the client had to split back apart. formatGrant and
grantParts in k8s-ui word it exactly as the server's Grant.String does,
GrantText renders the parts without a regex, and every CloudNativePG type
and message that carries a grant takes the object.
A namespace the caller may list but Radar's informer does not hold was
named in deniedNamespaces, and a scope the cache did not hold at all read
as error. Kind coverage now names such namespaces in uncachedNamespaces,
under the same disclosure rule as deniedNamespaces, and a scope the cache
holds none of has the state uncached. A partial result may carry both
lists. The HA operator-lease reason no longer tells the caller the
Deployment is hidden from them when Radar simply does not watch it.
actions.go now holds what any integration's write actions share:
ActionCapability and ActionRequest, actionError with refuseAction,
changedAction, blockedAction and partialAction, the changed /
context_changed / blocked / partial codes, decodeActionRequest (bounded
body, required fields, the caller's dynamic client, reviewed-context
check), decodeActionParams, the generic half of the error writer, and
mergePatchAtVersion.

The permission machinery moves with it: a Grant (verb, group, resource,
subresource, namespace) in internal/auth so Prometheus-backed reads can
name one too, grantPermission/grantDecision (the per-user SAR cache with
resource/subresource keys under auth, the 30s SelfSubjectAccessReview
memo locally), and capabilityVerdict. Grant.String() words a namespaced
grant and a cluster-wide one exactly as the two CNPG methods did.

CloudNativePG keeps its result fields, its all_fenced /
operator_webhook_unavailable / invalid_schedule / outcome_unknown codes,
the webhook wording, facts, guards, runners and grant templates. The wire
is unchanged.
Every grant on the wire is now {verb, group?, resource, subresource?,
namespace?} (no namespace means cluster-wide) rather than a sentence the
client had to split apart: action capabilities, HA, recovery, storage,
fleet disk/lag/growth and history coverage, the runtime proxy and exec
permissions, and the Prometheus history charts. Grants that were built
as literal strings now come from grant templates too. Reason strings
still embed the worded grant, with unchanged text where it came from a
template; grantText words an optional one.
CNPGHASource, CNPGReadCoverage and CNPGStorageCoverage were the same
{state, grant, reason} struct under three names; ReadSource replaces the
first two and storage coverage embeds it beside its isolation field. Each
source keeps its own state constants and classifier, including how it
reads a timeout. JSON is unchanged.
Radar Hub embeds the newest frontend against whatever Radar a cluster runs,
so every /api/cnpg endpoint the workspace added, and the GitOps
write-evidence read, now has a capability flag (cnpgWorkspace,
gitopsWriteEvidence) and a radarFeatures entry. Every CloudNativePG hook,
the log fetch and stream, the report download and the write-evidence query
go through the feature guard. On a Radar without the workspace the sidebar
offers no workspace destinations, a /workload link stays on the standard
view, the drawer and detail page drop the composed summary, actions and
extra tabs, and a workspace screen opened directly says it needs a newer
Radar. The two image-catalog lookups that predate the workspace stay
ungated.

A sidebar destination count taken over partly readable data is now a
lower bound on screen as well as in its tooltip: it renders "≥N", and a
zero renders the unknown dash rather than no badge. The certainty glyph
moves into k8s-ui (components/workspace/certainty) for the sidebar and
Capacity to share; CapacityCertainty is the same type under its old name.
The fleet metrics and fleet disk handlers each hand-rolled a semaphore,
cancellation check, indexed results and join. fanOut does that
scheduling; each handler still fans out over at most 64 namespaces,
answers the rest as notRead itself and sorts its rows.
The Issues page and the workspace titled WAL archiving and the latest
backup failure in two wordings. issueReasonTitle now answers for those
reasons in both places; the workspace keeps titles only for reasons the
Issues page does not title itself.
The workspace client re-parsed Argo CD and Flux labels itself and read an
apps-in-any-namespace tracking ID's ns_app prefix as the Application
name. topology.ManagedByFromMeta (the existing metadata-only detection,
now exported; nothing else in pkg changes) answers instead, and
/api/cnpg/workspace returns managedBy keyed Kind/namespace/name for every
returned CNPG object with a manager signal. A native Helm release keeps
an empty group and an Application named without a namespace keeps an
empty one.
web/src/api/actions.ts holds the client half of the action contract:
ActionCapability and ActionRequest, the shared refusal codes with
actionErrorCode (an integration widens it with its own codes, as
CloudNativePG does for all_fenced, operator_webhook_unavailable and
invalid_schedule), actionOutcomeLocked, actionCompleted, and
capabilityReason, which now words every disabled CloudNativePG action the
same way and names the missing grant when the server gives no reason.
DESIGN.md states how a surface that reads several sources shows what it
could not read, what it read in part and where a value came from, and
names the shared components that do it. Capacity and CloudNativePG link to
it and keep their own per-value tables.
Coverage gains the uncached state and uncachedNamespaces. One function,
cnpgCoverageGap, words why a kind was not read for both the workspace facts
and the related-object lookups: no access only when the namespace is named
as denied, "Radar does not cache …" when it is named as uncached, and
"not read" when the server names neither cause. Empty states and the
coverage notice word the uncached case the same way.
The workspace read Argo CD and Flux labels itself, which misnamed Argo CD
applications that live outside Argo CD's namespace and ignored the Flux
namespace label. It now uses the managedBy the server derives for each
object, and the shared ManagedByText names the manager as "Argo CD
application argocd/app" or "Flux Kustomization …", linking it when its
namespace is recorded; gitOpsOwnerFromRef is exported for it.

The operator page's coverage notice words its gaps like the workspace
notice ("not cached by Radar in pg") instead of printing raw states.
The integration guide gains a Workspace integrations chapter: when a
workspace is warranted, and the server, UI, navigation, version-skew and
action pieces a new one imports instead of copying, plus the ones that are
not shared yet because a second integration should shape them. CLAUDE.md
points at it, and docs/cnpg.md describes the grant object, the uncached
coverage state, managedBy and the cnpgWorkspace capability flag.
…space

A /workload link and a drawer's Expand now open the workspace page only once
the Radar is known to serve it, since the redirect replaces the URL; while
capabilities load, or on an older Radar, they stay on the standard view,
and a Cluster's Logs tab keeps the Pod logs instead of the merged instance
stream. useRadarFeature returns a stable guard, so a callback built on it,
like the Cluster log fetch, no longer reloads a running stream on every
render. A namespace the server names as denied or uncached now decides the
wording even when the kind's overall state is uncached, and an empty list
names both causes when both apply.
@nadaverell
nadaverell requested a review from hisco as a code owner October 3, 2026 23:43
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Extract shared workspace building blocks from CloudNativePG

✨ Enhancement 🐞 Bug fix 📝 Documentation 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Extract reusable workspace UI, access, action, and metrics contracts without generalizing
 CNPG-specific behavior.
• Correct CNPG grants, cache coverage, and GitOps ownership before the endpoints ship.
• Gate workspace features for older Radar versions and document how future integrations should use
 them.
Diagram

graph TD
  App["App and routes"] --> Gate["Feature gate"] --> Hooks["CNPG API hooks"] --> Server["CNPG endpoints"] --> Access["Shared access contracts"]
  Server --> Metrics["Series isolation"]
  Hooks --> UI["Workspace UI"]
  App --> UI
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Generalize the entire workspace framework now
  • ➕ Could provide one registry and lifecycle for every integration.
  • ➖ Would define interfaces for CNPG-only features before a second consumer validates them.
  • ➖ Increases migration and review risk.

Recommendation: Keep the incremental extraction. Shared contracts already have identifiable consumers or necessary cross-workspace wire semantics; defer the registry, runners, logs, and reports until another integration establishes their requirements.

Files changed (181) +3721 / -3000

Enhancement (25) +1143 / -864
grant.goIntroduce structured Kubernetes grants +43/-0

Introduce structured Kubernetes grants

• Defines a serializable RBAC grant with namespace binding and human-readable formatting.

internal/auth/grant.go

capabilities.goAdvertise workspace and write-evidence features +3/-0

Advertise workspace and write-evidence features

• Adds capability flags for CNPG workspace endpoints and GitOps write evidence.

internal/k8s/capabilities.go

actions.goExtract reviewed-action server contract +361/-0

Extract reviewed-action server contract

• Centralizes request validation, permission verdicts, structured refusals, local access reviews, and version-bound patches.

internal/server/actions.go

cnpg_cluster_ha.goReturn structured HA read grants +61/-66

Return structured HA read grants

• Uses the common ReadSource and Grant types for HA subreads and denied explanations.

internal/server/cnpg_cluster_ha.go

cnpg_recovery.goStructure recovery read grants +38/-46

Structure recovery read grants

• Adopts shared read sources, grants, and action helpers for recovery operations.

internal/server/cnpg_recovery.go

cnpg_report.goReturn structured report grants +22/-22

Return structured report grants

• Represents report-item read requirements with Grant objects.

internal/server/cnpg_report.go

cnpg_workspace.goUse shared kind coverage and server manager detection +45/-218

Use shared kind coverage and server manager detection

• Moves per-kind access to the shared reader, distinguishes uncached data, and includes server-derived managedBy references.

internal/server/cnpg_workspace.go

kind_access.goExtract workspace kind authorization and coverage +231/-0

Extract workspace kind authorization and coverage

• Shares dynamic and typed kind reads, including disclosure-safe denied and uncached namespace reporting.

internal/server/kind_access.go

read_source.goDefine common subread outcome +12/-0

Define common subread outcome

• Introduces a state, reason, and optional structured grant for workspace read sources.

internal/server/read_source.go

server.goServe new feature capability flags +9/-7

Serve new feature capability flags

• Marks CNPG workspace and GitOps write evidence as supported by this Radar.

internal/server/server.go

CNPGClusterHASection.tsxAdopt structured HA grant rendering +7/-4

Adopt structured HA grant rendering

• Uses shared workspace presentation and grant formatting for HA sources.

packages/k8s-ui/src/components/cnpg/CNPGClusterHASection.tsx

ha.tsFormat structured HA grants +11/-15

Format structured HA grants

• Converts HA read-source Grant objects into consistent user-facing facts.

packages/k8s-ui/src/components/cnpg/ha.ts

workspace.tsBind CNPG builders to shared workspace contracts +72/-120

Bind CNPG builders to shared workspace contracts

• Uses shared Fact and WorkspaceProblem types, structured grants, uncached coverage, and server-supplied managedBy references.

packages/k8s-ui/src/components/cnpg/workspace.ts

components.cssAdd standard secondary-button styling +15/-0

Add standard secondary-button styling

• Introduces btn-secondary to replace repeated inline button classes.

packages/k8s-ui/src/theme/components.css

grant.tsAdd client grant contract +36/-0

Add client grant contract

• Defines Grant and human-readable formatGrant and grantParts matching server grant semantics.

packages/k8s-ui/src/utils/grant.ts

managedby.goExport metadata-only manager detection +11/-7

Export metadata-only manager detection

• Exposes ManagedByFromMeta for server use without requiring a topology graph.

pkg/topology/managedby.go

cnpg-ha.tsGate and type CNPG HA reads +6/-5

Gate and type CNPG HA reads

• Uses shared grant-bearing sources and the CNPG workspace feature guard.

web/src/api/cnpg-ha.ts

cnpg-history.tsGate CNPG history and charts +16/-11

Gate CNPG history and charts

• Protects history requests on older Radars and uses structured grant types.

web/src/api/cnpg-history.ts

cnpg-recovery.tsGate recovery API calls +16/-11

Gate recovery API calls

• Guards recovery reads and writes and adopts shared action and grant contracts.

web/src/api/cnpg-recovery.ts

cnpg-sessions.tsGate CNPG session endpoints +21/-15

Gate CNPG session endpoints

• Protects session queries and uses structured access-grant responses.

web/src/api/cnpg-sessions.ts

cnpg-storage.tsGate CNPG storage endpoints +9/-7

Gate CNPG storage endpoints

• Guards storage requests and types returned read grants as objects.

web/src/api/cnpg-storage.ts

cnpg.tsGate core CNPG queries and actions +51/-74

Gate core CNPG queries and actions

• Uses useRadarFeature for workspace endpoints and shared action types; mutations are not retried.

web/src/api/cnpg.ts

radarFeatures.tsRegister workspace feature gates +2/-0

Register workspace feature gates

• Adds CNPG workspace and GitOps write-evidence feature specifications.

web/src/api/radarFeatures.ts

CNPGReportDialog.tsxRender structured report grants +3/-1

Render structured report grants

• Displays report permission requirements through shared grant formatting.

web/src/components/cnpg/actions/CNPGReportDialog.tsx

shared.tsxKeep CNPG-specific screen logic only +42/-235

Keep CNPG-specific screen logic only

• Moves generic layout out, adds uncached coverage wording, and shows an upgrade state on unsupported Radars.

web/src/components/cnpg/shared.tsx

Bug fix (10) +129 / -90
relations.tsStop inferring manager ownership in CNPG UI +8/-43

Stop inferring manager ownership in CNPG UI

• Removes label-based GitOps ownership inference and retains CNPG relationship logic.

packages/k8s-ui/src/components/cnpg/relations.ts

ResourcesSidebar.tsxDistinguish lower-bound workspace counts +8/-2

Distinguish lower-bound workspace counts

• Adds countLowerBound and renders partial counts as ≥N, with zero shown as unknown.

packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx

managed-by.tsxRender server-derived GitOps managers +36/-0

Render server-derived GitOps managers

• Displays Argo CD and Flux manager references, linking only when a namespace is known.

packages/k8s-ui/src/components/workspace/managed-by.tsx

gitops-owner.tsInterpret server manager references +3/-2

Interpret server manager references

• Adds GitOps owner conversion from ResourceRef instead of inferring CNPG ownership client-side.

packages/k8s-ui/src/utils/gitops-owner.ts

App.tsxGate CNPG app navigation +5/-3

Gate CNPG app navigation

• Restricts workspace-specific routing behavior according to Radar feature support.

web/src/App.tsx

CNPGClusterLogs.tsxGuard CNPG log streaming +6/-4

Guard CNPG log streaming

• Prevents workspace log requests against unsupported Radars.

web/src/components/cnpg/CNPGClusterLogs.tsx

CNPGOverview.tsxRender server-derived ownership in fleet +11/-9

Render server-derived ownership in fleet

• Uses common workspace layout and manager references instead of client label parsing.

web/src/components/cnpg/CNPGOverview.tsx

useCNPGSidebarWorkspace.tsHide unsupported workspace destinations +18/-11

Hide unsupported workspace destinations

• Checks feature support and marks incomplete fleet counts as lower bounds.

web/src/components/cnpg/useCNPGSidebarWorkspace.ts

WorkloadView.tsxFall back to standard workload views +21/-6

Fall back to standard workload views

• Avoids CNPG redirects and composed summaries when unsupported, and uses Pod logs instead of workspace logs.

web/src/components/workload/WorkloadView.tsx

useGitOpsWriteGuard.tsGate GitOps write-evidence requests +13/-10

Gate GitOps write-evidence requests

• Checks the write-evidence feature before querying an older Radar.

web/src/hooks/useGitOpsWriteGuard.ts

Refactor (92) +1745 / -1849
cnpg_history.goRemove CNPG-owned series isolation +12/-173

Remove CNPG-owned series isolation

• Uses extracted Prometheus series-scope types and helpers instead of defining them in CNPG history.

internal/prometheus/cnpg_history.go

pvc_usage.goUse shared series isolation for PVC charts +6/-6

Use shared series isolation for PVC charts

• Switches PVC usage attribution to the integration-neutral Prometheus helper.

internal/prometheus/pvc_usage.go

series_scope.goExtract Prometheus series-scope contracts +181/-0

Extract Prometheus series-scope contracts

• Houses cluster-identity isolation, ambiguity and mismatch errors, and claim selectors for multiple chart consumers.

internal/prometheus/series_scope.go

cache_scope.goExtract informer cache-scope intersection +58/-0

Extract informer cache-scope intersection

• Moves cache namespace checks into a helper shared by Capacity and CNPG.

internal/server/cache_scope.go

capacity.goUse shared cache-scope helper +2/-2

Use shared cache-scope helper

• Updates Capacity call sites after the cache-scope extraction.

internal/server/capacity.go

capacity_auth.goRemove embedded cache-scope implementation +0/-50

Remove embedded cache-scope implementation

• Leaves Capacity authorization behavior in place while relocating reusable informer-scope logic.

internal/server/capacity_auth.go

capacity_groups.goAdopt extracted namespace intersection +2/-2

Adopt extracted namespace intersection

• Uses the shared cache-scope naming in Capacity grouping.

internal/server/capacity_groups.go

cnpg_actions.goAdopt shared action and grant contracts +127/-453

Adopt shared action and grant contracts

• Replaces CNPG-specific request, capability, refusal, and permission machinery while retaining CNPG guards and action-specific codes.

internal/server/cnpg_actions.go

cnpg_actions_maintenance.goUse shared maintenance-action contracts +6/-6

Use shared maintenance-action contracts

• Moves maintenance action verdicts and grants to shared types.

internal/server/cnpg_actions_maintenance.go

cnpg_destroy.goUse shared destroy-action refusals +36/-34

Use shared destroy-action refusals

• Adopts common action errors and structured grants for instance destruction.

internal/server/cnpg_destroy.go

cnpg_history.goUse common history access contracts +46/-60

Use common history access contracts

• Replaces CNPG-local grant and response helpers with shared access and series-scope contracts.

internal/server/cnpg_history.go

cnpg_operator.goShare operator kind-access decisions +22/-22

Share operator kind-access decisions

• Uses shared per-kind coverage and structured access grants for operator reads.

internal/server/cnpg_operator.go

cnpg_operator_diagnosis.goUse common operator read sources +22/-32

Use common operator read sources

• Replaces CNPG-local access wording with shared read-source and grant representations.

internal/server/cnpg_operator_diagnosis.go

cnpg_operator_status.goAdopt shared operator coverage types +8/-8

Adopt shared operator coverage types

• Uses common kind-access and coverage states for operator status.

internal/server/cnpg_operator_status.go

cnpg_pooler_actions.goShare Pooler action verdicts +20/-19

Share Pooler action verdicts

• Uses the common action request, permission, and refusal contract for Pooler writes.

internal/server/cnpg_pooler_actions.go

cnpg_runtime.goUse common runtime grant type +4/-4

Use common runtime grant type

• Replaces CNPG-specific runtime permission descriptions with structured grants.

internal/server/cnpg_runtime.go

cnpg_sessions.goUse shared session access decisions +17/-17

Use shared session access decisions

• Applies common grants and permission helpers to session reads.

internal/server/cnpg_sessions.go

cnpg_storage.goShare storage read and fan-out contracts +52/-69

Share storage read and fan-out contracts

• Uses common read sources, structured grants, and bounded namespace fan-out.

internal/server/cnpg_storage.go

fanout.goExtract bounded namespace fan-out +32/-0

Extract bounded namespace fan-out

• Provides a reusable concurrency-limited helper for namespace reads.

internal/server/fanout.go

CNPGBackupSummary.tsxUse shared backup-summary primitives +8/-6

Use shared backup-summary primitives

• Renders backup facts and sections through workspace UI components.

packages/k8s-ui/src/components/cnpg/CNPGBackupSummary.tsx

CNPGClusterSummary.tsxCompose cluster summary with shared components +17/-27

Compose cluster summary with shared components

• Replaces CNPG-local facts, sections, and problem presentation with shared primitives.

packages/k8s-ui/src/components/cnpg/CNPGClusterSummary.tsx

CNPGConnectSection.tsxUse shared connection-section UI +4/-5

Use shared connection-section UI

• Adopts extracted workspace controls and secondary-button styling.

packages/k8s-ui/src/components/cnpg/CNPGConnectSection.tsx

CNPGDeclarativeSummary.tsxUse shared declaration-summary primitives +24/-26

Use shared declaration-summary primitives

• Replaces CNPG-specific fact and section elements with workspace components.

packages/k8s-ui/src/components/cnpg/CNPGDeclarativeSummary.tsx

CNPGImageCatalogSummary.tsxShare image-catalog summary layout +6/-4

Share image-catalog summary layout

• Switches image-catalog facts and sections to extracted components.

packages/k8s-ui/src/components/cnpg/CNPGImageCatalogSummary.tsx

CNPGLogicalPath.tsxShare logical-path presentation +7/-5

Share logical-path presentation

• Uses workspace facts and reusable reference links in logical replication paths.

packages/k8s-ui/src/components/cnpg/CNPGLogicalPath.tsx

CNPGObjectStoreSummary.tsxShare ObjectStore summary layout +8/-6

Share ObjectStore summary layout

• Renders ObjectStore values with the extracted fact and section components.

packages/k8s-ui/src/components/cnpg/CNPGObjectStoreSummary.tsx

CNPGPoolerSummary.tsxShare Pooler summary layout +9/-7

Share Pooler summary layout

• Adopts reusable workspace facts, sections, and reference links.

packages/k8s-ui/src/components/cnpg/CNPGPoolerSummary.tsx

CNPGSharedSummary.tsxBind shared problem UI to CNPG +8/-5

Bind shared problem UI to CNPG

• Keeps CNPG-specific summary composition while passing Cluster as the problem root kind.

packages/k8s-ui/src/components/cnpg/CNPGSharedSummary.tsx

logicalReplication.tsAdopt shared logical-replication types +4/-4

Adopt shared logical-replication types

• Uses extracted fact and reference types without changing CNPG-specific interpretation.

packages/k8s-ui/src/components/cnpg/logicalReplication.ts

pooler.tsUse shared Pooler fact model +3/-2

Use shared Pooler fact model

• Returns integration-neutral Fact values from CNPG Pooler builders.

packages/k8s-ui/src/components/cnpg/pooler.ts

primitives.tsxRemove CNPG-only primitive implementations +1/-257

Remove CNPG-only primitive implementations

• Moves generic facts, sections, and problems to components/workspace; CNPG retains only its bindings.

packages/k8s-ui/src/components/cnpg/primitives.tsx

index.tsExpose shared issue title helper +1/-0

Expose shared issue title helper

• Exports reason-title formatting for other consumers.

packages/k8s-ui/src/components/issues/index.ts

severity.tsCentralize issue reason titles +6/-1

Centralize issue reason titles

• Makes the Issues page and workspace use the same title for a reason.

packages/k8s-ui/src/components/issues/severity.ts

RefLink.tsxExtract generic resource reference links +20/-0

Extract generic resource reference links

• Moves reference navigation to ui using the existing ResourceRef contract.

packages/k8s-ui/src/components/ui/RefLink.tsx

index.tsExport generic UI helpers +3/-1

Export generic UI helpers

• Exposes reference links and shared status-tone helpers.

packages/k8s-ui/src/components/ui/index.ts

status-tone.tsxCentralize status-tone composition +25/-0

Centralize status-tone composition

• Adds reusable tone text and severity-comparison helpers beside existing fill styles.

packages/k8s-ui/src/components/ui/status-tone.tsx

certainty.tsxShare certainty glyphs +36/-0

Share certainty glyphs

• Moves exact, estimated, and lower-bound presentation out of Capacity.

packages/k8s-ui/src/components/workspace/certainty.tsx

facts.tsxExtract source-aware fact components +60/-0

Extract source-aware fact components

• Introduces shared Fact, grid, row, value, and provenance rendering.

packages/k8s-ui/src/components/workspace/facts.tsx

index.tsExport workspace UI contracts +7/-0

Export workspace UI contracts

• Provides one import surface for facts, sections, problems, certainty, and manager text.

packages/k8s-ui/src/components/workspace/index.ts

problems.tsxExtract category-parameterized problem UI +175/-0

Extract category-parameterized problem UI

• Defines WorkspaceProblem and reusable callout, list, provenance, and issue-link components.

packages/k8s-ui/src/components/workspace/problems.tsx

sections.tsxExtract workspace section components +63/-0

Extract workspace section components

• Shares headings and foldable section and summary layout.

packages/k8s-ui/src/components/workspace/sections.tsx

index.tsExpose workspace components and helpers +4/-1

Expose workspace components and helpers

• Updates package exports for the extracted UI and grant utilities.

packages/k8s-ui/src/index.ts

capacity.tsPreserve Capacity certainty compatibility +2/-2

Preserve Capacity certainty compatibility

• Keeps CapacityCertainty while basing it on the shared certainty type.

packages/k8s-ui/src/types/capacity.ts

core.tsExtend shared resource reference typing +2/-0

Extend shared resource reference typing

• Aligns core reference types with generic workspace navigation.

packages/k8s-ui/src/types/core.ts

index.tsExport grant utilities +1/-0

Export grant utilities

• Makes structured grant formatting available to package consumers.

packages/k8s-ui/src/utils/index.ts

summary.goUse exported manager detector +1/-1

Use exported manager detector

• Switches resource summaries to topology.ManagedByFromMeta.

pkg/resourcecontext/summary.go

overlay.goUse exported manager detector in overlays +1/-1

Use exported manager detector in overlays

• Keeps subject ownership behavior while adopting the exported topology helper.

pkg/subject/overlay.go

actions.tsExtract client reviewed-action contract +64/-0

Extract client reviewed-action contract

• Defines action requests and capabilities, refusal interpretation, retry locks, and disabled-action wording.

web/src/api/actions.ts

client.tsStabilize feature-guard callbacks +8/-7

Stabilize feature-guard callbacks

• Memoizes useRadarFeature's guard and gated query-key fragment for workspace consumers.

web/src/api/client.ts

CapacityActivity.tsxUse shared Activity screen layout +3/-31

Use shared Activity screen layout

• Replaces Capacity-local layout and controls with workspace components.

web/src/components/capacity/CapacityActivity.tsx

CapacityDemand.tsxUse shared Demand screen layout +4/-36

Use shared Demand screen layout

• Adopts common workspace body, controls, and table presentation.

web/src/components/capacity/CapacityDemand.tsx

CapacityOverview.tsxUse shared Capacity overview layout +5/-43

Use shared Capacity overview layout

• Moves reusable screen and table rendering to workspace components.

web/src/components/capacity/CapacityOverview.tsx

CapacityPoolDetail.tsxUse shared Pool detail presentation +6/-55

Use shared Pool detail presentation

• Replaces Capacity-local sections, controls, and text helpers with workspace UI.

web/src/components/capacity/CapacityPoolDetail.tsx

ClusterSchedulingCard.tsxUse shared certainty presentation +2/-10

Use shared certainty presentation

• Displays scheduling certainty through the extracted glyph.

web/src/components/capacity/ClusterSchedulingCard.tsx

shared.tsxRemove Capacity-owned workspace layout +7/-86

Remove Capacity-owned workspace layout

• Retains Capacity-specific behavior while moving reusable screen controls and presentation to workspace/layout.

web/src/components/capacity/shared.tsx

CNPGBlockingSessions.tsxDisplay structured session grants +8/-7

Display structured session grants

• Uses shared layout and grant rendering for blocking sessions.

web/src/components/cnpg/CNPGBlockingSessions.tsx

CNPGClusterActivity.tsxUse shared activity layout +1/-2

Use shared activity layout

• Imports workspace screen primitives rather than Capacity internals.

web/src/components/cnpg/CNPGClusterActivity.tsx

CNPGClusterRuntime.tsxShare runtime screen components +5/-6

Share runtime screen components

• Uses extracted layout and structured grant rendering.

web/src/components/cnpg/CNPGClusterRuntime.tsx

CNPGDeclarations.tsxShare declarations screen layout +15/-28

Share declarations screen layout

• Replaces Capacity layout imports with workspace controls and tables.

web/src/components/cnpg/CNPGDeclarations.tsx

CNPGDetailPage.tsxShare CNPG detail page navigation +9/-7

Share CNPG detail page navigation

• Uses generic page links, drawer trail, and workspace layout helpers.

web/src/components/cnpg/CNPGDetailPage.tsx

CNPGDrawerTrail.tsxUse generic drawer-trail codec +2/-2

Use generic drawer-trail codec

• Imports shared resource identity and trail utilities.

web/src/components/cnpg/CNPGDrawerTrail.tsx

CNPGOperator.tsxShare operator screen presentation +3/-14

Share operator screen presentation

• Uses extracted workspace layout and access wording.

web/src/components/cnpg/CNPGOperator.tsx

CNPGOperatorDiagnosis.tsxUse shared operator grant display +1/-1

Use shared operator grant display

• Aligns diagnosis presentation with the structured-grant contract.

web/src/components/cnpg/CNPGOperatorDiagnosis.tsx

CNPGPooling.tsxShare pooling screen layout +2/-13

Share pooling screen layout

• Replaces local controls and tables with workspace components.

web/src/components/cnpg/CNPGPooling.tsx

CNPGProtection.tsxShare protection screen layout +2/-15

Share protection screen layout

• Moves protection tables and controls to reusable workspace primitives.

web/src/components/cnpg/CNPGProtection.tsx

CNPGStorage.tsxUse shared storage presentation +8/-7

Use shared storage presentation

• Displays storage read requirements with GrantText and common screen layout.

web/src/components/cnpg/CNPGStorage.tsx

CNPGSummaryHost.tsxUse shared summary navigation and notices +20/-19

Use shared summary navigation and notices

• Uses generic issue links, resource references, problem context, and failed-refresh notices.

web/src/components/cnpg/CNPGSummaryHost.tsx

CNPGTrends.tsxUse shared trends presentation +3/-4

Use shared trends presentation

• Reuses workspace layout and chart-access grant wording.

web/src/components/cnpg/CNPGTrends.tsx

CNPGView.tsxUse generic drawer identity utilities +4/-3

Use generic drawer identity utilities

• Moves trail encoding and resource comparisons out of CNPG routes.

web/src/components/cnpg/CNPGView.tsx

CNPGClusterActions.tsxUse shared cluster-action helpers +8/-19

Use shared cluster-action helpers

• Centralizes disabled reasons and outcome handling while retaining CNPG action choices.

web/src/components/cnpg/actions/CNPGClusterActions.tsx

CNPGConnectButton.tsxShare connect-action reason wording +3/-3

Share connect-action reason wording

• Uses the common capability helper for unavailable connections.

web/src/components/cnpg/actions/CNPGConnectButton.tsx

CNPGDestroyInstanceDialog.tsxUse shared destroy-action refusal handling +4/-3

Use shared destroy-action refusal handling

• Applies common action error and grant interpretation in the confirmation dialog.

web/src/components/cnpg/actions/CNPGDestroyInstanceDialog.tsx

CNPGInstanceActions.tsxUse common instance-action wording +4/-3

Use common instance-action wording

• Renders instance capability reasons through the shared helper.

web/src/components/cnpg/actions/CNPGInstanceActions.tsx

CNPGMaintenanceBanner.tsxUse shared maintenance capability wording +2/-1

Use shared maintenance capability wording

• Aligns maintenance-action availability with the common client contract.

web/src/components/cnpg/actions/CNPGMaintenanceBanner.tsx

CNPGPoolerActions.tsxUse common Pooler action helpers +6/-5

Use common Pooler action helpers

• Adopts shared capability and refusal interpretation.

web/src/components/cnpg/actions/CNPGPoolerActions.tsx

CNPGScheduleActions.tsxShare scheduled-action error handling +6/-11

Share scheduled-action error handling

• Uses common capability reasons and uncertain-outcome handling.

web/src/components/cnpg/actions/CNPGScheduleActions.tsx

actionModel.tsBind CNPG actions to common types +3/-2

Bind CNPG actions to common types

• Uses shared action capability and request definitions.

web/src/components/cnpg/actions/actionModel.ts

baseBackup.tsUse structured backup grants +2/-2

Use structured backup grants

• Formats backup read permissions from Grant objects.

web/src/components/cnpg/baseBackup.ts

logicalSlots.tsFormat logical-slot grants +2/-1

Format logical-slot grants

• Uses shared grant formatting for unavailable slot readings.

web/src/components/cnpg/logicalSlots.ts

CNPGOperationTracker.tsxUse common operation outcome helper +1/-1

Use common operation outcome helper

• Adopts shared action-error interpretation without extracting CNPG's operation tracker.

web/src/components/cnpg/operations/CNPGOperationTracker.tsx

model.tsInterpret operations through shared action errors +2/-1

Interpret operations through shared action errors

• Keeps CNPG operation semantics while reusing common refusal helpers.

web/src/components/cnpg/operations/model.ts

paths.tsRemove CNPG-only generic page links +0/-22

Remove CNPG-only generic page links

• Relocates reusable back-label and issue-link helpers to web utilities.

web/src/components/cnpg/paths.ts

CNPGRestoreButton.tsxUse shared restore capability wording +1/-1

Use shared restore capability wording

• Displays unavailable restore reasons through the common helper.

web/src/components/cnpg/recovery/CNPGRestoreButton.tsx

CNPGRestoreProgress.tsxUse shared recovery layout +2/-2

Use shared recovery layout

• Adopts extracted workspace presentation for restore progress.

web/src/components/cnpg/recovery/CNPGRestoreProgress.tsx

restoreModel.tsUse common restore action contract +8/-7

Use common restore action contract

• Handles restore permissions and refusal states using shared helpers.

web/src/components/cnpg/recovery/restoreModel.ts

routes.tsDerive CNPG detail kinds from workspace table +22/-47

Derive CNPG detail kinds from workspace table

• Removes duplicated kind and group definitions and relocates generic drawer-trail functions.

web/src/components/cnpg/routes.ts

runtimeModel.tsUse structured runtime grants +3/-3

Use structured runtime grants

• Converts runtime read permissions with the shared grant utilities.

web/src/components/cnpg/runtimeModel.ts

useCNPGPoolerLive.tsUse shared Pooler read-source typing +2/-1

Use shared Pooler read-source typing

• Aligns live Pooler access results with structured grants.

web/src/components/cnpg/useCNPGPoolerLive.ts

layout.tsxExtract shared app workspace layout +259/-0

Extract shared app workspace layout

• Provides screen states, notices, controls, tables, text helpers, grant rendering, and stale-data warnings.

web/src/components/workspace/layout.tsx

table.tsShare workspace table styles +8/-0

Share workspace table styles

• Centralizes table class constants previously held by an integration.

web/src/components/workspace/table.ts

drawer-trail.tsExtract resource drawer-trail codec +35/-0

Extract resource drawer-trail codec

• Shares URL encoding, decoding, and resource identity comparison across workspace routes.

web/src/utils/drawer-trail.ts

page-links.tsExtract contextual page links +21/-0

Extract contextual page links

• Shares back-label selection and subject-filtered Issues URL generation.

web/src/utils/page-links.ts

Tests (48) +575 / -190
grant_test.goVerify grant formatting and scope +46/-0

Verify grant formatting and scope

• Tests namespaced, cluster-wide, grouped, and subresource grant wording.

internal/auth/grant_test.go

cnpg_history_test.goRetarget history isolation tests +9/-8

Retarget history isolation tests

• Updates tests to the shared series-scope names.

internal/prometheus/cnpg_history_test.go

capacity_auth_test.goRetarget Capacity cache-scope tests +4/-4

Retarget Capacity cache-scope tests

• Updates tests to the shared cache-scope helper.

internal/server/capacity_auth_test.go

cnpg_actions_maintenance_test.goUpdate maintenance-action assertions +2/-2

Update maintenance-action assertions

• Checks maintenance outcomes against shared action and grant types.

internal/server/cnpg_actions_maintenance_test.go

cnpg_actions_test.goUpdate CNPG action-contract tests +29/-29

Update CNPG action-contract tests

• Adapts action tests to shared refusals, permissions, and structured grants.

internal/server/cnpg_actions_test.go

cnpg_cluster_ha_test.goUpdate HA source assertions +4/-4

Update HA source assertions

• Tests HA responses using the extracted read-source representation.

internal/server/cnpg_cluster_ha_test.go

cnpg_errors_test.goRetarget CNPG refusal tests +3/-3

Retarget CNPG refusal tests

• Updates error assertions for shared action refusal codes.

internal/server/cnpg_errors_test.go

cnpg_history_test.goUpdate history response tests +3/-3

Update history response tests

• Adjusts assertions to shared history and grant representations.

internal/server/cnpg_history_test.go

cnpg_local_cani_test.goRetarget local access-review tests +6/-6

Retarget local access-review tests

• Exercises local permission decisions through shared grant helpers.

internal/server/cnpg_local_cani_test.go

cnpg_operator_status_test.goUpdate operator coverage tests +10/-10

Update operator coverage tests

• Rechecks operator status using shared coverage states.

internal/server/cnpg_operator_status_test.go

cnpg_operator_test.goUpdate operator response assertions +3/-3

Update operator response assertions

• Aligns operator tests with structured grants and shared coverage.

internal/server/cnpg_operator_test.go

cnpg_recovery_test.goUpdate recovery contract tests +6/-6

Update recovery contract tests

• Asserts recovery responses using shared read and grant structures.

internal/server/cnpg_recovery_test.go

cnpg_runtime_test.goUpdate runtime grant assertions +4/-4

Update runtime grant assertions

• Adjusts runtime tests for the structured grant contract.

internal/server/cnpg_runtime_test.go

cnpg_schedule_test.goUpdate schedule-action tests +4/-4

Update schedule-action tests

• Retargets schedule tests to the sha...

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Action refusals bypass standard errors 📘 Rule violation ≡ Correctness
Description
writeActionError writes refusal statuses and JSON directly with w.WriteHeader and
json.NewEncoder instead of calling s.writeError. When a CNPG action returns a coded refusal, its
handler reaches this separate response path rather than the standard error helper.
Code

internal/server/actions.go[R193-195]

+		w.Header().Set("Content-Type", "application/json")
+		w.WriteHeader(ae.Status)
+		if encErr := json.NewEncoder(w).Encode(body); encErr != nil {
Evidence
Rule 3036617 requires touched handlers to use the standard error helper for error responses. The new
shared refusal path writes its own status and JSON, and the CNPG action error handler delegates to
it.

Rule 3036617: Use standard JSON error helper in HTTP handlers
internal/server/actions.go[179-220]
internal/server/cnpg_actions.go[1942-1946]
internal/server/server.go[5107-5113]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Action refusals manually write error responses instead of using the server's standard error helper.
## Fix Focus Areas
- internal/server/actions.go[179-220]
- internal/server/server.go[5107-5113]
## Recommended Fix
Extend the standard error-writing helper to support the action response's structured fields, then delegate refusal responses to it without dropping code, current facts, or completed steps.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. A tone comment repeats the helper name ✓ Resolved
Description
The new documentation comment for worseTone says only that it returns the more severe tone,
restating the function's name and comparison. Its TONE_RANK lookup and return expression already
convey that behavior, so a later change would have to keep an unnecessary second description in
sync.
Code

packages/k8s-ui/src/components/ui/status-tone.tsx[76]

+/** The more severe of two tones. */
Evidence
Rule 3036542 disallows comments that only restate obvious behavior. The added comment repeats what
the adjacent helper's name and rank comparison express.

Rule 3036542: Avoid explanatory comments that restate obvious code behavior
packages/k8s-ui/src/components/ui/status-tone.tsx[74-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new public-helper comment merely restates the helper's name and implementation.
## Fix Focus Areas
- packages/k8s-ui/src/components/ui/status-tone.tsx[76-79]
## Recommended Fix
Remove the comment, or replace it only if there is a non-obvious contract that callers need to know.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can tweak Display settings with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/server/actions.go
Comment thread packages/k8s-ui/src/components/ui/status-tone.tsx Outdated
An uncached read can still name namespaces the caller was denied. Empty
collection text and the coverage notice now list every cause the server
named ("no access in c; Radar does not cache Pods in b") and fall back to
the state only when it names none.
Facts, the certainty glyph and the GitOps manager text are how any surface
shows observed values, single-kind renderers included, so they move from
components/workspace to components/facts. The problem list with its sources
moves to components/problems, and the section heading and folded section,
plain layout, to ui/FoldSection. No behaviour change.
Radar Hub uses "workspace" for the customer's account, and the embedded
app showed the same word as a heading inside the Resources sidebar. The
block above a category's kinds now reads "Views", the upgrade note says
"CloudNativePG views" and "CloudNativePG needs a newer Radar on this
cluster", the error states name the CloudNativePG data, and the README,
GitOps, Helm Compare and CloudNativePG docs describe these areas by their
subject. "Workspace" stays an internal term for an integration with
several kinds and its own screens.
@nadaverell
nadaverell merged commit 6cfb825 into feature/cnpg-actions-runtime Oct 4, 2026
1 check passed
@nadaverell
nadaverell deleted the feature/cnpg-workspace-kit branch October 4, 2026 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant