# bp-self-sovereign-cutover — default values.
#
# Per docs/INVIOLABLE-PRINCIPLES.md #4 (never hardcode), every operationally
# meaningful value flows in via per-Sovereign Flux HelmRelease values; the
# placeholder defaults below let `helm template` smoke-render cleanly in CI
# without --set. Per-Sovereign overlays
# (clusters/_template/bootstrap-kit/06a-bp-self-sovereign-cutover.yaml)
# supply real values via envsubst on `${SOVEREIGN_FQDN}` exactly the way
# 19-harbor.yaml + 10-gitea.yaml do.
#
# This chart installs DORMANT. Job PodSpecs are emitted as ConfigMaps;
# catalyst-api reads them at cutover trigger time and stamps real batch/v1
# Jobs. NO helm.sh/hook annotations on any Job manifests in this chart.

global:
  # When set, post-pivot step ConfigMaps render image references through
  # this prefix (so catalyst-api stamps Jobs that pull from the local
  # Harbor proxy-cache). Pre-pivot steps (gitea-mirror, harbor-projects,
  # harbor-prewarm, registry-pivot) MUST use upstream-public images
  # because they run BEFORE the local Harbor proxy-cache + containerd
  # registries.yaml v2 are in place. Default empty = upstream-public for
  # all steps (safe default for smoke render).
  imageRegistry: ""

# Sovereign coordinates. The HelmRelease in
# clusters/_template/bootstrap-kit/06a-bp-self-sovereign-cutover.yaml
# substitutes ${SOVEREIGN_FQDN} from cluster overlays.
sovereign:
  # REQUIRED at install time — overlay supplies a real FQDN. The
  # placeholder below lets `helm template` smoke-render in CI; runtime
  # use with the placeholder is non-functional by design.
  fqdn: "example.local"
  # Local Harbor URL (in-cluster Service form). Used by step 02
  # (harbor-projects) and step 03 (harbor-prewarm). The PUBLIC
  # `registry.<sovereign.fqdn>` URL is what registries.yaml v2 + step 06
  # (helmrepository-patches) rewrite to (since containerd + Flux
  # source-controller resolve through public DNS, not in-cluster
  # CoreDNS). NB: the HTTPRoute hostname is `registry.<sov>`, NOT
  # `harbor.<sov>` — see `clusters/_template/bootstrap-kit/19-harbor.yaml`
  # `gateway.host`. Pre-2026-05-18 this said `harbor.<sov>` which no
  # HTTPRoute matched → bp-sandbox stuck forever (t20 debug matrix).
  # Service name on bp-harbor is `harbor-core` (NOT `harbor-harbor-core`)
  # — caught live on otech103 2026-05-04. Verified via
  # `kubectl get svc -n harbor` returns harbor-core ClusterIP.
  harborInternalURL: "http://harbor-core.harbor.svc.cluster.local"
  # ↓ overlay required for real cutover (uses ${SOVEREIGN_FQDN}).
  #    MUST be `registry.<sov-fqdn>` to match the bp-harbor HTTPRoute.
  harborPublicURL: "https://registry.example.local"
  giteaInternalURL: "http://gitea-http.gitea.svc.cluster.local:3000"
  # ↓ overlay supplies https://gitea.${SOVEREIGN_FQDN} (informational; jobs use internal URL).
  giteaPublicURL: "https://gitea.example.local"

# Upstream openova-io read-only public clone — the source for cutover
# step 01. Step-1 calls Gitea's /repos/migrate API with mirror=true so
# Gitea itself owns the recurring upstream sync going forward; the local
# repo polls upstream on .Values.upstream.mirrorInterval. Overrideable
# so a Sovereign that ships from a fork can rebase the seed.
upstream:
  repoURL: "https://github.com/openova-io/openova"
  branch: "main"
  # Gitea pull-mirror poll interval. Format = Go duration string parsed
  # by Gitea (e.g. "10m0s", "1h0m0s"). Set to 10m by default — short
  # enough that a chart bump → upstream merge → Sovereign reconcile
  # cycle stays under 15 minutes end-to-end, long enough that GitHub
  # anonymous-clone rate limits aren't a concern even with hundreds of
  # Sovereigns. Caught the "drifts forever after cutover" bug live on
  # otech103 2026-05-04 — chart 0.1.14 closes that loop. (#870)
  mirrorInterval: "10m0s"
  # Mothership Harbor — the soft-tethered cold-start registry. Step 08
  # egress-block test asserts the cluster can survive without this URL.
  mothershipHarborURL: "https://harbor.openova.io"

