openova/core
e3mrah dfd48b1626
fix(chart,api,controllers,ui): qa-loop iter-11 Fix #45 — three-cluster closeout (#1265)
Cluster-A (bp-guacamole PVC immutability):
  - New pre-install/pre-upgrade Helm hook (Job + per-release SA/Role/
    RoleBinding + cluster-scoped CR/CRB for PV cleanup) that detects
    when an existing `guacamole-recordings` PVC is bound to a
    storageClass different from `.Values.guacamole.recordings.storageClass`
    and deletes the PVC + bound PV so the chart-side PVC manifest can
    recreate cleanly. Closes the live bp-guacamole HelmRelease wedge on
    omantel iter-11 (`PersistentVolumeClaim ... is invalid: spec:
    Forbidden: spec is immutable after creation`).
  - Operator escape hatch: `.Values.guacamole.recordings.allowMigration:
    false` suppresses the hook for Sovereigns with long-lived recording
    state.
  - Render test extended (15 docs total, plus toggle assertion).
  - bp-guacamole chart 0.1.8 → 0.1.9; bootstrap-kit slot pin bumped
    in both _template and omantel.omani.works overlays.

Cluster-B (Application phase stuck on Provisioning):
  - application-controller now observes the per-region downstream
    HelmRelease.status.conditions[Ready] and rolls up
    Application.status.phase: any region Ready=True → phase=Ready,
    any Ready=False → phase=Degraded, no HR yet → phase=Provisioning.
  - Periodic 30s re-list ticker (Run goroutine) so HR readiness flips
    reach the Application even though the Application Watch doesn't
    fire on sibling HR changes.
  - status.lastReconciledAt populated on every reconcile pass for
    TC-113.
  - application-controller ClusterRole gains
    helm.toolkit.fluxcd.io/helmreleases get/list/watch.
  - 3 new unit tests (HR Ready=True → phase=Ready, HR Ready=False →
    phase=Degraded with verbatim message, no-HR → phase=Provisioning).

Cluster-C (SPA AppDetail + k8s services namespace filter):
  - GET /api/v1/sovereigns/{id}/applications/{name} returns full
    Application detail (identity + spec + status). The SPA AppDetail
    page now falls back to this endpoint when wizard store has no
    descriptor for the requested componentId — the typical chroot
    Sovereign case where Apps are installed via `kubectl apply` /
    catalyst-api install endpoint, NOT via the wizard. Without the
    fallback every chroot-installed Application surfaced "App not
    found / The component qa-wp is not part of this deployment"
    even though the underlying CR was Ready=True. Closes TC-068 /
    TC-072 / TC-074 / TC-076 / TC-077 / TC-079 et al.
  - GET /api/v1/sovereigns/{id}/k8s/{kind} accepts BOTH `?ns=`
    (historic) AND `?namespace=` (kubectl/SPA-canonical). Without
    the alias TC-262 / TC-263 returned every namespace's services
    instead of qa-omantel-only. New test covers all 4 query
    permutations.

Chart bumps:
  - bp-catalyst-platform 1.4.116 → 1.4.117 (+ pin in
    clusters/_template/bootstrap-kit/13-bp-catalyst-platform.yaml).
  - bp-guacamole 0.1.8 → 0.1.9.

