Pular para o conteúdo principal
Em ambientes de producao, nem toda remediação automática deve ser executada sem supervisao humana. O sistema de Approval Workflow do ChatCLI permite definir politicas granulares que controlam quais ações requerem aprovação, quem pode aprovar, e em quais janelas de mudanca (change windows) as ações são permitidas.

Por que Approval Workflows são Essenciais

Seguranca

Previne que remediação automática cause impacto maior que o problema original (ex: rollback acidental em producao)

Compliance

Auditoria completa de quem aprovou, quando, e por que. Requisito para SOC2, PCI-DSS, HIPAA.

Confianca

Equipes adotam AIOps mais facilmente quando sabem que ações criticas requerem aprovação humana.
Sem approval workflows, uma IA que detecta um falso positivo pode executar um rollback desnecessario, afetando um deployment saudavel. Com approval policies, ações de alto impacto são bloqueadas até que um humano valide a análise e o blast radius.

Visao Geral do Fluxo

ApprovalPolicy CRD

O ApprovalPolicy define regras que determinam quais ações de remediação precisam de aprovação, em quais condicoes, e quem pode aprovar.
apiVersion: platform.chatcli.io/v1alpha1
kind: ApprovalPolicy
metadata:
  name: production-approval-policy
  namespace: production
spec:
  rules:
    - name: auto-approve-low-risk
      match:
        severities: [low, medium]
        actionTypes: [RestartDeployment, ScaleDeployment]
        namespaces: [staging, development]
      mode: auto
      autoApproveConditions:
        minConfidence: 0.85
        maxSeverity: medium
        historicalSuccessRate: 0.90

    - name: manual-approve-rollback
      match:
        actionTypes: [RollbackDeployment]
        namespaces: [production, payments]
      mode: manual
      requiredApprovers: 1
      timeoutMinutes: 30

    - name: quorum-critical-production
      match:
        severities: [critical, high]
        namespaces: [production]
        resourceKinds: [Deployment, StatefulSet]
      mode: quorum
      requiredApprovers: 2
      timeoutMinutes: 15

    - name: block-critical-namespace-rollback
      match:
        actionTypes: [RollbackDeployment]
        namespaces: [payments, auth]
        severities: [critical]
      mode: manual
      requiredApprovers: 2
      timeoutMinutes: 10

  changeWindow:
    timezone: "America/Sao_Paulo"
    allowedDays: [1, 2, 3, 4, 5]    # Segunda a Sexta
    startHour: 9
    endHour: 18
    overrideForCritical: true         # Critical ignora change window
    blackoutDates:
      - date: "2026-03-20"
        reason: "Congelamento pre-release Q1"
      - date: "2026-12-24"
        reason: "Vespera de Natal"
      - date: "2026-12-31"
        reason: "Vespera de Ano Novo"

Campos do Spec

ApprovalRule

Cada regra define um par match + mode com configurações especificas.
CampoTipoObrigatórioDescrição
namestringSimNome único da regra dentro da policy
matchApprovalMatchSimCriterios de matching
modestringSimauto, manual, quorum
requiredApproversintPara manual/quorumNúmero mínimo de aprovadores
timeoutMinutesintNãoTimeout em minutos (padrão: 60)
autoApproveConditionsAutoApproveConditionsPara autoCondicoes para auto-aprovação

ApprovalMatch

Define quais remediações são cobertas por está regra. A logica e AND entre campos e OR dentro de cada campo.
CampoTipoDescrição
severities[]stringcritical, high, medium, low
actionTypes[]stringScaleDeployment, RestartDeployment, RollbackDeployment, PatchConfig, AdjustResources, DeletePod, Custom
namespaces[]stringNamespaces K8s afetados
resourceKinds[]stringDeployment, StatefulSet, DaemonSet
Quando multiplas regras fazem match, a regra mais restritiva prevalece. A ordem de prioridade e: manual > quorum > auto. Se uma regra exige quorum com 2 aprovadores e outra exige manual com 1, o sistema aplica quorum com 2.

Tres Modos de Aprovação

