{{- /*
Sovereign HTTPRoute for Catalyst control plane — bp-catalyst-platform
(issue #387, Cilium Gateway API migration).

NOT excluded by .helmignore (unlike templates/ingress.yaml and
templates/ingress-console-tls.yaml, which are contabo-only legacy
demos under ADR-0001 §9.4). This template renders ON SOVEREIGNS
ONLY when ingress.gateway.enabled=true (default) and the per-Sovereign
overlay supplies hostnames.

Two routes:
  - console.<sov>  → catalyst-ui   (port 80 → pod 8080)
  - api.<sov>      → catalyst-api  (port 8080)

Hostnames flow from the bootstrap-kit slot
(clusters/_template/bootstrap-kit/13-bp-catalyst-platform.yaml):
  ingress.hosts.console.host=console.${SOVEREIGN_FQDN}
  ingress.hosts.api.host=api.${SOVEREIGN_FQDN}

Per-Sovereign overlays may override gateway.parentRef to attach to a
different Gateway (e.g. an internal-only Gateway when console exposure
is gated behind a corporate VPN).
*/}}
{{- if and .Values.ingress .Values.ingress.gateway .Values.ingress.gateway.enabled -}}
{{- $consoleHost := (((.Values.ingress.hosts).console).host) }}
{{- $apiHost := (((.Values.ingress.hosts).api).host) }}
{{- if and $consoleHost $apiHost }}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: catalyst-ui
  namespace: {{ .Release.Namespace }}
  labels:
    catalyst.openova.io/blueprint: bp-catalyst-platform
    catalyst.openova.io/component: catalyst-ui
spec:
  parentRefs:
    - name: {{ .Values.ingress.gateway.parentRef.name | default "cilium-gateway" | quote }}
      namespace: {{ .Values.ingress.gateway.parentRef.namespace | default "kube-system" | quote }}
      {{- with .Values.ingress.gateway.parentRef.sectionName }}
      sectionName: {{ . | quote }}
      {{- end }}
  hostnames:
    - {{ $consoleHost | quote }}
  rules:
    # /readyz and /healthz on the console hostname route to catalyst-api,
    # not catalyst-ui. The SPA's catch-all router would otherwise shadow
    # these paths with the React shell (HTTP 200 + index.html), making
    # them useless as health probes for any external monitor that points
    # at console.<sov>/readyz expecting a real Go-handler probe response.
    #
    # The catalyst-ui Pod's own k8s probes still hit the nginx-internal
    # /healthz at port 8080 inside the pod (see ui-deployment.yaml) —
    # this Gateway rule only affects external traffic on the console
    # hostname. Caught live on omantel.biz 2026-05-07: TC-211 surfaced
    # /readyz returning the SPA shell because no Gateway rule routed it
    # to catalyst-api.
    - matches:
        - path:
            type: Exact
            value: "/readyz"
        - path:
            type: Exact
            value: "/healthz"
      backendRefs:
        - name: catalyst-api
          port: 8080
    # /auth/handover on the console hostname routes to catalyst-api
    # (the Go backend), not catalyst-ui (the React shell). The handover
    # JWT lands at GET /auth/handover?token=… which is implemented in
    # catalyst-api. Without this rule the React app sees /auth/handover,
    # has no client-side route for it, and falls through to Keycloak's
    # bare login screen — defeating the Phase-8b seamless auth promise.
    # Caught live on otech46.
    #
    # CRITICAL — Exact match, not PathPrefix. Issue #879 Bug 5:
    # /auth/handover MUST be Exact (NOT PathPrefix /auth/). OIDC PKCE on
    # the Sovereign-side Keycloak (catalyst-ui client) configures
    # redirect_uri = https://console.<sov>/auth/callback, which the
    # React SPA handles client-side. A PathPrefix /auth/ rule routes
    # /auth/callback to catalyst-api too — and catalyst-api only
    # registers /api/v1/auth/callback, so it returns bare "404 page not
    # found". Result post-handover-JWT-cookie-expiry (8h TTL): the
    # operator cannot log into the Sovereign Console at all (Keycloak
    # bounces between login and a 404). Verified live on otech103,
    # 2026-05-05. By using Exact /auth/handover here, every other
    # /auth/* path (including /auth/callback, /auth/silent-renew,
    # /auth/handover-error, any future client-side OIDC routes) falls
    # through to the catalyst-ui default rule below and the React
    # Router resolves them.
    - matches:
        - path:
            type: Exact
            value: "/auth/handover"
      backendRefs:
        - name: catalyst-api
          port: 8080
    - matches:
        - path:
            type: PathPrefix
            value: "/api/"
      backendRefs:
        - name: catalyst-api
          port: 8080
    # Default — catalyst-ui (the React shell)
    - matches:
        - path:
            type: PathPrefix
            value: "/"
      backendRefs:
        - name: catalyst-ui
          port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: catalyst-api
  namespace: {{ .Release.Namespace }}
  labels:
    catalyst.openova.io/blueprint: bp-catalyst-platform
    catalyst.openova.io/component: catalyst-api
spec:
  parentRefs:
    - name: {{ .Values.ingress.gateway.parentRef.name | default "cilium-gateway" | quote }}
      namespace: {{ .Values.ingress.gateway.parentRef.namespace | default "kube-system" | quote }}
      {{- with .Values.ingress.gateway.parentRef.sectionName }}
      sectionName: {{ . | quote }}
      {{- end }}
  hostnames:
    - {{ $apiHost | quote }}
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: "/"
      backendRefs:
        - name: catalyst-api
          port: 8080
{{- end }}
{{- end }}
