# Default values for plugin-br-pix-jd.
# This is a YAML-formatted file.
#
# TWO COMPONENTS. The app publishes an image per entry point —
# plugin-br-pix-jd (cmd/app, ENTRYPOINT /service) and plugin-br-pix-jd-worker
# (cmd/worker, ENTRYPOINT /worker). The older single-image shape, where one image
# carries both binaries and the chart overrides the command to reach /worker, is
# still supported: leave worker.image.repository unset.
#
# The component key is `api` because the plugin's release pipeline writes the
# promoted tag there: gitops_yaml_key_mappings '{"plugin-br-pix-jd.tag": ".api.image.tag"}'.

# -- Overrides the chart name used for resource names
nameOverride: "plugin-br-pix-jd"
# -- Overrides the full name generated by Helm
fullnameOverride: ""
# -- Overrides the release namespace for multi-namespace layouts
namespaceOverride: ""

global:
  # -- Registry prefixed onto every component image (mirrors, air-gapped installs)
  imageRegistry: ""
  # -- Pull secrets applied to every component unless overridden per component
  imagePullSecrets: []
  # -- Labels added to every rendered object
  commonLabels: {}
  # -- Annotations added to every rendered object EXCEPT the HorizontalPodAutoscaler.
  # The HPA is the one exception because lerian-common.hpa accepts no annotations at
  # all; every other object gets them, with a component's own annotations winning on
  # a key collision.
  commonAnnotations: {}
  # -- Environment-wide datastore defaults, read via lerian-common.datastore.value
  # (native api.configmap.<KEY> still wins when set — see the escape-hatch note
  # near api.extraConfigmap below). Postgres host has no field here: it is
  # derived per bundled/external topology by plugin-br-pix-jd.postgresHost, not
  # by this mask.
  # Fields: postgres.{port, user, ssl}, redis.{host}.
  # Example: datastores: { postgres: { user: "plugin_br_pix_jd" }, redis: { host: "redis.example.com:6379" } }
  datastores: {}
  # -- Environment-wide tenant-manager infra, read by lerian-common.multiTenant.env
  multiTenant: {}
  # -- Environment-wide auth defaults, read by lerian-common.auth.env
  # Fields: enabled, host.
  auth: {}
  # -- Environment-wide telemetry defaults, read by lerian-common.otel.env.
  # The block is named `observability` (not `otel`) — that is the contract key
  # lerian-common.globalValue looks up. Fields: enabled, otlpEndpoint,
  # deploymentEnvironment.
  observability: {}
  # -- Environment-wide streaming/broker defaults, read by lerian-common.streaming.env
  streaming: {}

serviceAccount:
  # -- Create a ServiceAccount shared by api and worker
  create: true
  # -- Annotations for the ServiceAccount (e.g. IRSA role ARN)
  annotations: {}
  # -- Use an existing ServiceAccount by name instead of creating one
  name: ""