# Local Gitea target — the org + repo created by step 01 (gitea-mirror).
gitea:
  org: "openova"
  repo: "openova"
  # Shape of the admin secret created by bp-gitea's templates.
  # Keys: username, password, token (optional). Job uses BasicAuth
  # username:password against /api/v1 + git push.
  adminSecretRef:
    name: "gitea-admin-secret"
    namespace: "gitea"
    usernameKey: "username"
    passwordKey: "password"

# Local Harbor target — admin credentials + proxy_cache projects to create.
harbor:
  # Shape of the admin secret materialised by bp-harbor's templates
  # (Catalyst-curated `harbor-admin` Secret with key HARBOR_ADMIN_PASSWORD).
  #
  # The bp-harbor umbrella chart (templates/admin-secret.yaml) emits
  # this Secret in the `harbor` namespace AND annotates it with
  # Reflector mirror annotations (allowed-namespaces=catalyst), so the
  # SAME Secret name auto-materialises in this Job's `catalyst`
  # namespace without any cross-namespace secretKeyRef gymnastics.
  # Caught live on otech113 2026-05-05 — Step 02 was failing with
  # `secret "harbor-core" not found` because the upstream `harbor-core`
  # Secret only exists in the `harbor` namespace and K8s forbids
  # cross-namespace secretKeyRef. (issue #935)
  #
  # HARBOR_ADMIN_USERNAME is intentionally NOT carried by the Secret —
  # the upstream Harbor chart hardcodes it to "admin", and Step 02's
  # PodSpec already defaults via `: "${HARBOR_USERNAME:=admin}"` with
  # `optional: true` on the secretKeyRef.
  adminSecretRef:
    name: "harbor-admin"
    namespace: "harbor"
    usernameKey: "HARBOR_ADMIN_USERNAME"
    passwordKey: "HARBOR_ADMIN_PASSWORD"
  # GHCR upstream credential (operator-issued, written by cloud-init at
  # /var/lib/catalyst/ghcr-pull-secret.yaml). Used as the credential the
  # proxy-ghcr registry attaches when pulling from ghcr.io.
  ghcrSecretRef:
    name: "ghcr-pull"
    namespace: "flux-system"
    # Secrets of dockerconfigjson type carry their value under
    # `.dockerconfigjson`; step 02 parses it for username/password.
    dockerConfigKey: ".dockerconfigjson"
  # Seven proxy-cache projects + their upstream registry endpoints.
  # Names are stable because step 06 (helmrepository-patches) +
  # registries.yaml v2 (registry-pivot) rewrite paths against these
  # literal project names.
  proxyProjects:
    - name: "proxy-ghcr"
      upstreamURL: "https://ghcr.io"
      # Harbor adapter "github-ghcr" (the canonical GHCR proxy-cache
      # adapter), with `docker-registry` fallback for older Harbor
      # versions. Caught live on otech103 2026-05-04 (was "github" →
      # "adapter factory for github not found"). Per Harbor 2.x docs.
      registryType: "github-ghcr"
      authMode: "credential"      # uses harbor.ghcrSecretRef
    - name: "proxy-docker"
      upstreamURL: "https://registry-1.docker.io"
      registryType: "docker-hub"
      authMode: "anonymous"
    - name: "proxy-k8s"
      upstreamURL: "https://registry.k8s.io"
      registryType: "docker-registry"
      authMode: "anonymous"
    - name: "proxy-gcr"
      upstreamURL: "https://gcr.io"
      registryType: "docker-registry"
      authMode: "anonymous"
    - name: "proxy-quay"
      upstreamURL: "https://quay.io"
      # docker-registry adapter — Harbor's "quay" type is internal/legacy
      # and rejects project metadata.proxy_cache=true with HTTP 400
      # "unsupported registry type quay". Quay speaks plain v2 so the
      # generic docker-registry adapter is the right shape. Caught live
      # on otech103 2026-05-04.
      registryType: "docker-registry"
      authMode: "anonymous"
    - name: "proxy-xpkg"
      upstreamURL: "https://xpkg.upbound.io"
      registryType: "docker-registry"
      authMode: "anonymous"
    - name: "proxy-ecr"
      upstreamURL: "https://public.ecr.aws"
      registryType: "docker-registry"
      authMode: "anonymous"

