# bp-openclaw values.
#
# Per docs/INVIOLABLE-PRINCIPLES.md #4 (never hardcode), every
# operationally-meaningful value is configurable; cluster overlays in
# clusters/<sovereign>/bootstrap-kit/ may override any of these without
# rebuilding the Blueprint OCI artifact.
#
# Required at install time (overlay MUST set):
#   - keycloak.realmURL          (SME-vcluster Keycloak realm OIDC issuer)
#   - keycloak.clientSecretName  (ExternalSecret with OIDC client_secret)
#   - tenant.namespace           (SME tenant namespace where per-user pods run)
#   - ingress.host               (controller public hostname)
#   - newapi.baseURL             (NewAPI customer-facing hostname)
#   - controller.image.tag       (SHA-pinned tag)
#   - perUserPod.image.tag       (SHA-pinned tag)
#
# Placeholder defaults below let `helm template` smoke-render cleanly in
# CI without --set (mirroring the bp-self-sovereign-cutover pattern).
# Runtime use with the placeholder values is non-functional by design;
# the chart's integration tests + deploy-time validation enforce real
# values on actual installs.

catalystBlueprint:
  upstream:
    chart: ""              # scratch chart — no upstream Helm chart
    version: ""
    repo: ""
    images:
      controller: "ghcr.io/openova-io/openova/openclaw-controller"
      runtime: "ghcr.io/openova-io/openova/openclaw-runtime"

# When `true`, _helpers.tpl :: assertNoPlaceholders fails render with a
# helpful error if any placeholder default is still in place. Per-cluster
# Flux overlays MUST set this to `true` so a bad overlay (forgot to set
# tenant.namespace, etc.) fails install fast instead of installing a
# non-functional release. Default `false` so CI's helm-template smoke
# render passes (the smoke run uses defaults — placeholders are valid
# bytes for render-time syntax checks but non-functional at runtime).
assertNoPlaceholders: false

# ─── Controller (multi-tenant) ───────────────────────────────────────────
controller:
  enabled: true
  replicas: 1
  image:
    # Operator-supplied SHA tag at install time. Placeholder default lets
    # smoke render pass; real installs MUST override (per Inviolable
    # Principle 4 — no floating tags in production).
    repository: ghcr.io/openova-io/openova/openclaw-controller
    tag: "0.1.0-placeholder"      # OVERRIDE on install with SHA-pinned tag
    pullPolicy: IfNotPresent
  port: 8080
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 512Mi
  securityContext:
    runAsNonRoot: true
    runAsUser: 1001
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: ["ALL"]
  probes:
    liveness:
      path: /healthz
      port: 8080
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3
    readiness:
      path: /readyz
      port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3

# ─── Auth: SME-vcluster Keycloak (OIDC) ──────────────────────────────────
# The controller validates inbound end-user JWTs against the SME's own
# Keycloak realm. It NEVER uses the OTECH-ops realm, NEVER trusts a JWT
# from outside the SME vcluster.
keycloak:
  # Required at install time: full realm issuer URL.
  # e.g. "https://keycloak.<sme-domain>/realms/<sme-realm>"
  # Placeholder default lets `helm template` smoke-render pass.
  realmURL: "https://keycloak.example.local/realms/example"
  # OIDC client registered in the SME's Keycloak realm for OpenClaw.
  clientID: "openclaw"
  # ExternalSecret name carrying the OIDC client_secret. Required key:
  # OIDC_CLIENT_SECRET. Provisioned by the SME-tenant onboarding pipeline
  # (epic #795 ticket #804). Placeholder default lets smoke render pass.
  clientSecretName: "openclaw-oidc"

# ─── NewAPI integration ──────────────────────────────────────────────────
# Per-user pods talk to NewAPI via its CUSTOMER-FACING hostname (egress
# through the OTECH ingress with TLS), NEVER the in-cluster admin URL.
# Per ADR-0003 §3.3 the per-user Secret carries `base-url` matching this
# value; we read the value from the Secret at pod-spawn time so this
# field acts as a fallback default for overlays that don't yet set
# `base-url` on the Secret.
newapi:
  # Required at install time. Placeholder default lets smoke render pass.
  baseURL: "https://newapi.example.local"