Auto-approve: O sistema aprova automaticamente se todas as condicoes de autoApproveConditions forem atendidas. Caso contrario, escala para manual.
CondiçãoTipoDescrição
minConfidencefloat64Confianca minima da análise de IA (0.0-1.0)
maxSeveritystringSeveridade máxima para auto-approve
historicalSuccessRatefloat64Taxa minima de sucesso histórico para este tipo de ação
mode: auto
autoApproveConditions:
  minConfidence: 0.90      # IA tem >= 90% de confianca
  maxSeverity: medium      # Até severidade medium
  historicalSuccessRate: 0.85  # >= 85% de sucesso em ações similares
Logica de avaliacao:
auto_approve = (
  ai_confidence >= minConfidence AND
  severity <= maxSeverity AND
  historical_success_rate >= historicalSuccessRate
)

Se auto_approve = false -> escala para modo manual (1 approver)

ChangeWindowSpec

Define janelas de mudanca (change windows) que controlam quando remediação automática pode ser executada.
CampoTipoObrigatórioDescrição
timezonestringSimTimezone IANA (ex: America/Sao_Paulo)
allowedDays[]intSimDias permitidos (0=Domingo, 6=Sabado)
startHourintSimHora de início da janela (0-23)
endHourintSimHora de fim da janela (0-23)
overrideForCriticalboolNãoSe true, severidade critical ignora a change window
blackoutDates[]BlackoutDateNãoDatas especificas com congelamento total
Quando fora da change window, ações de remediação ficam enfileiradas (não descartadas). Elas serão executadas automaticamente quando a proxima janela abrir — desde que o Issue ainda esteja ativo e o approval não tenha expirado.

ApprovalRequest CRD

O ApprovalRequest e criado automaticamente pelo RemediationReconciler quando uma ação requer aprovação. Contem todas as informações necessarias para o aprovador tomar uma decisao informada.
apiVersion: platform.chatcli.io/v1alpha1
kind: ApprovalRequest
metadata:
  name: approve-api-gateway-rollback-1234
  namespace: production
  labels:
    platform.chatcli.io/issue: api-gateway-oom-kill-1771276354
    platform.chatcli.io/action-type: RollbackDeployment
    platform.chatcli.io/severity: critical
spec:
  issueRef:
    name: api-gateway-oom-kill-1771276354
  remediationPlanRef:
    name: api-gateway-oom-kill-plan-1
  requestedAction:
    type: RollbackDeployment
    params:
      toRevision: "previous"
  policyRef:
    name: production-approval-policy
    rule: manual-approve-rollback
  requiredApprovers: 1
  timeoutMinutes: 30

  blastRadius:
    affectedPods: 5
    affectedServices:
      - name: api-gateway
        namespace: production
        endpoints: 3
      - name: api-gateway-internal
        namespace: production
        endpoints: 2
    affectedIngresses:
      - name: api-gateway-ingress
        namespace: production
    riskLevel: high
    estimatedDowntime: "30s"
    rollbackAvailable: true

  evidence:
    aiConfidence: 0.87
    analysis: "High restart count caused by OOMKilled. Container memory limit (512Mi) insufficient."
    historicalSuccessRate: 0.92
    similarIncidents: 3
    lastSimilarResolution: "RollbackDeployment to revision 5 (2 days ago, success)"

status:
  state: Pending            # Pending | Approved | Rejected | Expired
  decisions: []
  createdAt: "2026-03-19T14:30:00Z"
  expiresAt: "2026-03-19T15:00:00Z"

Campos do Spec

Raiz

CampoTipoObrigatórioDescrição
issueRefObjectRefSimReferência ao Issue que originou o request
remediationPlanRefObjectRefSimReferência ao RemediationPlan pausado
requestedActionActionSpecSimAção que requer aprovação
policyRefPolicyRefSimReferência a policy e regra que disparou
requiredApproversintSimNúmero mínimo de aprovadores
timeoutMinutesintSimTempo até expirar
blastRadiusBlastRadiusAssessmentSimAvaliacao de impacto
evidenceApprovalEvidenceSimEvidencias para tomada de decisao

BlastRadiusAssessment

CampoTipoDescrição
affectedPodsintNúmero de pods que serão afetados pela ação
affectedServices[]ServiceRefServices que roteiam para os pods afetados
affectedIngresses[]IngressRefIngresses que expoe os services afetados
riskLevelstringcritical, high, medium, low (calculado)
estimatedDowntimestringEstimativa de downtime durante a ação
rollbackAvailableboolSe a ação pode ser revertida