# -- AWS credential source for the multi-tenant M2M path, which resolves each
# tenant's Midaz / CRM / JD credentials from Secrets Manager at runtime.
#
# TWO MUTUALLY EXCLUSIVE OPTIONS — pick by cluster, never enable both:
#
#   EKS            -> IRSA. Leave rolesAnywhere.enabled=false and put the role ARN
#                     in serviceAccount.annotations["eks.amazonaws.com/role-arn"].
#                     The EKS webhook injects the credentials; nothing else needed.
#   anywhere else  -> IAM Roles Anywhere (below). IRSA does not exist off EKS, so an
#                     aws-signing-helper sidecar trades an X.509 client certificate
#                     for temporary credentials and serves them on a loopback IMDS
#                     endpoint that the AWS SDK inside the app picks up.
#
# Enabling this adds a sidecar to BOTH the api and the worker pods, mounts the
# certificate Secret read-only, and forces the pod fsGroup to 65532 so the sidecar
# can read it. The certificate itself is NOT created by this chart — provision it
# (cert-manager or otherwise) into a Secret with tls.crt / tls.key keys.
aws:
  rolesAnywhere:
    # -- Enable the aws-signing-helper sidecar. Keep false on EKS.
    enabled: false
    # -- Required when enabled; the render fails without them.
    trustAnchorArn: ""
    profileArn: ""
    roleArn: ""
    # -- Region the credentials are minted in.
    region: "us-east-2"
    # -- Credential lifetime in seconds; the helper refreshes before expiry.
    sessionDuration: 3600
    # -- Secret holding tls.crt / tls.key. Defaults to <fullname>-iam-tls.
    certificateSecretName: ""
    sidecar:
      image:
        # NOTE: this is the tag every sibling chart (plugin-fees, fetcher, reporter)
        # uses, kept identical on purpose. Be aware it is BOTH floating and
        # arch-pinned: `latest-amd64` will not schedule on arm64 nodes, and it can
        # change under a running deployment. Pin a digest for production.
        repository: public.ecr.aws/rolesanywhere/credential-helper
        tag: latest-amd64
        pullPolicy: IfNotPresent
      # -- Loopback port the IMDS shim listens on.
      port: 9911
      resources:
        limits:
          cpu: 100m
          memory: 128Mi
        requests:
          cpu: 10m
          memory: 64Mi

podSecurityContext:
  fsGroup: 1000

# -- Container security context. Compatible with the app image as built:
# distroless/static-debian12:nonroot running USER nonroot, and the binary writes
# nothing to disk, so readOnlyRootFilesystem holds.
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  runAsGroup: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop:
      - ALL
  seccompProfile:
    type: RuntimeDefault