# Pre-warm list — images to HEAD-pull through Harbor proxy-cache before
# the cluster reconciles against local Harbor, so first-reconcile pulls
# hit a warm cache. The list is intentionally narrow (the heaviest
# charts). Operators can extend via overlay; an empty list is also valid.
prewarm:
  images:
    - "proxy-docker/library/redis:7"
    - "proxy-docker/library/postgres:16"
    - "proxy-quay/cilium/cilium:v1.16.5"
    - "proxy-quay/jetstack/cert-manager-controller:v1.16.1"
    - "proxy-quay/kyverno/kyverno:v1.13.4"
    - "proxy-docker/grafana/loki:3.3.2"
    - "proxy-docker/grafana/grafana:11.4.0"
    - "proxy-docker/grafana/alloy:v1.5.1"
    - "proxy-docker/falcosecurity/falco:0.39.2"
    - "proxy-ghcr/fluxcd/source-controller:v1.4.1"
    - "proxy-ghcr/fluxcd/helm-controller:v1.1.0"

# GitOps source — Flux GitRepository in flux-system namespace that step
# 05 (flux-gitrepository-patch) patches to point at local Gitea.
gitopsRepository:
  name: "openova"
  namespace: "flux-system"

# HelmRepository patch list — step 06 (helmrepository-patches) iterates
# this list and replaces oci://ghcr.io/openova-io →
# oci://harbor.<sov-fqdn>/openova-io for every entry. Default is
# materialised by listing the bp-* HelmRepositories the bootstrap-kit
# ships; per-Sovereign overlays may extend the list with operator-added
# Application Blueprints.
helmRepositories:
  namespace: "flux-system"
  upstreamPrefix: "oci://ghcr.io/openova-io"
  # Local prefix is computed at runtime from sovereign.harborPublicURL
  # so we don't double-encode the FQDN here. Step 06 PodSpec carries
  # the pivot script that does the substitution.
  names:
    - "bp-cilium"
    - "bp-gateway-api"
    - "bp-cert-manager"
    - "bp-flux"
    - "bp-crossplane"
    - "bp-sealed-secrets"
    - "bp-reflector"
    - "bp-nats-jetstream"
    - "bp-openbao"
    - "bp-keycloak"
    - "bp-gitea"
    - "bp-powerdns"
    - "bp-external-dns"
    - "bp-catalyst-platform"
    - "bp-crossplane-claims"
    - "bp-external-secrets"
    - "bp-external-secrets-stores"
    - "bp-cnpg"
    - "bp-valkey"
    - "bp-seaweedfs"
    - "bp-harbor"
    - "bp-opentelemetry"
    - "bp-alloy"
    - "bp-loki"
    - "bp-mimir"
    - "bp-tempo"
    - "bp-grafana"
    - "bp-kyverno"
    - "bp-reloader"
    - "bp-vpa"
    - "bp-trivy"
    - "bp-falco"
    - "bp-sigstore"
    - "bp-syft-grype"
    - "bp-velero"
    - "bp-coraza"
    - "bp-cert-manager-powerdns-webhook"
    - "bp-cluster-autoscaler-hcloud"
    # openova-catalog (TBD-C19, 2026-05-18) — the named Flux v1
    # HelmRepository the application-controller renders every
    # per-Application HelmRelease against (catalogSourceRef default).
    # Unlike the bp-* HRs above which are rendered directly from
    # clusters/_template/bootstrap-kit/*.yaml slot files, this HR is
    # rendered by the bp-catalyst-platform Helm chart itself
    # (products/catalyst/chart/templates/openova-catalog-helmrepository
    # .yaml) from `.Values.catalog.helmRepository.url`. Step-06 phase-1
    # patches the live HR; phase-1.6 patches the parent HelmRelease's
    # spec.values override; phase-2 makes the override durable in
    # local Gitea by sed-injecting it into
    # clusters/_template/bootstrap-kit/13-bp-catalyst-platform.yaml.
    # Without this entry step-08 catches `openova-catalog` as the only
    # remaining ghcr.io offender ~1 min after step-06 (the catalyst-
    # platform chart's next reconcile re-renders the HR back to
    # ghcr.io). Caught live on t22.omantel.biz 2026-05-18.
    - "openova-catalog"

# catalyst-api Deployment to patch in step 07 (catalyst-api-env-patch).
# Sovereign-side namespace is `catalyst-system`, NOT `catalyst-platform`
# — caught live on otech103 2026-05-04 (Step-7 'deployment catalyst-api
# not found' in catalyst-platform). Verified `kubectl get deploy -A` →
# catalyst-system/catalyst-api.
catalystAPI:
  deploymentName: "catalyst-api"
  namespace: "catalyst-system"
  # The env var that catalyst-api reads for its GitOps source URL.
  envVar: "CATALYST_GITOPS_REPO_URL"