Refs: qa-loop iter-11 Fix #45 (Cluster-A + Cluster-B + Cluster-C);
post-merge image SHAs land via the catalyst-api / catalyst-controllers
build workflows + the bp-guacamole / bp-catalyst-platform release
workflows.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 07:26:05 +04:00
..
admin fix(admin,billing): drop unsafe state-write in snippet — spinner stays forever (#1000) (#1001) 2026-05-05 23:36:50 +04:00
cmd feat(epic-4): K+P+X1+G — k8s-ws-proxy + projector + WebSocket logs + Guacamole chart (#1099) (#1164) 2026-05-09 09:27:39 +04:00
console feat(consolidation): Phase 1 — move Catalyst-Zero apps + CI + manifests into public monorepo 2026-04-28 12:08:09 +02:00
controllers fix(chart,api,controllers,ui): qa-loop iter-11 Fix #45 — three-cluster closeout (#1265) 2026-05-10 07:26:05 +04:00
marketplace fix(marketplace,checkout): drop Google sign-in, port Sovereign-style PinInput6 (#1010) (#1011) 2026-05-06 00:08:42 +04:00
marketplace-api feat(consolidation): Phase 1 — move Catalyst-Zero apps + CI + manifests into public monorepo 2026-04-28 12:08:09 +02:00
pkg/dynadot-client fix(pdm/dynadot): remove fictional ResponseHeader wrapper from api3.json adapter (#939) (#948) 2026-05-05 15:11:39 +04:00
pool-domain-manager fix(pdm/dynadot): remove fictional ResponseHeader wrapper from api3.json adapter (#939) (#948) 2026-05-05 15:11:39 +04:00
services feat(catalog): catalog-svc HTTP REST service + chart wiring (slice L1+L2, #1097) (#1148) 2026-05-09 04:04:52 +04:00
README.md feat(consolidation): Phase 1 — move Catalyst-Zero apps + CI + manifests into public monorepo 2026-04-28 12:08:09 +02:00

Catalyst Control Plane (core/)

The user-facing Catalyst control plane modules. Status: Consolidated and deployed on Catalyst-Zero (Contabo k3s) as of Pass 105 (2026-04-28).

Read first: docs/PROVISIONING-PLAN.md, docs/GLOSSARY.md, docs/ARCHITECTURE.md, docs/IMPLEMENTATION-STATUS.md.


What this is

The four modules that constitute the Catalyst control plane's user-facing surface, plus the Go backend they share. Each is its own Containerfile-built workload, deployed on every Catalyst Sovereign (starting with Catalyst-Zero on Contabo, and on every franchised Sovereign provisioned thereafter).

Module Stack Purpose Deployed image
console/ Astro + Svelte Primary user-facing UI. Form / Advanced / IaC editor depths. The Sovereign-provisioning wizard at /sovereign (Phase 3) lives here. ghcr.io/openova-io/openova/console:<sha>
admin/ Astro + Svelte Sovereign-admin operations UI. Includes the canonical voucher / billing / catalog / orders / tenants admin surface that sovereign-admin uses to issue vouchers to franchised tenants. ghcr.io/openova-io/openova/admin:<sha>
marketplace/ Astro + Svelte Public-facing Blueprint card grid (the "App Store"). 5-step Plan → Apps → Addons → Checkout → Review flow. ghcr.io/openova-io/openova/marketplace:<sha>
marketplace-api/ Go Backend API for marketplace and console. Handlers (handlers/), provisioner (provisioner/), store (store/). Phase 4 extends this with full Hetzner provisioning. ghcr.io/openova-io/openova/marketplace-api:<sha>

The Helm chart that deploys all four (plus catalyst-ui, catalyst-api, and the legacy SME backend services) lives at products/catalyst/chart/.


CI / Build

Each module has a corresponding GitHub Actions workflow:

Each workflow watches its module path, builds the Containerfile, pushes to GHCR with a SHA tag, and pins the SHA into the corresponding manifest in products/catalyst/chart/templates/ (so Flux on Catalyst-Zero picks up the new image on the next reconciliation).


Migration history

  • Pass 105 (2026-04-28): console/, admin/, marketplace/ consolidated from openova-private/apps/{console,admin,marketplace}/ into this directory. marketplace-api/ consolidated from openova-private/website/marketplace-api/. Six CI workflows migrated to .github/workflows/ of the public repo. Catalyst-Zero K8s manifests migrated from openova-private/clusters/contabo-mkt/apps/{catalyst,sme/services,marketplace-api}/ into products/catalyst/chart/templates/. Image references updated from ghcr.io/openova-io/openova-private/sme-{admin,console,marketplace} to ghcr.io/openova-io/openova/{admin,console,marketplace}. The 8 legacy SME backend services (auth, billing, catalog, domain, gateway, notification, provisioning, tenant) keep their openova-private/sme-* image refs until their source code migrates in a follow-up phase.

Part of OpenOva