server:
  addr: ":8080"
  web_ui_base_url: "https://alerts.pingcap.net/ui/"
database:
  dsn: "${DB_DSN}"

im:
  provider: lark
  main_channel_id: "oc_39c92891432ec965b40022bf177f5912"
  app_id: "cli_aad4ad63ddb8dbb5"
  app_secret: "${LARK_APP_SECRET}"
  lark_base_url: "https://open.feishu.cn"

clinic:
  base_url: "https://clinic.pingcap.com"
  token: "${CLINIC_TOKEN}"
  # jiralert prod's ActivityHub endpoint, which is the right one here: this
  # deployment reads the prod alert feed. Dev points at the same URL for want of
  # a non-prod source; staging has its own.
  activity_url: "https://e4hr1v4oqh.execute-api.us-west-2.amazonaws.com/activities/"
  activity_source: "eventbus"
  activity_key: "${EVENT_KEY}"
  timeout: 5s

oncall:
  # Internal (ClusterIP-only) listener of the oncall v2 service: no
  # credential, so no key to rotate.
  #
  # Alerts route by their oncall_team label. fire_master catches the ones
  # without it — the same team jiraport pages at the top of its escalation
  # ladder, so an alert nobody else owns lands with whoever is holding the
  # pager rather than nowhere. Note this is a fallback for a *missing* label:
  # an alert whose label names a team the service does not have is reported as
  # unknown_team and stays unowned.
  base_url: "http://oncall-internal.oncall-prod.svc.cluster.local"
  default_team: "fire_master"
  timeout: 5s
  cache_ttl: 1m

# core-server's user directory, the mirror of the Lark org chart the web UI
# searches when someone reassigns an alert. An in-cluster ClusterIP listener
# that authenticates nothing — the shared gateway does that in front of it — so
# unlike the oncall lookup above there is no credential here. Dropping base_url
# only costs the suggestions; the assignee field is free text with or without
# them.
directory:
  base_url: "http://core-server.core-server-prod.svc.cluster.local"
  timeout: 5s
  cache_ttl: 5m

# The DevOps ops portal, which owns the commercial view of a tenant: the sales
# region the account belongs to (NA/EMEA/APAC/…, not the cloud region an alert's
# labels carry), whether it is internal or a customer's, and its sales tier
# (SKA/KA/SMB). Alerts carry none of that and Clinic knows clusters, not
# accounts.
#
# Same shape as the two lookups above: alertstore reads the portal's own
# ClusterIP listener over /api/v1/devops-internal, which carries no auth
# middleware and is not routed through the public ALB, so there is no credential
# here either. Dropping base_url only costs the three fields; nothing else about
# an alert changes.
devops:
  base_url: "http://devops-server.devops-prod.svc.cluster.local:8088"
  timeout: 5s
  cache_ttl: 30m

alert:
  response_deadline: 15m
  recovery_deadline: 4h
webhook:
  alertmanager_token: "${ALERTSTORE_WEBHOOK_TOKEN}"

# Transitional, removed along with jiralert. For the alerts alertstore is the
# primary responder for, it also creates the Jira ticket jiralert used to, so
# automation reading Jira keeps working.
#
# Off, as in staging, and here it is not a preference but the whole safety
# model: an alert is alertstore's only if its rule carries `as_response`, the
# same label jiralert reads to stop responding to it. Everything else stays a
# shadow copy — recorded and queryable, but no owner, no subscription forward,
# no issue — and jiralert keeps handling it exactly as it does today. Flipping
# this to true would take every prod alert at once, and would double-file with
# jiralert on every rule it still answers.
cutover:
  own_everything: false

# The project and summary tag jiralert's prod receivers use, so downstream
# readers see no change when a rule hands over. Only handed-over alerts get an
# issue. JIRA_TOKEN is optional in the Deployment: until it is present in
# Secrets Manager the mirror simply stays off, which is a fine state to start
# prod in.
jira:
  base_url: "https://tidb.atlassian.net/"
  user: "charles.m@pingcap.com"
  token: "${JIRA_TOKEN}"
  project: "O11Y"
  summary_prefix: "[PROD]"

# Agents. Which agents exist, which alerts each one wants and where to reach it
# live in the `agent_subscription` table, not here — an agent's reach changes as
# it earns trust, and that is data, not a redeploy.
#
# callback_base_url is alertstore's own API root *as the agent can reach it*,
# which for prod is not an in-cluster address: the agents run on the resilience
# platform box in the staging cluster, so they come back through the datasource
# proxy beside them, which already holds the prod DevOps credential and fronts
# the same gateway this service is published on. alertstore only templates this
# into the dispatch payload and never calls it itself, so the value only has to
# mean something on the agent's host.
#
# With no `agent_subscription` rows this is inert: nothing is dispatched. The
# two together are the on switch, deliberately — a half-configured environment
# then drops nothing rather than dead-lettering every alert until somebody
# notices.
agent:
  callback_base_url: "http://127.0.0.1:8990/devops/prod"
  timeout: 10s
  # 0 while no agent output is rendered on any human surface. Raise it in the
  # same change that first shows a verdict to a resolver: a verdict on screen
  # anchors the human's own, so once they are visible the agreement rate stops
  # measuring accuracy. The held sample is the only population where the two
  # stay independent, and it cannot be created retroactively.
  hold_rate: 0