# Step container images. The first three steps (01..03) + the
# registry-pivot DaemonSet use upstream-public images because they run
# BEFORE registries.yaml v2 takes effect on the node containerd.
# Post-pivot steps (≥ 05) MAY use the local Harbor copy via
# global.imageRegistry — defaulted off so smoke render is clean.
#
# Fix #163 (2026-05-11, MIRROR-EVERYTHING): every default repository
# is now the explicit Harbor proxy-cache path per CLAUDE.md inviolable
# rule. The Sovereign's k3s cloudinit (infra/hetzner/cloudinit-control-
# plane.tftpl line 706) ALWAYS configures containerd with
# /etc/rancher/k3s/registries.yaml routing docker.io → harbor.openova.io
# BEFORE k3s starts, so the pre-cutover Jobs can reach the explicit
# Harbor URL just fine. Post-cutover overlay via global.imageRegistry
# remains the operator override for true air-gap mode.
images:
  kubectl:
    # alpine/k8s is the canonical alpine-based image carrying kubectl +
    # helm + the standard k8s CLI surface (replaced bitnami/kubectl in
    # 2025 after Bitnami's deprecation on Docker Hub).
    repository: "harbor.openova.io/proxy-dockerhub/alpine/k8s"
    tag: "1.31.4"
  git:
    repository: "harbor.openova.io/proxy-dockerhub/alpine/git"
    tag: "v2.45.2"
  curl:
    repository: "harbor.openova.io/proxy-dockerhub/curlimages/curl"
    tag: "8.10.1"
  # registry-pivot writes to /etc/rancher/k3s/registries.yaml on every
  # node. Uses alpine + `chroot /host` invocation pattern (kubectl not
  # required — direct file write via host mount).
  hostExec:
    repository: "harbor.openova.io/proxy-dockerhub/library/alpine"
    tag: "3.20"

# registry-pivot DaemonSet — runs from chart install to converge
# /etc/rancher/k3s/registries.yaml on every node. The DaemonSet starts
# DORMANT (writes the v1 cold-start file) and only flips to v2 when
# catalyst-api updates the cutover-status ConfigMap key
# `registriesYamlActive` to "v2" — see template 04-registry-pivot-daemonset.yaml.
# Operators can disable the always-on DaemonSet shape via overlay; in
# that case catalyst-api stamps the DaemonSet on demand at trigger time.
registryPivot:
  enabled: true

# CiliumNetworkPolicy for step 08 (egress-block-test). Operator
# overrides duration via overlay if 10 min isn't enough.
egressTest:
  durationSeconds: 600
  blockedDomains:
    - "github.com"
    - "ghcr.io"
    - "harbor.openova.io"

# Status sentinel ConfigMap — initial state machine state. catalyst-api
# updates the per-step fields as each Job completes.
status:
  configMapName: "self-sovereign-cutover-status"

# Post-cutover continuous mirror re-sync CronJob (TBD-A37, issue #1899,
# chart 0.1.33).
#
# Step 01 (gitea-mirror) runs EXACTLY ONCE at cutover and produces a
# STANDALONE local repo (PR #1029 — pull-mirror semantics block Step-
# 06's HelmRepository URL rewrite push, so the cutover migrated off
# Gitea's built-in pull-mirror). Without a re-sync mechanism, upstream
# chart bumps that land AFTER cutover never reach the Sovereign.
#
# A45 t31 verifier 2026-05-19 caught the live regression: sandbox-
# controller stuck at image :8017700 (PR #1690, 2026-05-16) even
# though PR #1862 had merged 2 days earlier with the NATS consume-leg
# update — the upstream values.yaml bump never crossed the seam.
#
# This block configures the gitea-mirror-resync CronJob (template
# 11-mirror-resync-cronjob.yaml) which re-runs the same idempotent
# bare-clone + push --mirror --force every 5 min. Pre-cutover fires
# are no-ops (the script detects the local repo is missing and exits
# 0). Post-cutover fires close the upstream → local Gitea loop.
mirrorResync:
  # Cron schedule. */5 = every 5 minutes. Short enough that chart-bump
  # → upstream-merge → Sovereign-reconcile completes in ~10 min end-
  # to-end (5 min for this CronJob to fire + the bp-* HelmRepository's
  # 15m interval — but Flux source-controller picks up new commits on
  # the GitRepository within seconds of the push). Long enough that
  # GitHub anonymous-clone rate limits aren't a concern even with
  # hundreds of Sovereigns (300 req/hr per IP for anonymous clone;
  # one Sovereign clones at 12/hr).
  schedule: "*/5 * * * *"
  # Suspended? Default false (active). Operator overlay may flip true
  # for a sandboxed soak Sovereign that intentionally lags upstream.
  suspended: false
  # Per-Job activeDeadlineSeconds. 900s = 15 min covers slow GitHub
  # days; well under typical 5 min cycle so jobs don't pile up.
  jobTimeoutSeconds: 900