api:
  # -- Enable the HTTP api component
  enabled: true
  # -- Replicas when autoscaling is disabled
  replicaCount: 1
  # -- Number of old ReplicaSets retained for rollback
  revisionHistoryLimit: 5
  image:
    # -- Repository for the container image
    repository: ghcr.io/lerianstudio/plugin-br-pix-jd
    # -- Image tag. Empty falls back to .Chart.AppVersion (1.12.0-beta.8). Pin this
    # explicitly in production rather than riding the chart's release train.
    tag: ""
    # -- Image pull policy
    pullPolicy: IfNotPresent
  # -- Pull secrets for this component (falls back to global.imagePullSecrets)
  imagePullSecrets: []
  service:
    # -- Kubernetes service type
    type: ClusterIP
    # -- Service port. 8080 is the port the app listens on (Dockerfile EXPOSE 8080).
    port: 8080
    # -- Container port name the Service targets
    targetPort: http
  ingress:
    # -- Enable or disable ingress
    enabled: false
    # -- Ingress class name
    className: ""
    # -- Additional ingress annotations
    annotations: {}
    # -- Ingress hosts, e.g. [{host: pix.example.com, paths: [{path: /, pathType: Prefix}]}]
    hosts: []
    # -- Ingress TLS configuration
    tls: []
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi
  # -- Liveness probe. /health is auth-exempt and rate-limit-relaxed in the app.
  livenessProbe:
    path: /health
    initialDelaySeconds: 15
    periodSeconds: 20
    timeoutSeconds: 5
    failureThreshold: 3
  # -- Readiness probe. /readyz reports dependency health; in multi-tenant mode it
  # also serves per-tenant sub-paths.
  readinessProbe:
    path: /readyz
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3
  startupProbe:
    # -- Enable a startup probe for slow cold starts (migrations are a separate Job)
    enabled: false
    path: /readyz
    initialDelaySeconds: 10
    periodSeconds: 5
    failureThreshold: 30
  autoscaling:
    # -- Enable horizontal pod autoscaling
    enabled: false
    minReplicas: 2
    maxReplicas: 12
    targetCPUUtilizationPercentage: 70
    targetMemoryUtilizationPercentage: 85
  pdb:
    # -- Enable PodDisruptionBudget
    enabled: true
    minAvailable: 1
    annotations: {}
  deploymentStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  # -- Grace period for shutdown. MUST stay ABOVE STREAMING_CLOSE_TIMEOUT_S
  # (lib-streaming default 30s) or the producer's flush is cut off mid-close and
  # buffered CloudEvents are lost. Raise both together, never just one.
  terminationGracePeriodSeconds: 60
  # -- Node selector for scheduling
  nodeSelector: {}
  # -- Tolerations for tainted nodes
  tolerations: []
  # -- Affinity rules
  affinity: {}
  # -- Productized rate-limit knobs consumed by lerian-common.rateLimit.env.
  # Raw configmap.<KEY> still works and takes precedence over these.
  # WARNING on `allowFailOpen`: it turns the fail-closed limiter into fail-open, and
  # the app HARD-FAILS its boot when it is truthy under ENVIRONMENT_NAME=production
  # (it is one of three vars in productionForbiddenBypassEnvVars). Dev/CI only.
  rateLimit: {}
  # -- CORS. Emitted as ACCESS_CONTROL_* (the names lib-commons actually reads) AND
  # mirrored to CORS_*. Leaving allowedOrigins empty means lib-commons refuses the
  # wildcard and applies a DENY-ALL policy — every browser cross-origin call fails.
  # Set it to your console origins for any browser-facing install.
  # Fields: allowedOrigins, allowedMethods, allowedHeaders, exposeHeaders,
  # allowCredentials.
  cors: {}
  # -- Non-secret environment overrides for the api. EMPTY BY DESIGN.
  #
  # The chart's defaults are literals in templates/_helpers.tpl, not empty
  # placeholders here, for two reasons that both bit the first cut:
  #   1. lerian-common's resolvers test PRESENCE (hasKey). A key declared here,
  #      even as "", counts as set and beat the global.<block> tier — which made
  #      global.observability / global.auth / global.datastores dead on arrival.
  #   2. Reading a default back out of this map swallowed an explicit 0 or false
  #      from the operator and replaced it with the chart default.
  # Anything set here now WINS over both the global tier and the chart default,
  # including an explicit "0", "false" or "".
  #
  # Keys that have a global contract — declare them once at the umbrella level
  # instead of per component:
  #   global.observability -> ENABLE_TELEMETRY, OTEL_EXPORTER_OTLP_ENDPOINT,
  #                           OTEL_RESOURCE_DEPLOYMENT_ENVIRONMENT
  #   global.auth          -> PLUGIN_AUTH_ENABLED, PLUGIN_AUTH_HOST
  #   global.datastores    -> POSTGRES_PORT / POSTGRES_USER / POSTGRES_SSLMODE,
  #                           REDIS_HOST
  #
  # Chart defaults when a key is absent everywhere: LOG_LEVEL=info,
  # SERVER_ADDRESS=:8080, TLS_TERMINATED_UPSTREAM=true, POSTGRES_SSLMODE=disable,
  # POSTGRES_USER/POSTGRES_NAME=plugin-br-pix-jd, MIGRATIONS_PATH=/migrations,
  # SYSTEMPLANE_ENABLED=false, SWAGGER_ENABLED=false, ENVIRONMENT_NAME="",
  # DEPLOYMENT_MODE="".
  # REDIS_HOST has NO default and is required — the rate limiter is fail-closed.
  #
  # DEPLOYMENT_MODE (saas | byoc | local, default "") is validated at render time
  # because the app rejects an unrecognized value at boot. It is INDEPENDENT of
  # ENVIRONMENT_NAME: "saas" arms TLS enforcement over Postgres, Redis and — in
  # multi-tenant — the MT Redis and MT URL, failing the boot when any of them is
  # plaintext. Empty is read by the app as "local" (enforcement off).
  #
  # See README.md for the full table.
  configmap: {}
  # -- Extra environment variables appended to the container (list of name/value)
  extraEnvVars: []
  # -- Escape hatch for non-secret env keys this chart does not model yet. These are
  # merged LAST, so a key here DOES override a modeled key of the same name. Use it
  # to reach a variable the chart has not grown yet, not to fight a modeled default.
  extraConfigmap: {}
  # -- Secret values. Rendered into the component Secret unless existingSecret.name
  # is set. POSTGRES_PASSWORD is absent on purpose when the bundled subchart is
  # enabled: it is read from the subchart's own Secret via secretKeyRef so the
  # credential lives in exactly one place. Set it here only for an external
  # Postgres that has no existingSecret of its own.
  secrets:
    # Required. lib-license-go validates on boot and on every worker tick.
    LICENSE_KEY: ""
    # Optional — a Redis with no auth is a legitimate in-cluster setup.
    REDIS_PASSWORD: ""
  # -- Escape hatch for secret keys this chart does not model yet. Base64-encoded
  # by the template, so supply plaintext values.
  extraSecrets: {}
  existingSecret:
    # -- Read all Secret keys from this pre-existing Secret instead of rendering one
    name: ""

