Runbook: ETM session failure

Severity (default): P2 (P1 если затронуто > 50% credentials). Owner: ingestion team / on-call. Связанные алерты:

  • session_refresh_failed_total{supplier="etm"} > 3 за 10 мин на одной credential.
  • etm_credential_failures_total{type="auth"} rate > 1/min на одной credential.
  • Резкий drop ingestion_observations_emitted_total{supplier="etm"}.

Симптом

  • Дашборд “Ingestion → ETM” показывает падение rate observations.
  • В UI клиентского кабинета у одного или нескольких клиентов — badge “credential failing”.
  • Алерт session_refresh_failed.

Диагностика

# 1. Какие credentials упали?
kubectl -n tracium exec deploy/ingestor -- \
  psql "$PG_DSN" -c "
    SELECT id, label, customer_ref, status, last_validated_at
    FROM supplier_credential
    WHERE supplier_ref='etm' AND status IN ('failing','expired')
    ORDER BY last_validated_at DESC LIMIT 50;
  "
# 2. Логи последних попыток login для конкретной credential
kubectl -n tracium logs deploy/ingestor --since=30m \
  | grep -E "etm.*credential_id=<CRED_ID>" \
  | grep -E "login|auth|session"
# 3. Состояние бакета в Redis
kubectl -n tracium exec deploy/redis -- \
  redis-cli GET "ratelimit:etm:<CRED_ID>:login"
# 4. Проверить ответ ETM напрямую (с системной credential, аккуратно)
# Для отладки сначала используем itest2; prod нужен только для parity-check.
curl -sS -X POST https://itest2.etm.ru/api/v1/user/login \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'log=<system_login>' \
  --data-urlencode 'pwd=<system_pass>'

Возможные причины:

  • A: ETM поменяли пароль клиента (или клиент сам поменял у ETM, не уведомил).
  • B: Всплеск rate-limit ETM (etm_credential_usage_ratio > 1.0 в момент падения).
  • C: Истёк срок договора клиента у ETM (expired от сервера, valid_to нашей credential тоже истёк).
  • D: Инцидент API ETM (5xx на /user/login по всем credentials, не только одной).
  • E: Изменение API ETM (login form / envelope / session-id query перестали соответствовать текущему wire-contract).

Смягчение

Если C/D (массово)

# Открыть circuit breaker для всех ETM-credentials, перейти на graceful degradation.
kubectl -n tracium exec deploy/admin-api -- \
  curl -X POST localhost:8080/v1/admin/connectors/etm/pause \
  -H 'X-Admin-Token: <token>' \
  -d '{"reason":"upstream incident","ttl":"15m"}'

UI клиентов автоматически покажет stale data с пометкой.

Если A/C (одна credential)

# Помечаем credential failing (если ещё не помечено), уведомление клиенту уйдёт автоматически.
kubectl -n tracium exec deploy/ingestor -- \
  psql "$PG_DSN" -c "
    UPDATE supplier_credential
    SET status='failing', updated_at=now()
    WHERE id='<CRED_ID>';
  "

Клиент получит email + UI badge → обновит у себя credential через свой кабинет.

Если B (всплеск rate)

# Временно снизить rate в hot-config override
kubectl -n tracium exec deploy/admin-api -- \
  curl -X PATCH localhost:8080/v1/admin/connectors/etm/rate-limits \
  -H 'X-Admin-Token: <token>' \
  -d '{"goods_read":{"rate":1,"period":"2s"},"ttl":"1h"}'

Если E (изменение API)

Не смягчение — нужен hotfix коннектора. Эскалация в ingestion.

Устранение root cause

  • A: процесс уведомления клиента о смене пароля ETM (UX в кабинете).
  • B: пересмотр rate budget (см. 30-services/ingestion/connectors/etm/rate-budget.md).
  • C: автоматическая проверка valid_to за 7 дней до истечения с email-нотификацией клиенту.
  • D: оповещение от ETM SRE / страница инцидентов.
  • E: ручной smoke против itest2 на каждый PR коннектора и точечный parity-check против prod перед релизом.

Эскалация

  • 15 мин без mitigation → #oncall-ingestion.
  • 30 мин и > 30% клиентов с failing credentials → #oncall-product (нужна коммуникация с клиентами).
  • Если подозрение на security incident (массовая компрометация credentials) → #security немедленно.

Связано

  • 30-services/ingestion/connectors/etm/rate-budget.md
  • 30-services/ingestion/connectors/etm/spec.md
  • 10-business/contexts/credentials.md § Lifecycle credentials
  • ADR-0009 (multi-tenant supplier credentials)