# Gateway readiness gate (issue #1871, chart 0.1.32).
#
# Step-06 (helmrepository-patches) rewrites every HelmRepository URL
# `oci://ghcr.io/openova-io` → `oci://registry.<sov-fqdn>/openova-io`.
# That rewrite MUST NOT fire until the Cilium Gateway in `kube-system`
# is `Programmed=True` (= listener bound to `*.<sov-fqdn>:443` with a
# valid TLS cert). Without the wait, source-controller's very next
# pull hits TLS handshake EOF against `registry.<sov-fqdn>` and the
# whole bootstrap-kit Kustomization deadlocks — see Chart.yaml 0.1.32
# header for the full chicken-and-egg chain (t26 99bb823cb0513f4b
# A55 diagnostic).
#
# The wait is implemented inside the Step-06 Job (Phase -1) rather
# than as a Flux HelmRelease `dependsOn` because dependsOn can only
# reference other HelmReleases — sovereign-tls is a Kustomization, so
# the previous attempt (PR #1875) was an unresolvable cross-kind
# reference and helm-controller logged
# `helmreleases.helm.toolkit.fluxcd.io "sovereign-tls" not found`
# forever (A84 empirical test on t27).
gateway:
  # The single per-Sovereign Gateway lives in `kube-system` — installed
  # by `clusters/_template/sovereign-tls/cilium-gateway.yaml`. Every
  # other bootstrap-kit HTTPRoute (gitea, auth, grafana, harbor, openbao,
  # powerdns, console/catalyst-platform) attaches here; this is the same
  # Gateway whose TLS listener Step-06 implicitly depends on.
  namespace: "kube-system"
  name: "cilium-gateway"
  # 30 min covers the slowest observed cold-start (Hetzner ≈18 min:
  # bootstrap-kit Ks reconcile → sovereign-tls Ks reconcile → cert-
  # manager issues wildcard cert → cilium-agent wires listener) with
  # comfortable headroom. Exceeding the timeout exits the Job with a
  # clear failure (NOT exit-0-and-continue) — better to surface the
  # Gateway block to operators than silently rewrite URLs that won't
  # answer.
  waitTimeoutSeconds: 1800

# Per-step Job-stamp tuning. Each value lands inside the corresponding
# PodSpec ConfigMap; catalyst-api copies it onto the stamped Job.
stepTimeouts:
  giteaMirrorSeconds: 1200
  harborProjectsSeconds: 600
  harborPrewarmSeconds: 1800
  fluxGitRepositoryPatchSeconds: 600
  helmRepositoryPatchesSeconds: 600
  catalystAPIEnvPatchSeconds: 600
  egressBlockTestSeconds: 900   # 600 deny + buffer for assert sweep
  # Step 09 (gitea-token-mint, TBD-C18) — short-lived: a single
  # Gitea API mint + validate + Secret patch + best-effort rollout.
  # 600s leaves generous headroom for the provisioning Deployment
  # rollout (which can take a few minutes on a cold-start cluster).
  giteaTokenMintSeconds: 600