ApprovalEvidence

CampoTipoDescrição
aiConfidencefloat64Nível de confianca da análise da IA (0.0-1.0)
analysisstringResumo da análise da IA
historicalSuccessRatefloat64Taxa de sucesso de ações similares no histórico
similarIncidentsintNúmero de incidentes similares no passado
lastSimilarResolutionstringDescrição da ultima resolucao similar

ApprovalDecision

Cada aprovação ou rejeicao e registrada como uma decision no status:
CampoTipoDescrição
approverstringIdentificador do aprovador (usuario ou sistema)
decisionstringapproved ou rejected
reasonstringJustificativa para a decisao
timestampTimeQuando a decisao foi feita

Estados do ApprovalRequest

Uma única rejeicao e suficiente para bloquear a acao, independente do número de aprovações. Isso garante que qualquer membro da equipe pode vetar uma ação de risco.

Blast Radius Calculator

O blast radius calculator avalia o impacto potencial de uma ação de remediação antes de solicitar aprovação.

Como Funciona

1

Consulta pods do deployment

O calculator lista todos os pods gerenciados pelo deployment alvo usando label selectors.
pods = kubectl get pods -l app=api-gateway -n production
affectedPods = len(pods)  // ex: 5
2

Encontra services que roteiam para os pods

Para cada Service no namespace, verifica se o selector faz match com as labels dos pods do deployment.
for service in namespace.services:
  if service.selector matches pod.labels:
    affectedServices.append(service)
3

Encontra ingresses que expoe os services

Para cada Ingress no namespace, verifica se referência algum dos services afetados.
for ingress in namespace.ingresses:
  for rule in ingress.rules:
    if rule.backend.service in affectedServices:
      affectedIngresses.append(ingress)
4

Calcula risk level

O risk level e determinado pelo número de pods afetados:
if affectedPods > 10:  riskLevel = "critical"
if affectedPods > 5:   riskLevel = "high"
if affectedPods > 2:   riskLevel = "medium"
else:                  riskLevel = "low"
5

Estima downtime

Com base no tipo de acao:
AçãoDowntime Estimado
ScaleDeployment (up)0s (nenhum pod removido)
RestartDeployment~30s (rolling update)
RollbackDeployment~30-60s (rolling update)
AdjustResources~30s (rolling update)
DeletePod~10s (recreacao pelo ReplicaSet)
PatchConfig0s (sem restart)

Integração com RemediationReconciler

Fluxo Completo

Annotation de Controle

O RemediationReconciler usa a annotation platform.chatcli.io/approval-pending para controlar o fluxo:
metadata:
  annotations:
    platform.chatcli.io/approval-pending: "approve-api-gateway-rollback-1234"
Quando está annotation está presente:
  1. O reconciler não executa nenhuma ação
  2. Consulta o status do ApprovalRequest referenciado
  3. Remove a annotation apenas quando o request e Approved
  4. Se Rejected ou Expired, marca o plan como Failed

Como Aprovar

Via kubectl

A maneira mais direta de aprovar e usando annotations:
# Aprovar
kubectl annotate approvalrequest approve-api-gateway-rollback-1234 \
  -n production \
  platform.chatcli.io/approve="edilson:LGTM, blast radius aceitavel"

# Rejeitar
kubectl annotate approvalrequest approve-api-gateway-rollback-1234 \
  -n production \
  platform.chatcli.io/reject="edilson:Risk too high, investigate memory leak first"
Formato da annotation:
platform.chatcli.io/approve="<usuario>:<motivo>"
platform.chatcli.io/reject="<usuario>:<motivo>"
O reconciler do ApprovalRequest detecta a annotation, registra a decision no status, e remove a annotation.

Via REST API

O operator expoe uma API REST para integrações:
curl -X POST \
  http://localhost:8090/api/v1/approvals/approve-api-gateway-rollback-1234/approve \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "approver": "edilson",
    "reason": "LGTM, blast radius aceitavel. AI confidence 87% com histórico de sucesso."
  }'
Resposta da API (exemplo):
{
  "name": "approve-api-gateway-rollback-1234",
  "namespace": "production",
  "state": "Approved",
  "requestedAction": {
    "type": "RollbackDeployment",
    "params": {"toRevision": "previous"}
  },
  "blastRadius": {
    "affectedPods": 5,
    "riskLevel": "high"
  },
  "decisions": [
    {
      "approver": "edilson",
      "decision": "approved",
      "reason": "LGTM, blast radius aceitavel",
      "timestamp": "2026-03-19T14:35:00Z"
    }
  ]
}