# ─── Tenant namespace ────────────────────────────────────────────────────
# SME tenant namespace where:
#   - per-user pods are created and deleted
#   - newapi-key-{uuid} Secrets are read by the controller's ServiceAccount
tenant:
  # Required at install time. Placeholder default lets smoke render pass.
  namespace: "sme-example"

# ─── Per-user pod template ───────────────────────────────────────────────
# These values are baked into a ConfigMap; the controller renders the
# pod-spec at session-start time, substituting NEWAPI_KEY (Secret ref)
# and NEWAPI_BASE_URL (env value).
perUserPod:
  image:
    repository: ghcr.io/openova-io/openova/openclaw-runtime
    tag: "0.1.0-placeholder"      # OVERRIDE on install with SHA-pinned tag
    pullPolicy: IfNotPresent
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 1
      memory: 1Gi
  securityContext:
    runAsNonRoot: true
    runAsUser: 1001
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: ["ALL"]
  # Idle-session reaper — controller deletes the per-user pod after
  # this many minutes without inbound traffic. Default 30 minutes.
  idleTimeoutMinutes: 30
  # Optional extra env vars baked into every per-user pod (operator
  # overlay may extend, e.g. for HTTP proxy, telemetry endpoint, etc.).
  extraEnv: []

# ─── Service ─────────────────────────────────────────────────────────────
service:
  type: ClusterIP
  port: 8080
  targetPort: 8080

# ─── ServiceAccount ──────────────────────────────────────────────────────
serviceAccount:
  create: true
  name: ""

# ─── Ingress + cert-manager TLS ──────────────────────────────────────────
# Public hostname for the controller. Per Q-mine-1 of #795:
# `openclaw.<sme-domain-or-subdomain>`. cert-manager auto-issues a
# per-host certificate via the operator's ACME issuer.
ingress:
  enabled: true
  className: "traefik"
  # Required at install time. Placeholder default lets smoke render pass.
  host: "openclaw.example.local"
  tls:
    enabled: true
    issuer: "letsencrypt-prod"    # cert-manager ClusterIssuer
    secretName: "openclaw-tls"
  annotations: {}

# ─── NetworkPolicy ───────────────────────────────────────────────────────
# Default-allow ingress from the platform's gateway namespace (traefik).
# Egress from CONTROLLER:
#   - SME-vcluster Keycloak (OIDC discovery + JWKS)
#   - K8s api-server (pod create/delete; goes to kube-system endpoint)
#   - per-user pod range in tenant namespace (proxy WebSocket/SSE)
#   - DNS
# Egress from PER-USER pod (separate NetworkPolicy applied at pod-spawn
# time by the controller, NOT by this chart's render — see
# README.md §"per-user-pod NetworkPolicy"):
#   - NewAPI Service (cluster-internal hostname or external ingress)
#   - DNS
# This chart's NetworkPolicy template covers the controller pod only;
# per-user pods receive their NetworkPolicy from a controller-rendered
# template at session-start.
networkPolicy:
  enabled: true
  controller:
    ingress:
      fromNamespaceLabels:
        kubernetes.io/metadata.name: traefik
    # Egress targets — operator may extend if SME-vcluster Keycloak
    # reaches the controller via a different namespace label.
    egress:
      keycloakNamespaceLabel: "keycloak"
      keycloakPort: 8443

# ─── ServiceMonitor ──────────────────────────────────────────────────────
# Default false per docs/BLUEPRINT-AUTHORING.md §11.2 (Observability
# toggles must default false). Operator opts in via per-cluster overlay
# once kube-prometheus-stack reconciles.
serviceMonitor:
  enabled: false
  interval: "30s"
  scrapeTimeout: "10s"
  path: "/metrics"
  labels: {}