worker:
  # -- Disabled by default: the worker is opt-in, not every install runs jobs.
  #
  # The app publishes a DEDICATED worker image, ghcr.io/lerianstudio/plugin-br-pix-jd-worker,
  # built from cmd/worker/Dockerfile with its own ENTRYPOINT ["/worker"]. Set
  # worker.image.repository to it and the chart stops overriding the command.
  #
  # Leaving worker.image.repository unset keeps the older one-image shape, where the
  # api image carries both binaries and the chart overrides the entrypoint. Both work.
  #
  # TAGS MAY DIVERGE, and the chart does not police it. The release pipeline builds
  # only the component that changed, so an api-only release legitimately leaves the
  # worker a tag behind. An earlier version of this chart failed the render on any
  # mismatch; that gate blocked the pipeline's normal output and was removed.
  #
  # What it was trying to protect — the two processes sharing one database and one
  # schema — is owned by the release pipeline, not by this values file.
  enabled: false
  # -- Replicas. The jobs take cross-replica Postgres advisory locks, so >1 is safe,
  # but there is nothing to gain: each tick is single-flight per job.
  replicaCount: 1
  revisionHistoryLimit: 5
  image:
    # -- Leave repository/tag EMPTY to inherit the api's. Setting either to a
    # different value fails the render: api and worker are two entry points of one
    # build and must never come from different commits.
    repository: ""
    tag: ""
    pullPolicy: IfNotPresent
  imagePullSecrets: []
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi
  pdb:
    # -- Off by default: a single cron process has no availability target to protect.
    enabled: false
    minAvailable: 0
    annotations: {}
  deploymentStrategy:
    # -- Recreate, not RollingUpdate: two overlapping workers would contend on the
    # same advisory locks for no benefit during a rollout.
    type: Recreate
  # -- Above the lib-streaming close timeout, same coupling as the api.
  terminationGracePeriodSeconds: 60
  nodeSelector: {}
  tolerations: []
  affinity: {}
  # -- Non-secret environment for the worker. Only the deltas from the api are
  # listed; everything else is inherited by rendering the same shared keys.
  configmap:
    # Distinct telemetry identity so worker spans are not attributed to the api.
    OTEL_RESOURCE_SERVICE_NAME: "plugin-br-pix-jd-worker"
  extraEnvVars: []
  # -- Escape hatch for non-secret worker env keys not modeled yet (merged last, wins).
  extraConfigmap: {}
  # -- Worker credentials. LICENSE_KEY and REDIS_PASSWORD fall back to the api's values
  # so the two components cannot drift; set them here only to diverge deliberately.
  secrets: {}
  # -- Escape hatch for worker secret keys not modeled yet (plaintext in, base64 out).
  extraSecrets: {}
  existingSecret:
    name: ""