# Step 09 (gitea-token-mint, TBD-C18) — bootstrap the Gitea API token
# that the SME provisioning service uses for tenant repo materialisation.
#
# Root cause this addresses: the catalyst-platform chart's
# `provisioning-github-token.yaml` template mirrors gitea-admin-secret's
# PASSWORD into sme/provisioning-github-token.GITHUB_TOKEN. The
# provisioning service sends `Authorization: token <X>` to Gitea, which
# resolves the credential as an API access token (sha1 lookup) — the
# admin password is NOT a valid access token. Result: 401 "user does
# not exist", tenant materialisation silently fails, customer voucher
# checkout completes but no Organization CR is created.
#
# This step mints a real Gitea API token at cutover time and patches
# the destination Secret. See 09-gitea-token-mint-job.yaml for the full
# protocol.
giteaTokenMint:
  # Name of the Gitea API token created under gitea_admin. Surfaced in
  # the Gitea UI under Settings → Applications so an operator can audit
  # / revoke it. The step is idempotent on this name (DELETE-then-POST)
  # so re-running the cutover (chart upgrade, manual replay) rotates
  # the token cleanly.
  tokenName: "catalyst-platform-bootstrap"
  # Comma-separated Gitea API scope list. `all` is broadest — the SME
  # provisioning service needs to create orgs/repos/branches/commits/
  # webhooks under arbitrary tenant paths the marketplace wizard
  # generates. Narrowing scopes (e.g. `write:repository,write:user`)
  # is tracked as a follow-up and requires aligning every
  # core/services/provisioning/* gitea call with a minimum-privilege
  # mapping. Shipping broad here so the journey-step-16 unblock lands
  # today; narrowing follows in TBD-C18-narrow.
  tokenScopes: "all"
  # Destination Secret coordinates — must match the catalyst-platform
  # chart's smeServices.provisioning.gitToken.* defaults.
  # NB: This Secret is created by the catalyst-platform chart with
  # helm.sh/resource-policy: keep, so it survives chart uninstall and
  # this Step's patch is non-destructive on re-run.
  destSecretNamespace: "sme"
  destSecretName: "provisioning-github-token"
  destSecretKey: "GITHUB_TOKEN"

# Trigger configuration — surface here so operators see it in
# `helm get values`. When trigger.auto=true, the chart's Helm
# post-install hook (templates/10-auto-trigger-job.yaml) POSTs
# /api/v1/sovereign/cutover/start on catalyst-api after the chart's
# ConfigMaps + RBAC land. catalyst-api handles idempotency via the
# durable status ConfigMap, so the hook is safe to fire on every
# install AND every upgrade.
trigger:
  # Default true (founder rule per #933): handover is not "done" until
  # cutover has run; the operator must NOT have to click a CTA on
  # console.<sov-fqdn>/console/dashboard. Set to false in per-Sovereign
  # overlay if a sandboxed test Sovereign should stay tethered.
  auto: true
  # Optional pre-flight delay before the hook POSTs /start. 0 = fire
  # immediately. Useful for soak Sovereigns where the operator wants a
  # short window to inspect the freshly-handed-over dashboard before
  # the cutover starts.
  autoDelaySeconds: 0
  # In-cluster URL the auto-trigger Job hits. Default points at the
  # catalyst-api Service in `catalyst-system` (the post-handover
  # Sovereign-side namespace per .Values.catalystAPI.namespace), which
  # is reachable by the Job's catalyst-runner SA without any cross-
  # namespace egress concerns. Override per-Sovereign if catalyst-api
  # is exposed under a different Service name.
  catalystAPIURL: "http://catalyst-api.catalyst-system.svc.cluster.local:8080"
  # How long the auto-trigger Job will wait for catalyst-api to be
  # reachable before giving up (and exiting 0 so the operator can fire
  # manually). Must finish below the HelmRelease install/upgrade
  # timeout (30m for bp-self-sovereign-cutover post-Fix-#152) AND the
  # activeDeadline below so the Job exits cleanly even when catalyst-
  # api never comes up — 25 minutes leaves a healthy 5m buffer below
  # the 30m HR cap. Bumped from 720s (12m) on Fix #152 (chart 0.1.27)
  # after prov #23 hit the 14m Job deadline before catalyst-api came
  # up — cold-start budget needs ~2× headroom on slow Sovereigns.
  autoWaitForAPISeconds: 1500
  # Overall cap on the auto-trigger Job runtime. activeDeadlineSeconds
  # on the Job spec — anything longer means catalyst-api is sick and
  # the operator should investigate. The Job exiting at this deadline
  # is non-fatal for the chart install (the cutover engine already
  # runs detached inside catalyst-api once /start returns 200).
  # Must stay below the HelmRelease install/upgrade timeout (30m =
  # 1800s post-Fix-#152) so the Job ends and the hook unblocks before
  # Helm gives up. Bumped from 840s (14m) on Fix #152 (chart 0.1.27)
  # after prov #23 wedged at 3 consecutive DeadlineExceeded — 29m
  # leaves a 1m buffer below the 30m HR cap.
  autoTimeoutSeconds: 1740
  # TTL on the completed Job — kept for audit so operators can read
  # the trigger Pod logs if something looks wrong.
  autoJobTTLSeconds: 86400
