Wires the sandbox-controller binary + standalone Helm chart for the Wave 1 slice of the Sandbox product (architecture spec: products/sandbox/docs/architecture.md §7). Companion to the CRD shipped in PR #1615. Controller (core/controllers/sandbox/): - cmd/sandbox-controller/main.go — controller-runtime entry point, env-driven config, leader election on by default. Mirrors core/controllers/organization/cmd/main.go shape. - internal/controller/sandbox_controller.go — Reconciler that Get's the Sandbox CR, renders Wave 1 manifests, and writes them into the per-Org `catalyst-tenant` Gitea repo under `sandbox/<owner-uid>/`. Same idiom organization-controller uses for vcluster manifests (organization_controller.go:188-225). - internal/gitops/manifests.go — text/template renderer for the Wave 1 set: Namespace + ResourceQuota + ServiceAccount + Role + RoleBinding + placeholder Secret + 1 PVC per spec.repos[] + kustomization. Sorted iteration + no time.Now() = deterministic output (byte-equal PutFile short-circuit on steady state). - internal/controller/sandbox_controller_test.go — 5 cases: happy-path + idempotency + 2 drift paths (missing orgRef / missing email) + missing-CR. Cloned from organization_controller_test.go. - Dockerfile — two-stage build, alpine:3.20 runtime, non-root UID 65534. Mirrors organization/Containerfile (same CC1 shared go.mod + pkg layout). Chart (platform/sandbox/chart/): - Chart.yaml / values.yaml — opt-in via .enabled=false default. - templates/{serviceaccount,clusterrole,clusterrolebinding,deployment}.yaml + _helpers.tpl — modelled on products/catalyst/chart/templates/controllers/organization-controller-*.yaml. - ClusterRole grants are least-privilege (sandboxes + sandboxes/status + sandboxes/finalizers + leases + events). No secrets:get yet (deferred to Wave 2 when the long-lived org-scoped token issuance flow lands). - Image tag is required at render time (fail-fast on empty per Inviolable Principle #4a — no :latest). Wave 1 does NOT ship: pty-server / openova-sandbox-mcp Deployments, HTTPRoutes for preview subdomains, long-lived token issuance, per-repo git-clone initContainer. Those land in Wave 2. Hard rules respected: READ-ONLY clusters, no chart 1.4.156 bump, no UI touched, no npm/tsc. Verified locally: - `go build ./sandbox/...` clean (go 1.23.4) - `go test -count=1 ./sandbox/...` ok (5/5 pass) - `go vet ./sandbox/...` clean - `helm lint platform/sandbox/chart` clean - `helm template ... --set enabled=true --set image.tag=abc123 ...` renders 4 resources (SA + ClusterRole + CRB + Deployment). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| admin | ||
| cmd | ||
| console | ||
| controllers | ||
| 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