* fix(catalyst-api): rip out dangling sovereign_* route registrations + chart 1.4.56
PR #1050 deleted sovereign_more.go (which defined HandleSovereignUsers,
HandleSovereignCatalog, HandleSovereignSettings, HandleSovereignTopology)
but left four route registrations in cmd/api/main.go that still
referenced those handler methods. The catalyst-api build for the merged
revert (run 25439549879) failed with:
cmd/api/main.go:690:39: h.HandleSovereignUsers undefined
cmd/api/main.go:691:41: h.HandleSovereignCatalog undefined
cmd/api/main.go:692:42: h.HandleSovereignSettings undefined
cmd/api/main.go:693:42: h.HandleSovereignTopology undefined
That's why ghcr.io/openova-io/openova/catalyst-api:fdd3354 was never
published — only the UI image rolled. Result: omantel.biz catalyst-api
pod stuck in ImagePullBackOff.
Drop the four route registrations. Same baby, new address — the chroot
Sovereign uses the existing /api/v1/deployments/{depId}/* handlers via
the JWT-resolved deploymentId, not parallel-baby /api/v1/sovereign/*
endpoints.
Also revert two more parallel-baby fragments still on main:
- getHierarchicalInfrastructure mode-aware fetcher → single mother
URL (the chroot resolves deploymentId from the cookie and the
mother-side topology handler serves byte-identical data once
cutover-import has persisted the deployment record on the
Sovereign's local store)
- CatalogAdminPage.fetchApps mode-aware → /catalog/apps everywhere
Bump bp-catalyst-platform chart 1.4.55 → 1.4.56 and the cluster
Kustomization version pin to match.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(sovereignDynamicClient): in-cluster fallback when running ON the Sovereign
The chroot Sovereign Console at console.<sov-fqdn> is the SAME catalyst-api
binary as the mother. When that binary runs ON the Sovereign cluster
(catalyst-system namespace on the Sovereign itself), there is no
posted-back kubeconfig — the catalyst-api IS in the cluster it needs
to talk to, and rest.InClusterConfig() returns the right credentials.
Without this, every endpoint that needs the Sovereign-side dynamic
client returned 503 with "sovereign cluster kubeconfig not yet posted
back" — including ListUserAccess (/users page), CreateUserAccess,
infrastructure CRUD, etc. Caught on omantel.biz 2026-05-06: /users
rendered "list user-access: HTTP 503" because the Sovereign-side
catalyst-api was looking for a kubeconfig that doesn't exist on the
chroot side of the cutover boundary.
Detection: SOVEREIGN_FQDN env (set on every Sovereign-side catalyst-api
deployment by the chart) matches dep.Request.SovereignFQDN. On the
mother, SOVEREIGN_FQDN is unset → unchanged behavior. On the chroot,
SOVEREIGN_FQDN matches the only deployment served (its own) → use
in-cluster.
Same fallback applied to tryDynamicClientLocked (loaderInputFor's
best-effort live-source client) so /infrastructure/topology and the
/cloud graph render with live data on the chroot too.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(user-access): empty list when CRD absent + RBAC for chroot
Two coupled fixes for the /users page on chroot Sovereign Console:
1. catalyst-api-cutover-driver ClusterRole: grant read/write on
useraccesses.access.openova.io. The Sovereign chroot's catalyst-api
uses the in-cluster ServiceAccount (per PR #1052). The list call
was returning 403 from the apiserver because the SA had no rule
covering this CRD.
2. ListUserAccess: return 200 with empty items when the CRD itself
is not installed (apierrors.IsNotFound). The access.openova.io
CRD ships via a separate blueprint that may not yet be installed
on a fresh Sovereign — the page should render its empty state,
not a 500 toast.
Caught live on omantel.biz 2026-05-06 after PR #1052 unblocked the
in-cluster client path: list call surfaced first as 403 (RBAC), then
as 500 "server could not find the requested resource" (CRD absent).
Both now resolve to a 200 + [].
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(chroot): byte-identical /jobs + /cloud — kill fixture fallback, lazy-seed jobs.Store from live cluster, single endpoint
Two parallel-baby paths still made the chroot diverge from the mother
on /cloud and /jobs/{jobId}. Both now ship one path that serves
byte-identical data on both surfaces.
1. CloudPage rendered fictional topology (Frankfurt, Helsinki,
omantel-primary, omantel-secondary, edge-lb, vpc-net-eu, …) when
the topology query errored — because it fell back to
`infrastructureTopologyFixture` from `src/test/fixtures/`. That is
a test-only file leaking into production via the production import
tree, in direct violation of INVIOLABLE-PRINCIPLES #1 (no
placeholder data — empty state when you don't know).
Fix: drop the fixture fallback. On error → null → empty-state
render. The mother shows the same empty state when its loader
returns nothing; byte-identical.
2. JobsTable + JobDetail rendered a flat green-grid because the chroot
was hitting `/api/v1/sovereign/jobs` which returns a minimal shape
(no dependsOn, no parentId, no exec records). Mother's
`/api/v1/deployments/{depId}/jobs` returns the rich shape from a
per-deployment jobs.Store, which on the chroot starts empty (the
mother's exportDeploymentToChild only ships the deployment record,
not the jobs.Store contents).
Fix: ship one URL on both surfaces — `/api/v1/deployments/{id}/jobs`.
Add `chrootSeedJobsStoreIfEmpty` that runs at handler-time when
SOVEREIGN_FQDN matches dep.Request.SovereignFQDN AND the per-
deployment jobs.Store has 0 records: do a one-shot HelmRelease
list via the in-cluster client (helmwatch.ListAndSnapshotHelmReleases
— exported here, mirrors Watcher.SnapshotComponents without
spinning up an informer), pass through snapshotsToSeeds +
Bridge.SeedJobsFromInformerList. Subsequent calls read directly
from the now-populated store and return rich Job records with
dependsOn / parentId / status — exactly like the mother.
useLiveJobsBackfill loses its mode-aware fetcher; the chroot UI
uses the same `/api/v1/deployments/{id}/jobs` URL as the mother.
3. HandleDeploymentImport now also loads the imported record into the
in-memory deployments map immediately, so `/deployments/{id}/*`
handlers don't need a pod restart's restoreFromStore to see the
chroot-imported deployment.
Bump bp-catalyst-platform 1.4.56 → 1.4.57 (chart + Kustomization).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>