# -- Schema migrations, as a SEGREGATED Job (templates/common/migrations-job.yaml) —
# the repository convention, matching plugin-br-bank-transfer, notifications,
# plugin-access-manager and plugin-br-pix-switch.
#
# The app does NOT migrate on boot: it reads MIGRATIONS_PATH and never calls
# golang-migrate. The Job's hook PHASE switches on where Postgres lives:
#   bundled  -> post-install/post-upgrade (PostSync). The bitnami StatefulSet is
#               provisioned during Sync, so a pre-hook would race a database that does
#               not exist. Post-Sync also means this chart's Secrets already exist, so
#               no migration-only hook Secret is needed. Tradeoff: the api rolls out
#               before the schema lands and errors on PIX routes until the Job finishes.
#   external -> pre-install/pre-upgrade (PreSync), schema-first. That path DOES need the
#               minimal migration-only hook Secret at weight -5, since the chart's normal
#               Secret does not exist yet.
#
# There is no separate `<app>-migrations` image for this plugin, so the Job extracts the
# migrations tree out of the app image into an emptyDir and runs generic golang-migrate
# over it — schema and app therefore come from the same tag by construction.
#
# MULTI-TENANT: incompatible, and the chart FAILS on the combination. The Tenant Manager
# owns per-tenant database migrations; this Job targets the single-tenant database that
# MT never uses, so leaving it on would look like success while no tenant schema moved.
migrations:
  # -- Render the migration Job
  enabled: true
  # -- Job retry/lifecycle bounds
  backoffLimit: 3
  activeDeadlineSeconds: 600
  ttlSecondsAfterFinished: 600
  # -- Bounded wait for the bundled datastore; a timeout fails the Job loudly instead of
  # sitting in Init forever.
  waitTimeoutSeconds: 300
  # -- Extra annotations for the Job
  annotations: {}
  # -- Resources for the migrate container
  resources: {}
  # -- Image used to wait for the datastore to accept connections
  waitImage: busybox:1.37
  # -- golang-migrate image that applies the SQL
  migrateImage: migrate/migrate:v4.18.1
  # -- Where the migrations live inside the app image (Dockerfile copies them here)
  sourcePath: /migrations
  # -- Optional x-migrations-table override; empty uses golang-migrate's default
  table: ""

# -- Values block for the lerian-common library dependency. It is INERT — a library
# chart renders nothing and reads no values — but it must be declared, and this is
# not cosmetic: Helm injects a values key for EVERY declared dependency, library
# included, so a closed root schema (additionalProperties: false, which the
# repository schema generator emits) rejects the render with
# "additional properties 'lerian-common-helm' not allowed". The failure only
# surfaces in the repository render gate, which materializes the local dependency
# into an isolated workspace. Keep this key while the dependency exists.
lerian-common-helm: {}

postgresql:
  # -- Bundle the Bitnami postgresql subchart (the default). Set false for an
  # operator-provided Postgres and supply api.configmap.POSTGRES_HOST plus a
  # password (see api.secrets).
  enabled: true
  # -- Treat the datastore as external even while the dependency is present. Same
  # effect as enabled=false for credential sourcing.
  external: false
  auth:
    # -- Application database user. Must match api.configmap.POSTGRES_USER.
    username: "plugin-br-pix-jd"
    # -- LEAVE EMPTY. The subchart generates the password into its own Secret and
    # the app reads it from there via secretKeyRef (single-source, Pattern A).
    # Publishing a default here would be a reusable credential in version control.
    password: ""
    # -- Application database name. Must match api.configmap.POSTGRES_NAME.
    database: "plugin-br-pix-jd"
    # -- Point the subchart at an operator-managed Secret instead of a generated one
    existingSecret: ""
  primary:
    persistence:
      enabled: true
      size: 8Gi
