openova/core
hatiyildiz 20f5dca902 feat(wizard): #169 — StepDomain three-mode (pool / byo-manual / byo-api)
Closes openova#169.

Wizard UI:
- New StepDomain.tsx with three radio modes (pool / BYO manual NS / BYO
  registrar API). Pool flow unchanged from #163. BYO-manual surfaces the
  three OpenOva nameservers (ns1-3.openova.io) verbatim with copy buttons.
  BYO-api adds a registrar dropdown (Cloudflare, Namecheap, GoDaddy, OVH,
  Dynadot) + token field + Validate button — read-only validation hits
  /api/v1/registrar/{r}/validate before Next is enabled.
- StepOrg trimmed to org-only fields (domain capture moved to StepDomain).
- WizardPage + WizardLayout add the new "Domain" step (now 7 steps total).

Wizard store:
- DomainMode expanded to 'pool' | 'byo-manual' | 'byo-api' with legacy
  'byo' coerced to 'byo-manual' on rehydrate.
- New fields: registrarType (RegistrarType | null), registrarToken,
  registrarTokenValidated.
- partialize() strips registrarToken + registrarTokenValidated from
  localStorage (credential hygiene per docs/INVIOLABLE-PRINCIPLES.md #10).
- setSovereignDomainMode cascades a clean reset of irrelevant fields.

PDM (core/pool-domain-manager):
- New endpoint POST /api/v1/registrar/{registrar}/validate — read-only
  twin of /set-ns. Calls adapter.ValidateToken; never flips NS records.
  Maps registrar errors to canonical HTTP statuses (401/403/429/502).
  Token never enters a logged struct.

catalyst-api (products/catalyst/bootstrap/api):
- New handler/registrar.go — thin proxy that forwards
  /api/v1/registrar/{r}/{validate|set-ns} to PDM's matching endpoint,
  reading the body once and streaming PDM's response status + body
  verbatim so the wizard's error-mapping vocabulary stays consistent.

Tests:
- StepDomain.test.tsx — 18 vitest cases covering all three modes,
  mode-switch field cleanup, validate fetch happy/error paths, token
  invalidation on edit.
- store.test.ts — wizard-store mutations + persist hygiene.
- StepSuccess.test.tsx — fixture updated 'byo' -> 'byo-manual'.
- registrar_test.go (PDM) — 7 new test cases for /validate covering
  happy, invalid-token, domain-not-in-account, unsupported-registrar,
  missing-fields, bad-JSON, response-doesnt-leak-token.

103 vitest cases pass. Go tests pass for both PDM and catalyst-api.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:01:07 +02:00
..
admin feat(admin,billing): per-Sovereign voucher issuance for sovereign-admin 2026-04-28 13:52:19 +02:00
console feat(consolidation): Phase 1 — move Catalyst-Zero apps + CI + manifests into public monorepo 2026-04-28 12:08:09 +02:00
marketplace feat(marketplace): public /redeem?code=... voucher landing flow 2026-04-28 13:56:54 +02:00
marketplace-api feat(consolidation): Phase 1 — move Catalyst-Zero apps + CI + manifests into public monorepo 2026-04-28 12:08:09 +02:00
pool-domain-manager feat(wizard): #169 — StepDomain three-mode (pool / byo-manual / byo-api) 2026-04-29 09:01:07 +02:00
services merge: Group L testing (Playwright e2e smoke tests, Hetzner provisioning test scaffold gated on HETZNER_TEST_TOKEN secret, integration tests for bootstrap installer + Dynadot + voucher) 2026-04-28 14:05:59 +02: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