Commit Graph

1457 Commits

Author SHA1 Message Date
github-actions[bot]
7ea5023ced deploy: update catalyst images to ff864e9 2026-05-05 22:43:05 +00:00
e3mrah
ff864e93e9
chore(contabo): bump catalyst-{ui,api}:074d65c → :4e2192e (PR #1026 DeploymentsList row-click fix) (#1027)
Co-authored-by: Hati Yildiz <hatiyildiz@openova.io>
2026-05-06 02:40:49 +04:00
github-actions[bot]
6177ba0bf8 deploy: update catalyst images to 4e2192e 2026-05-05 22:36:22 +00:00
e3mrah
4e2192ef4a
fix(deployments-list): row click goes to that row's dashboard, not the current one (#1026)
The Sovereign Console at /sovereign/deployments rendered every row's FQDN
as a Link to=`/dashboard` regardless of which row was clicked. On contabo
(mother) this resolved to /sovereign/dashboard (the CURRENT user's
Sovereign), so clicking ANY row in the deployments list always
navigated to the same dashboard — breaking the operator's expectation
that "click row X to see deployment X's pages."

Fix: route each row to /provision/<row-id>/dashboard on the mother view
(Catalyst-Zero), and to /dashboard on the chroot Sovereign view (where
each Sovereign sees only its own deployment, so /dashboard is correct).

Mode resolved via the existing DETECTED_MODE singleton.

Bumps bp-catalyst-platform chart 1.4.40 → 1.4.41.

Co-authored-by: Hati Yildiz <hatiyildiz@openova.io>
2026-05-06 02:34:06 +04:00
e3mrah
2944723583 provision: deploy tenant e2e-wp-test (plan: m, apps: 1) 2026-05-06 02:23:14 +04:00
e3mrah
ddd3f8b474 provision: deploy tenant e2e-wp-test (plan: m, apps: 1) 2026-05-06 02:23:07 +04:00
github-actions[bot]
87696df3ca deploy: update catalyst images to aba77c0 2026-05-05 22:20:30 +00:00
e3mrah
aba77c09a1
chore(bp-catalyst-platform): bump 1.4.39 → 1.4.40 + literal :1b62da7 → :074d65c (#1023 store-fallback) (#1024)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-06 02:18:28 +04:00
e3mrah
074d65c7fd
fix(sovereign-self): re-add store-fallback (PR #992 reverted #984's version, my dup #983 also lost) (#1023)
Live on otech124 right now: /api/v1/sovereign/self returns 503
deployment-id-not-yet-stamped because:
- CATALYST_SELF_DEPLOYMENT_ID env is empty (orchestrator never patches
  it, and #984's cutover-step-09-graduate idea wasn't merged either)
- The handler doesn't fall back to the local store

The deployment record IS imported on Sovereign (verified — POST
/api/v1/internal/deployments/import returns 200, persisted log
confirmed). Once the handler scans the store, /sovereign/self
returns the deploymentId and every chroot-aware UI Link
(/dashboard, /jobs, /apps, /cloud) finally renders correctly.

Without this, every <Link> built via useResolvedDeploymentId on
Sovereign mode produces /provision//<page> with empty id segment,
which the route validator rejects with 'Deployment id in the URL
is malformed' (founder report).

Closes the live regression on otech124.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:18:07 +04:00
e3mrah
478743db17
fix(cutover-step-06): actually surface git push stderr (PR #1021 merged with only chart bump) (#1022)
PR #1021 was supposed to ship this code fix but the chart-version bump
landed first and the actual sed didn't apply (sed quoting mishap). The
debug-error fix never reached main. Re-shipping now as a clean Edit-
based commit. Captures git push stderr into push_err and prints it on
FATAL so the next iteration's failed Job logs include git's actual
rejection (auth / branch protection / hook).

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:12:00 +04:00
github-actions[bot]
710f101efe deploy: update sme service images to c9b8c13 + bump chart to 1.4.40 2026-05-05 22:11:21 +00:00
e3mrah
69980ed48e
chore(bp-self-sovereign-cutover): bump 0.1.20 → 0.1.21 (#1021)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-06 02:10:45 +04:00
e3mrah
c9b8c13406
fix(tenant): JWT-bypass /tenant/internal/* — paid checkouts never provisioned (#1018) (#1019)
Billing's dispatchOrderPlaced enriches the order.placed NATS event by
calling /tenant/internal/tenants/<id>/subdomain over the in-cluster
ClusterIP. routes.go registers that path with the comment "Internal —
unauthenticated service-to-service", but main.go wraps everything
under /tenant/ in JWTAuth except /tenant/check-slug/. So billing got
401, returned "" for the subdomain, published order.placed with
subdomain="", and provisioning rejected every paid checkout with
"invalid subdomain expected=[a-z][a-z0-9-]{2,30}".

Add /tenant/internal/ to the public-paths bypass. Both gateways
already 401 the path externally, and subdomain values are public DNS
names — the documented threat model.

Co-authored-by: hatiyildiz <hatice@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:09:55 +04:00
e3mrah
362a377dc3
chore(bp-catalyst-platform): bump 1.4.38 → 1.4.39 + literal :69f3be2 → :1b62da7 (#1017 LIVE jobs) (#1020)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-06 02:09:54 +04:00
github-actions[bot]
4199935ebe deploy: update catalyst images to 1b62da7 2026-05-05 22:09:26 +00:00
e3mrah
1b62da733f
fix(sovereign-jobs): use /api/v1/sovereign/jobs (LIVE) on Sovereign mode, not imported snapshot (#1017)
Per founder report on otech122, the Sovereign Console /jobs page showed
all 'Pending' status — the imported deployment record's job snapshot
captured at mother's phase1-watching state, frozen forever.

The fix is small: useLiveJobsBackfill on Sovereign mode (DETECTED_MODE
=== 'sovereign') prefers /api/v1/sovereign/jobs which sovereign.go
already exposes — it reads HelmRelease history + recent K8s Jobs from
the local cluster's apiserver via in-cluster config and returns LIVE
status. The /api/v1/deployments/<id>/jobs path stays the default for
contabo monitor surface (mother view of an in-flight provision —
that's where the imported record IS the canonical view).

Also added credentials:'include' so the cookie reaches the endpoint.

Closes the user-reported 'all jobs Pending forever' on Sovereign
Console.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:07:28 +04:00
github-actions[bot]
6f06bbe740 deploy: update catalyst images to 146e4f4 2026-05-05 22:06:19 +00:00
e3mrah
146e4f4021
fix(auth-callback): post-PKCE navigate to /dashboard not /console/dashboard (#1016)
Last leftover from PR #983's URL contract that PR #992 reverts undid.
PR #996 caught the auth_handover.go + router.tsx /console/dashboard
references but missed AuthCallbackPage.tsx:80. The Sovereign-side
PKCE callback after Keycloak login was navigating to a route that
doesn't exist in the consoleLayoutRoute tree.

Found while verifying otech124 mid-Phase-1.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:04:18 +04:00
e3mrah
0156ae19ec provision: deploy tenant test (plan: m, apps: 1) 2026-05-06 02:01:17 +04:00
e3mrah
aa40c884e4 provision: deploy tenant test12-2 (plan: s, apps: 2) 2026-05-06 02:00:18 +04:00
github-actions[bot]
30c37ffc34 deploy: update catalyst images to b8ef07d 2026-05-05 21:30:30 +00:00
e3mrah
b8ef07def4
chore(bp-catalyst-platform): bump 1.4.37 → 1.4.38 + literal :32d4a87 → :69f3be2 (#1014 sidebar redux) (#1015)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-06 01:28:14 +04:00
e3mrah
69f3be2fdf
fix(sovereign-console): re-fix SovereignSidebar /console/X → /X + AppsPage row chroot-aware (#1014)
Two problems surfaced live on otech122 (founder report):

1. SovereignSidebar.tsx still has /console/X paths.
   PR #983 originally fixed this. PR #984 introduced the same fix in a
   different shape. PR #992 (revert of broken redirect chain) reverted
   #984 and accidentally reverted #983's SovereignSidebar fix too —
   both PRs touched the same nav literals. PR #998 re-fixed
   Sidebar.tsx (mother) but missed re-fixing SovereignSidebar.tsx.
   Symptoms: clicking Settings on console.<sov-fqdn> goes to
   /console/settings (route doesn't exist → 'Not found'); other nav
   items fall through to wizard-side /provision//<page> handlers.

2. AppsPage.tsx app card row link is not chroot-aware.
   On the mother monitor surface, the row link to <Link to='/app/$id'>
   escapes /sovereign/provision/<dep-id>/ to /sovereign/app/<id>.
   Fix: same DETECTED_MODE-aware pattern as PR #1000 used for JobsTable
   and FlowPage.

3. SovereignConsoleLayout's settings dropdown navigate also still
   pointed at /console/settings — fixed inline.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:27:52 +04:00
github-actions[bot]
401e297486 deploy: update catalyst images to 4f3cce6 2026-05-05 20:55:41 +00:00
e3mrah
4f3cce668d
chore(bp-catalyst-platform): bump 1.4.36 → 1.4.37 + literal :a1b30cc → :32d4a87 (#1012 wizard validators public) (#1013)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-06 00:53:18 +04:00
e3mrah
32d4a874b3
fix(catalyst-api): make ALL wizard pre-submit validators public (no session) (#1012)
Same architectural reasoning as PR #1008 (subdomains/check). The wizard's
StepCredentials, StepDomain, StepCloud-creds and StepSSH all run BEFORE
the operator authenticates. Gating those endpoints on a session cookie
returned 401 to every anonymous visitor and blocked the only flow that
matters.

Move from rg (session-gated) to r (unauthenticated):
- /api/v1/credentials/validate         (Hetzner token + project id)
- /api/v1/credentials/object-storage/validate (S3 creds)
- /api/v1/sshkey/generate              (read-only ephemeral keypair)
- /api/v1/registrar/{r}/validate       (Dynadot key+secret)

All four are read-only probes — they call the upstream API
(Hetzner/S3/Dynadot) with the operator-supplied credential and return
200/400 based on whether it works. No state change on success. The
upstream API itself is the auth gate (a wrong credential simply gets
rejected at the upstream).

/api/v1/registrar/{r}/set-ns stays in rg (session-gated) — it's
called from CreateDeployment which is itself post-auth.

Closes the wizard 401 the founder hit on Domain (BYO Dynadot) +
Credentials (Hetzner) steps trying otech with omantel.biz.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 00:52:57 +04:00
github-actions[bot]
17043b1800 deploy: update Catalyst marketplace image to cb1b7ab 2026-05-05 20:09:40 +00:00
e3mrah
cb1b7ab5a1
fix(marketplace,checkout): drop Google sign-in, port Sovereign-style PinInput6 (#1010) (#1011)
The marketplace checkout login surface diverged from the canonical
Sovereign wizard sign-in (console.openova.io/sovereign/wizard) on two
fronts. (1) Continue-with-Google was still rendered above an "or use
email" divider — founder wants email + PIN only. (2) The 6-digit PIN
row used 6 separate <input maxlength=1> boxes; paste only worked after
clicking inside a box first because no input was focused when verify
mounted.

Port the canonical PinInput6 (products/catalyst/bootstrap/ui/src/
components/PinInput6.tsx) to Svelte 5 — one hidden <input maxlength=6>
overlaid on 6 decorative boxes, auto-focused on mount AND on
visibilitychange + window focus. Paste-anywhere just works, mobile
SMS one-time-code suggestion still routes to the focused input.

Drop the inline ~80 LOC PIN handlers (codeDigits / codeRefs /
focusBox / setDigitAt / onDigitInput / onDigitKeyDown / onDigitPaste)
in favour of the new component. Remove the Google button, divider,
handleGoogleAuth / handleGoogleCallback, and the google_auth=1
URL-param $effect. Strip getGoogleAuthUrl / googleCallback from
imports. Simplify auth/callback.astro to a passive redirect to
/checkout — the route stays alive in case any old Google-issued
redirect URI fires.

API surface unchanged: /api/auth/magic-link + /api/auth/verify already
work as a PIN flow, only the UI shell changes. api.ts Google exports
are kept (dead code, but no backend coupling churn).

Co-authored-by: hatiyildiz <hatice@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 00:08:42 +04:00
github-actions[bot]
b32c190e7b deploy: update catalyst images to 78fe10a 2026-05-05 20:02:24 +00:00
e3mrah
78fe10aa87
chore(bp-catalyst-platform): bump 1.4.35 → 1.4.36 + literal :8ec8c01 → :a1b30cc (#1008 public subdomains/check) (#1009)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-05 23:59:50 +04:00
e3mrah
a1b30ccc28
fix(catalyst-api): make /api/v1/subdomains/check public (no auth required) (#1008)
* deploy: re-bump chart literal :b45a49f → :8ec8c01 (mistake-rollback fix)

PR #1006 rolled back to :b45a49f because the catalyst-api pod was
ImagePullBackOff for ~30s while pulling :8ec8c01. The image was IN
GHCR; the pull just took time. Pod recovered to Running on :8ec8c01,
THEN my rollback kicked in and reverted to :b45a49f — losing the
wizard credentials fix from PR #1004 that the founder needed.

Re-bump forward. :8ec8c01 contains useSubdomainAvailability's
credentials:'include' fix that closes the wizard 401 → false-502.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(catalyst-api): make /api/v1/subdomains/check public (no session required)

The wizard's Domain step renders BEFORE the operator authenticates —
PIN issue + verify happen AFTER they pick a subdomain. Requiring a
session cookie on /api/v1/subdomains/check forced 401 on every
anonymous visitor and trapped logged-out operators in a 'check
unavailable' state.

Move the route from rg (session-gated) to r (unauthenticated). Same
model as /auth/pin/issue: read-only public-facing endpoint with no
state change. Information disclosure is negligible — 'is this
subdomain taken?' is what DNS itself answers to anyone with a
resolver.

The handler routes to PDM (managed pool) or DNS (BYO); both are
read-only. PDM has its own rate-limiting middleware on the public
ingress, so anonymous spam is bounded by that.

Closes the wizard 401 the founder hit on otech119 Domain step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:59:28 +04:00
github-actions[bot]
5e3df8eeb8 deploy: update catalyst images to b09b752 2026-05-05 19:57:04 +00:00
e3mrah
b09b752817
deploy: re-bump chart literal :b45a49f → :8ec8c01 (mistake-rollback fix) (#1007)
PR #1006 rolled back to :b45a49f because the catalyst-api pod was
ImagePullBackOff for ~30s while pulling :8ec8c01. The image was IN
GHCR; the pull just took time. Pod recovered to Running on :8ec8c01,
THEN my rollback kicked in and reverted to :b45a49f — losing the
wizard credentials fix from PR #1004 that the founder needed.

Re-bump forward. :8ec8c01 contains useSubdomainAvailability's
credentials:'include' fix that closes the wizard 401 → false-502.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:54:58 +04:00
github-actions[bot]
065364f52e deploy: update catalyst images to 2d0a004 2026-05-05 19:54:20 +00:00
e3mrah
2d0a004bce
rollback: chart literal :8ec8c01 → :b45a49f — pod ImagePullBackOff (build in flight) (#1006)
Chart 1.4.35 referenced :8ec8c01 before the catalyst-build for that
SHA finished pushing to GHCR. Flux applied → catalyst-api pod stuck
ImagePullBackOff → wizard breaks ('worked few seconds then failed').

Roll the literal back to :b45a49f (the previous working SHA from
chart 1.4.34). Chart version stays 1.4.35 to avoid re-publishing
churn. The wizard credentials fix in :8ec8c01 will land when the
build catches up — at which point we manually re-bump the literal.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:52:16 +04:00
github-actions[bot]
aaadd78ff6 deploy: update catalyst images to b887f95 2026-05-05 19:52:01 +00:00
e3mrah
b887f95d29
chore(bp-catalyst-platform): bump 1.4.34 → 1.4.35 + literal :b45a49f → :8ec8c01 (#1005)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-05 23:49:58 +04:00
e3mrah
8ec8c01503
fix(wizard): include credentials on subdomain availability check (#1004)
* chore(bp-catalyst-platform): bump 1.4.33 → 1.4.34 + literal :11dd19e → :b45a49f (#1000 cloud chroot + wizard banner)

* fix(wizard): include credentials on subdomain availability check fetch

The Domain step's POST /api/v1/subdomains/check was firing without
`credentials: 'include'`, so the catalyst_session cookie wasn't sent.
catalyst-api's RequireSession middleware returned 401, which the
wizard surfaced as 'Availability check failed (HTTP 401)' —
indistinguishable from a true upstream PDM failure.

Add credentials:'include'. Other session-gated wizard fetches already
have this; this one was missed.

Repro: open /sovereign/wizard signed-in, type a subdomain, see
'Availability check unavailable'. catalyst-api access log shows POST
.../subdomains/check → 401.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:49:37 +04:00
e3mrah
b7a7759bcc provision: deploy tenant bbb (plan: m, apps: 3) 2026-05-05 23:48:46 +04:00
e3mrah
7fdc139202 teardown: delete tenant bakkal 2026-05-05 23:47:54 +04:00
e3mrah
a4f1eefb1f teardown: delete tenant test13 2026-05-05 23:47:35 +04:00
e3mrah
d40d349459 teardown: delete tenant market 2026-05-05 23:47:16 +04:00
e3mrah
39afadc03a teardown: delete tenant test 2026-05-05 23:47:13 +04:00
e3mrah
a311243988 teardown: delete tenant test-2 2026-05-05 23:47:10 +04:00
e3mrah
5725d7369b teardown: delete tenant aaa 2026-05-05 23:47:07 +04:00
e3mrah
e5834d2c9b teardown: delete tenant test12 2026-05-05 23:47:03 +04:00
github-actions[bot]
246e70f8f1 deploy: update catalyst images to 1b85ab9 2026-05-05 19:46:03 +00:00
e3mrah
1b85ab9227
chore(bp-catalyst-platform): bump 1.4.33 → 1.4.34 + literal :11dd19e → :b45a49f (#1000 cloud chroot + wizard banner) (#1003)
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
2026-05-05 23:44:03 +04:00
e3mrah
b45a49ff96
fix: cloud chroot escapes + wizard-inflight banner instead of auto-redirect (#1002)
Two operator-reported bugs:

1. Cloud sub-pages still escaped chroot. PR #998 closed Sidebar/JobsTable/
   FlowPage but missed CloudPage (4 navigate sites), CloudListView (2),
   UserAccessEditPage (2). Apply the same DETECTED_MODE-aware target
   construction so /provision/<id>/cloud paths stay scoped under the
   chroot on the mother monitoring view.

2. WizardPage auto-redirected signed-in operators with an inflight
   deployment to /provision/<id>/dashboard, blocking the legitimate
   case of starting a SECOND provision while the first is still in
   flight (founder: 'maybe I'll provision one more').

   Replace the auto-redirect with an inline banner at the top of the
   wizard pointing at the inflight monitor. The wizard stays
   interactive — operator can step through and Launch a second
   deployment if they want, OR click 'Open monitor →' to resume the
   first one.

Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:43:52 +04:00
github-actions[bot]
7f4b886094 deploy: update catalyst images to 9964cee 2026-05-05 19:39:07 +00:00