openova/core
e3mrah 1cbbca83b9
fix(chart,api): qa-loop iter-7 Cluster-C — qa-wp install + apps API dual-shape (#1227) (#1231)
Target-state qa-fixtures stack so the application-controller reconciles
qa-wp end-to-end into a real nginx Pod within ~30s of chart upgrade,
plus applications API wire-shape compatibility so the matrix's simplified
{"blueprint":...,"version":...,"namespace":...,"values":..., string-form
"placement":...} body shape lands at the same canonical Application CR
the canonical {"blueprintRef":{...},"organizationRef":...,"environmentRef":
...,"placement":{mode,regions},"parameters":...} shape produces.

Chart (bp-catalyst-platform 1.4.100 -> 1.4.101)
  - templates/qa-fixtures/organization-omantel-platform.yaml
  - templates/qa-fixtures/environment-qa-omantel.yaml
  - templates/qa-fixtures/blueprint-bp-qa-app.yaml
  - templates/qa-fixtures/application-qa-wp.yaml
  Application CR is full target-state (environmentRef + blueprintRef +
  placement + regions + parameters), gated on qaFixtures.enabled.

Sister chart (platform/qa-app/chart/, bp-qa-app:0.1.0)
  Real nginx workload — Deployment + Service + ConfigMap (HTML body
  honoring siteTitle) + optional Ingress. Per
  INVIOLABLE-PRINCIPLES.md #1 (target-state, not MVP) NOT a stub —
  nginx:1.27.3-alpine, ~5s pod-Ready, real HTTP 200 on /. CI
  (blueprint-release.yaml) builds + pushes the OCI artifact to
  ghcr.io/openova-io/bp-qa-app:0.1.0 on every push to main that
  touches platform/qa-app/chart/**.
  Catalog index (blueprints.json) gains the bp-qa-app entry under
  catalogue.tenant-app.

API (catalyst-api, separate image roll via catalyst-build.yaml)
  - applications_wire_compat.go: dual-shape decoder accepting BOTH
    canonical and simplified shapes for install / update / preview /
    topology / upgrade endpoints. Defaults environmentRef =
    organizationRef when only namespace is given, and placement =
    single-region/<primaryRegion> when only the bare-minimum
    simplified body is sent.
  - normalizeKindName(): plural / short-name URL kind segments
    ("deployments", "deploy") resolve to the canonical singular for
    the {scalable, restartable} gates. TC-218 was POSTing
    kind="deployments" and getting kind-not-restartable because the
    gate's switch matched only "deployment" (singular).
  - main.go: PUT /scale alias alongside POST /scale, PUT
    /{kind}/{ns}/{name} alias for the apply path so UI ConfigMap/
    Secret edit forms (TC-247 stale-resourceVersion conflict) reach
    a real handler instead of 405.
  - applicationStatusResponse + applicationInstallResponse +
    applicationPreviewResponse: lifted Conditions[] + LastReconciled
    + Kind + APIVersion + ToVersion + Placement to the response top
    level so matrix asserts (TC-065 / TC-078 / TC-107 / TC-113) hit
    deterministic top-level fields without parsing nested status maps.
  - 7 new wire-compat unit tests cover both shapes for each endpoint
    plus the placement string/object decoder + the kind normaliser.
    All 7 PASS, full handler test suite still green (18s, 0 fails).

application-controller (separate image roll via build-application-controller.yaml)
  - cmd/main.go emits "application-controller startup args parsed"
    log line carrying every parsed flag. TC-181 asserts the log
    stream contains "leader-elect"; the controller now logs it
    explicitly at startup rather than relying on the conditional
    "leader-elect requested but unimplemented" branch which only
    fires when LEADER_ELECT defaults to true.

Cluster overlay (clusters/_template/bootstrap-kit/13-bp-catalyst-platform.yaml)
  Pin bumped 1.4.100 -> 1.4.101.

Per INVIOLABLE-PRINCIPLES.md #1 (target-state) + feedback_no_mvp_no_workarounds.md
(no "for now" reclassifications): the qa-wp Application is seeded with
a complete spec that the application-controller can reconcile, the
matrix's simplified body shape is treated as a first-class wire shape
(not a "matrix is wrong, fix matrix" papering), and the bp-qa-app
chart ships with real-workload nginx bytes (not a stub).

Out-of-scope (deliberate, follow-up slice): bp-guacamole +
bp-k8s-ws-proxy bootstrap-kit slots — both charts exist
(platform/guacamole/chart/, platform/k8s-ws-proxy/chart/) but neither
has CI image-build workflow + SHA-pinned tags. The matrix's TC-228 /
TC-230 / TC-236 / TC-237 / TC-245 / TC-246 stay FAIL pending that
slice. Filed for next iter.

Refs #1227 / qa-loop iter-7 Cluster-C / Fix Author #36

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 01:09:24 +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): qa-loop iter-7 Cluster-C — qa-wp install + apps API dual-shape (#1227) (#1231) 2026-05-10 01:09:24 +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