Via Slack (interativo)

Quando integrado com o canal Slack via NotificationPolicy, o ApprovalRequest inclui botoes interativos no Block Kit:
  • Approve: Registra aprovação com o usuário Slack como aprovador
  • Reject: Abre dialog para motivo de rejeicao
  • Details: Expande blast radius e evidencias da IA
A integração Slack interativa requer configuração adicional de um Slack App com Interactive Components habilitado e endpoint de callback apontando para o operator.

Exemplos YAML Completos

Auto-approve para Low Severity + High Confidence

apiVersion: platform.chatcli.io/v1alpha1
kind: ApprovalPolicy
metadata:
  name: staging-auto-approve
  namespace: staging
spec:
  rules:
    - name: auto-approve-all-staging
      match:
        severities: [low, medium]
        actionTypes:
          - RestartDeployment
          - ScaleDeployment
          - AdjustResources
          - DeletePod
        namespaces: [staging]
      mode: auto
      autoApproveConditions:
        minConfidence: 0.80
        maxSeverity: medium
        historicalSuccessRate: 0.75

    - name: manual-for-rollback-staging
      match:
        actionTypes: [RollbackDeployment]
        namespaces: [staging]
      mode: manual
      requiredApprovers: 1
      timeoutMinutes: 60

  changeWindow:
    timezone: "America/Sao_Paulo"
    allowedDays: [0, 1, 2, 3, 4, 5, 6]   # Todos os dias
    startHour: 0
    endHour: 23

Quorum de 2 Approvers para Producao

apiVersion: platform.chatcli.io/v1alpha1
kind: ApprovalPolicy
metadata:
  name: production-strict
  namespace: production
spec:
  rules:
    - name: quorum-all-production-actions
      match:
        severities: [critical, high, medium]
        namespaces: [production]
      mode: quorum
      requiredApprovers: 2
      timeoutMinutes: 15

    - name: auto-low-severity-restart
      match:
        severities: [low]
        actionTypes: [RestartDeployment]
        namespaces: [production]
      mode: auto
      autoApproveConditions:
        minConfidence: 0.95
        maxSeverity: low
        historicalSuccessRate: 0.98

  changeWindow:
    timezone: "America/Sao_Paulo"
    allowedDays: [1, 2, 3, 4, 5]
    startHour: 9
    endHour: 18
    overrideForCritical: true

Change Window Weekdays 9-18 UTC

apiVersion: platform.chatcli.io/v1alpha1
kind: ApprovalPolicy
metadata:
  name: change-window-policy
  namespace: production
spec:
  rules:
    - name: all-actions-require-approval
      match:
        namespaces: [production]
      mode: manual
      requiredApprovers: 1
      timeoutMinutes: 120

  changeWindow:
    timezone: "UTC"
    allowedDays: [1, 2, 3, 4, 5]    # Monday to Friday
    startHour: 9
    endHour: 18
    overrideForCritical: true
    blackoutDates:
      - date: "2026-03-27"
        reason: "End of Q1 freeze"
      - date: "2026-03-28"
        reason: "End of Q1 freeze"
      - date: "2026-06-30"
        reason: "End of Q2 freeze"
Use overrideForCritical: true para permitir que incidentes critical sejam remediados fora da change window. Sem isso, um incidente critico as 3h da manha ficara enfileirado até as 9h.

Bloqueio de RollbackDeployment em Namespaces Criticos

apiVersion: platform.chatcli.io/v1alpha1
kind: ApprovalPolicy
metadata:
  name: critical-namespace-protection
  namespace: payments
