⭐ New Features
Custom Resources & Helm tab
A new sidebar entry that surfaces every CustomResourceDefinition installed in the cluster (cert-manager, ArgoCD, Strimzi, External Secrets, KEDA, etc.) along with every Helm release deployed via the chart's helm.sh/release.v1 Secret format.
- CRDs sub-tab — search across kinds, API groups, plural names, and short names; grouped browse by API group; click a CRD to list instances (namespace-scoped or cluster-scoped); click any instance to view its full YAML read-only. Backed by the dynamic client — no compile-time knowledge of CRD types needed. Bookmarkable via
?crd=group/version/plural. - Helm Releases sub-tab — every Helm release with status pill (
deployed/failed/superseded/uninstalled), revision number, "updated X ago". Click a release for a tabbed detail modal (Overview / Manifest / Values / History) showing chart metadata, rendered manifest, merged values, and the full revision history (up to 64 revisions). - Compare values between revisions — side-by-side colored diff (rose for removed lines, emerald for added) selected from the History tab.
- Browser back works correctly — sub-tab and selected CRD live in URL params (
?tab=helm,?crd=...) with popstate handling.
Helm rollback & uninstall (admin)
The Custom Resources tab now supports destructive Helm actions for admins:
- Rollback to any revision — Helm Go SDK handles pre/post hooks, resource ordering, and the new "rollback" revision marker. Confirm dialog before execution.
- Uninstall release — Helm SDK deletes every resource in the latest manifest. Confirm dialog before execution.
keepHistory=truequery param available for preserving revision history. - Both actions audit-logged as
helm.rollbackandhelm.uninstallwith actor, role, resource, detail, and source IP.
🔒 Security
-
Helm release detail endpoint redacts secrets for non-admins. Previously,
/api/helm/releases/{ns}/{name}and/api/helm/releases/{ns}/{name}/revisions/{rev}returned the full decoded release includingconfig(user-supplied values),chart.values, the renderedmanifest(withSecretresources base64-encoded),chart.files,chart.templates, and every subchart's values. For non-admin requesters we now:- Selectively redact string values in
config,chart.values, and everychart.dependencies[].values(subcharts) when the leaf key matches a sensitive substring (password,passwd,secret,token,apiKey,accessKey,privateKey,signingKey,encryptionKey,credential,bearer,dsn). When a leaf is a value-holder (value,raw,data,content,plaintext, etc.) under a sensitive-key ancestor, it's also redacted — so the commonpassword: { value: "..." }structured form is covered. Resource references (keys ending inName,Names,Ref,Refs,Reference,References) are never redacted —imagePullSecretName,tlsSecretRef,tokenNameare passed through. Numbers, booleans, and nulls are never redacted (a viewer learningreplicas: 3orserviceType: ClusterIPis not a leak). - Mask Secret resources in the manifest — parse the multi-doc YAML, find any doc with
kind: Secret, replace every.data/.stringDatavalue withREDACTED-NON-ADMIN. Non-Secret docs pass through unchanged. - Drop
chart.filesandchart.templates— files can ship credentials bundled with the chart; templates are raw source that can contain string literals for a viewer to reason backwards from. - Each redacted fetch records an audit entry as
helm.release.viewwith detail noting which fields were redacted, so admins can see who looked at what.
- Selectively redact string values in
-
Secret values are no longer readable by non-admins via the YAML endpoint. Previously,
/api/yaml/Secret/{ns}/{name}returned the raw resource with.database64-encoded — a viewer could fetch it and decode the values. Non-admin requests now have every.data/.stringDatavalue replaced with a***REDACTED-NON-ADMIN***placeholder. Each redacted fetch is recorded assecret.view. -
apiConfigDataadmin check fixed when auth is disabled. The Secret-reveal endpoint at/api/configs/{ns}/{name}?kind=secretwas unconditionally treating no-auth requesters as admin — ignoringDEFAULT_ROLE. As a result, even when/api/mecorrectly reported the user as viewer (the default), clicking Reveal on the Config page returned cleartext secret values. Now uses the sameisAdminhelper as the rest of the codebase.
🛠 Engineering
-
Backend reorganization — moved every handler/cache/auth/audit/jit/notify file out of the flat
cmd/server/package into per-domain packages underinternal/{api,auth,audit,jit,notify,httpx}/.cmd/server/main.gois now 238 lines of pure wire-up (env parsing → client init → DI of cross-package callbacks → mux → ListenAndServe). Behavior unchanged across all endpoints. Seedocs/REORGANIZATION.mdfor the executed plan. -
Initial test suite — 36 unit tests across 6 packages covering security-critical helpers and pure utilities:
TestIsAdmin_*(5) — role gating across auth-enabled/disabled and viewer/adminTestAuditDedup_*(3) andTestAuditTrimExpired_*(3, including zero-retention guard) — replica consistency, boundary retentionTestJit*andTestHasActiveJIT_*(6) — approval lifecycle, workload scoping, expirationTestConfigAcceptsEvent_*(2) andTestWebhookSign_*(2) — webhook fan-out filtering and HMACTestRedactValues_*,TestIsSensitiveLeafKey,TestRedactManifestSecrets_*,TestRedactReleaseForViewer_*(7 including subchart + value-holder + template cases) — Helm value redaction heuristicsTestServedVersion(5 sub-cases) — CRD storage/served version resolutionTestJSON_*,TestError_*,TestK8sError_*(5) — httpx response helpers including NotFound→404 translationTestSplitReleasePath— Helm dispatcher path parser- All pass via
go test ./...
-
TanStack Query data layer —
@tanstack/react-queryinstalled,QueryClientProviderwired inmain.tsx, and auseApi()drop-in wrapper foruseFetchinweb/src/hooks/useApi.ts. Migration path: rename the import in any view, behavior is identical. Once every view is migrated, the manual SWR cache inuseFetch.tsxcan be deleted. -
CLAUDE.md — project brief at the repo root with the post-reorg architecture map, coding conventions, security paths already handled, version bump policy, release process, and the "run tests after every backend change" rule. Read this first before making changes in future sessions.
🐛 Fixes
- CRD YAML modal now opens correctly — earlier the modal block was trapped inside an early-return branch and never rendered when on the CRD instance list. The modal is now at the top-level of the view.
- CRD browser browser-back — clicking back from a CRD's instance list now returns to the CRD index, not the dashboard's Overview tab. Selected CRD is in the URL so popstate restores the right view.
- Helm README screenshots now render on ArtifactHub. Replaced the raw HTML
<table>block with plain markdown image syntax, which ArtifactHub's renderer doesn't strip.
🛠 Dependencies
- Added
helm.sh/helm/v3for rollback/uninstall via the official Helm SDK. - Added
@tanstack/react-queryfor the data-layer migration. - Bumped
github.com/moby/spdystreamtov0.5.1(advisory). - Bumped
postcssfloor to^8.5.10(advisory); resolves to8.5.14.