openova/core
e3mrah 8edb485caf
fix(billing): wire /api/v1/billing/purchase route (TBD-C15, Closes #1750) (#1924)
The close-audit DoD validator on a Sovereign host
(e.g. console.t32.omani.works) probes POST /api/v1/billing/purchase
+ POST /api/v1/sme/billing/purchase during the marketplace
customer-journey re-walk (Step 15 — "Purchase" button). On t32 both
returned 404 because the route was never registered on catalyst-api
or the billing service — distinct from the prior 502 class which
was a billing-service-Pod-stale / NATS-connection failure (TBD-A1

The canonical purchase wire has always been
POST /api/billing/checkout (marketplace gateway → billing service
Checkout handler — see CheckoutStep.svelte:722 + handlers.go +
routes.go); the validator vocabulary diverged from the in-cluster
naming. Rather than renaming the canonical handler or migrating
every existing caller, this PR registers two thin aliases:

  - billing service (core/services/billing/handlers/routes.go):
    POST /billing/purchase → existing Checkout handler. Same
    promo-code application, same Stripe-session creation, same
    paid_by_credit shortcut. Semantic alias only.

  - catalyst-api (products/catalyst/bootstrap/api/...):
    POST /api/v1/billing/purchase + POST /api/v1/sme/billing/purchase
    → proxy to SME gateway /api/billing/purchase → billing
    service /billing/purchase. Mirrors sme_billing_vouchers.go
    proxy shape — same mintSMEBridgeToken RS256→HS256 bridge,
    same 503 sme-gateway-unreachable graceful-degradation on a
    Sovereign without the SME services tier.

Marketplace UI continues to call /api/billing/checkout unchanged
(no FE migration), so every existing customer-journey GREEN path
remains stable. The new aliases exist primarily so the
operator-side DoD validator on console.<sov-fqdn> stops 404'ing.

Chart bump: 1.4.188 → 1.4.189 + bootstrap-kit pin synced.

Tests: routes_test.go asserts both /billing/purchase and
/billing/checkout resolve (regression guard for accidental
rename / removal). All existing billing + catalyst-api handler
tests pass.

Co-authored-by: hatiyildiz <hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:20:53 +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(gitea-client): use POST /api/v1/orgs not /admin/orgs for org create (TBD-A43, Closes #1906) (#1910) 2026-05-19 07:59:08 +04:00
marketplace test(marketplace): codified customer-journey regression (17 steps) (#1655) 2026-05-18 12:02:39 +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): auto-register NS glue records before set_ns (#1496) 2026-05-15 13:32:49 +04:00
services fix(billing): wire /api/v1/billing/purchase route (TBD-C15, Closes #1750) (#1924) 2026-05-19 11:20:53 +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