spec:
  rules:
    - name: block-rollback-payments
      match:
        actionTypes: [RollbackDeployment]
        namespaces: [payments, auth, billing]
      mode: quorum
      requiredApprovers: 2
      timeoutMinutes: 10

    - name: block-delete-pod-payments
      match:
        actionTypes: [DeletePod]
        namespaces: [payments]
      mode: manual
      requiredApprovers: 1
      timeoutMinutes: 15

    - name: auto-scale-only
      match:
        actionTypes: [ScaleDeployment]
        namespaces: [payments]
      mode: auto
      autoApproveConditions:
        minConfidence: 0.90
        maxSeverity: high
        historicalSuccessRate: 0.95

  changeWindow:
    timezone: "America/Sao_Paulo"
    allowedDays: [1, 2, 3, 4]    # Seg-Qui (sem sexta para freeze pre-fim-de-semana)
    startHour: 10
    endHour: 16
    overrideForCritical: true
    blackoutDates:
      - date: "2026-03-31"
        reason: "Fechamento mensal"
      - date: "2026-04-30"
        reason: "Fechamento mensal"

Auditoria e Compliance

Todas as decisoes de aprovação são registradas no status do ApprovalRequest CR, criando um trail de auditoria completo:
# Ver histórico de aprovações
kubectl get approvalrequests -n production \
  -o custom-columns=NAME:.metadata.name,STATE:.status.state,APPROVER:.status.decisions[0].approver,REASON:.status.decisions[0].reason,TIME:.status.decisions[0].timestamp

# Output:
# NAME                                  STATE      APPROVER   REASON              TIME
# approve-api-gw-rollback-1234          Approved   edilson    LGTM                2026-03-19T14:35:00Z
# approve-worker-scale-5678             Approved   system     Auto-approved       2026-03-19T15:00:00Z
# approve-payment-restart-9012          Rejected   maria      Risk too high       2026-03-19T15:30:00Z
# approve-auth-rollback-3456            Expired    -          Timeout (15min)     2026-03-19T16:00:00Z
Para compliance SOC2 e PCI-DSS, exporte os ApprovalRequests periodicamente:
kubectl get approvalrequests -A -o json | jq '.items[] | {
  name: .metadata.name,
  namespace: .metadata.namespace,
  action: .spec.requestedAction.type,
  state: .status.state,
  decisions: .status.decisions,
  blastRadius: .spec.blastRadius.riskLevel,
  created: .status.createdAt
}' > approval-audit-$(date +%Y%m%d).json

Prometheus Metrics

O sistema de approval workflow expoe metricas para monitoramento:
MetricaTipoLabelsDescrição
chatcli_approvals_totalCounterpolicy, rule, namespace, decisionTotal de aprovações por decision (approved/rejected/expired/auto)
chatcli_approval_duration_secondsHistogrampolicy, rule, decisionTempo entre criacao do request e decisao
chatcli_approvals_pendingGaugepolicy, namespaceNúmero de ApprovalRequests pendentes
chatcli_approval_auto_approved_totalCounterpolicy, rule, namespaceTotal de auto-aprovações
chatcli_approval_auto_escalated_totalCounterpolicy, rule, namespaceAuto-approve que escalou para manual
chatcli_approval_blast_radius_podsHistogramnamespace, action_typeDistribuicao de pods afetados nos requests
chatcli_change_window_blocked_totalCounterpolicy, namespaceAções bloqueadas por change window
Alertas Prometheus recomendados:
groups:
  - name: chatcli-approvals
    rules:
      - alert: ApprovalRequestPendingTooLong
        expr: chatcli_approvals_pending > 0 and time() - chatcli_approval_created_timestamp > 600
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "ApprovalRequest pendente ha mais de 10 minutos"
          description: "{{ $labels.policy }}/{{ $labels.namespace }} tem requests aguardando aprovação"

      - alert: HighRejectionRate
        expr: rate(chatcli_approvals_total{decision="rejected"}[1h]) / rate(chatcli_approvals_total[1h]) > 0.3
        for: 30m
        labels:
          severity: warning
        annotations:
          summary: "Taxa de rejeicao de aprovações acima de 30%"
          description: "Pode indicar falsos positivos na análise de IA ou politica muito permissiva"

      - alert: ApprovalTimeoutRate
        expr: rate(chatcli_approvals_total{decision="expired"}[1h]) > 0.1
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "Aprovações expirando por timeout"
          description: "Equipes podem não estar recebendo notificações ou timeouts estão curtos demais"

Próximo Passo

Notificações e Escalacao

Sistema de notificações multi-canal e politicas de escalacao

SLOs e SLAs

Gestao de Service Level Objectives com burn rate alerting

AIOps Platform

Deep-dive na arquitetura AIOps completa

K8s Operator

Configuração e CRDs do operator