Six coupled chart + orchestrator fixes that unblock alice marketplace
signup → tenant ready → SaaS integrations → LLM → ledger on a freshly
franchised Sovereign. C5-final got Gate 1 GREEN on otech113 (2026-05-05)
but every downstream gate failed because the SME bundle hardcoded
contabo-only assumptions.
Bumps:
- bp-catalyst-platform 1.4.21 → 1.4.22
- bp-newapi 1.3.0 → 1.4.0
- bootstrap-kit slot 13 + 80 pins updated in lockstep
Issues addressed (single consolidated PR — smaller PRs would race
against alice signup retries):
- #934 (auth SMTP empty → "failed to send email"): sme-secrets.yaml
now reads SMTP_* from `catalyst-system/sovereign-smtp-credentials`
(the same A5-seeded source #883/#905 the chart 1.4.20 catalyst-
openova-kc-credentials Secret already uses) with source-wins
precedence. Both canonical (smtp-host/port/from/user/pass) AND
legacy (host/port/from/user/password) source-Secret key shapes
accepted. Empty source falls back to chart-level defaults so the
contabo path stays clean.
- #940 (provisioning service GITHUB_TOKEN placeholder + hardcoded
upstream github.com): chart values
.Values.smeServices.provisioning.{githubToken,git.{apiURL,owner,
repo,branch}} make every GitHub-API coordinate operator-overridable
with topology-aware defaults (Sovereign ⇒ in-cluster Gitea REST
API + `openova` org; contabo ⇒ api.github.com + `openova-io` org).
Provisioning binary's startup gate validates the GITHUB_TOKEN does
NOT contain placeholder substrings (<placeholder>, PLACEHOLDER,
REPLACE_ME, ...) and crashes the Pod into Pending if it does — the
operator sees the misconfig immediately instead of after alice
signups have failed silently in service logs. GitHub client now
accepts a custom API URL via NewClientWithAPIURL so Gitea's GitHub-
compatible /api/v1 surface drops in without re-implementing the
client.
- #941 (catalog "27 apps COMING SOON"): added `openclaw` and
`stalwart-mail` to migrateAppDeployable's deployable map at
core/services/catalog/handlers/seed.go. Both blueprints (bp-openclaw,
bp-stalwart-{sovereign,tenant}) ship with visibility=listed in the
embedded blueprints.json AND have working SME-tenant overlay
templates in sme_tenant_gitops.go, but the catalog handler silently
filtered them out because they were missing here. Map extracted to
DeployableAppSlugs() exported function so unit tests can assert
membership without invoking a Mongo store.
- #942 (REDPANDA_BROKERS hardcoded to talentmesh): configmap.yaml
selects broker default at render time based on global.sovereignFQDN
— Sovereign ⇒ NATS JetStream Service per ADR-0001 (the only local
bus on Sovereigns); contabo ⇒ legacy Redpanda Service in talentmesh.
Operator MAY override either default via
.Values.smeServices.eventBus.brokers without forking the chart.
The ConfigMap key name stays REDPANDA_BROKERS for back-compat with
existing SME service Go env wiring; new EVENT_BUS_PROTOCOL key
surfaces the protocol hint for services that want to switch wire
format independently.
- #943 (bp-newapi silently skips Deployment): NEW
templates/cnpg-cluster.yaml auto-provisions a CNPG-backed Postgres
Cluster + Helm-`lookup`-persistent DSN Secret when
.Values.cnpg.enabled (DEFAULT true). NEW templates/credentials-
secret.yaml auto-generates SESSION_SECRET + CRYPTO_SECRET (each
64-char randAlphaNum, persistent across reconciles via Helm
`lookup`) when .Values.credentials.autoProvision (DEFAULT true).
deployment.yaml gate now resolves Secret names from the chart-
emitted defaults when the operator hasn't supplied an override.
Capabilities-gated on postgresql.cnpg.io/v1 so a cold install
before bp-cnpg is Ready surfaces as "no Cluster yet" rather than
a hard install error.
- #944 (CRITICAL — cross-cluster pollution): provisioning.yaml
templates GIT_BASE_PATH from
.Values.smeServices.provisioning.gitBasePath with a topology-aware
default `clusters/<sovereignFQDN>/sme-tenants` on Sovereigns. NEW
`core/services/provisioning/gitguard` package validates at startup
AND on every commit code path that the path begins with
`clusters/<self-FQDN>/` — refusing to commit to any other cluster's
tree. Defence in depth so a runtime env mutation (kubectl exec,
ConfigMap update without Pod restart, hostile sidecar) cannot
bypass the check. Pre-#944 every alice tenant overlay landed in
upstream openova/openova `clusters/contabo-mkt/tenants/<id>/`
which contabo Flux would then install on the contabo cluster —
C5-final caught + reverted the alice2 incident at commit
|
||
|---|---|---|
| .. | ||
| admin | ||
| cmd/cert-manager-dynadot-webhook | ||
| console | ||
| marketplace | ||
| marketplace-api | ||
| pkg/dynadot-client | ||
| pool-domain-manager | ||
| services | ||
| README.md | ||
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:
.github/workflows/console-build.yaml.github/workflows/admin-build.yaml.github/workflows/marketplace-build.yaml.github/workflows/marketplace-api-build.yaml.github/workflows/catalyst-build.yaml— coversproducts/catalyst/bootstrap/{ui,api}/(the React SPA + Go bootstrap API)
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 fromopenova-private/apps/{console,admin,marketplace}/into this directory.marketplace-api/consolidated fromopenova-private/website/marketplace-api/. Six CI workflows migrated to.github/workflows/of the public repo. Catalyst-Zero K8s manifests migrated fromopenova-private/clusters/contabo-mkt/apps/{catalyst,sme/services,marketplace-api}/intoproducts/catalyst/chart/templates/. Image references updated fromghcr.io/openova-io/openova-private/sme-{admin,console,marketplace}toghcr.io/openova-io/openova/{admin,console,marketplace}. The 8 legacy SME backend services (auth,billing,catalog,domain,gateway,notification,provisioning,tenant) keep theiropenova-private/sme-*image refs until their source code migrates in a follow-up phase.
Part of OpenOva