# promotion-manifest.yaml
# Manifesto de promoção lab -> homolog (ClubPetro).
# A PR de promoção deve ser marcada com [lab] e conter este arquivo.
# O pipeline lê os campos abaixo pra rodar os gates 0 + A-F + G + admissao.
#
# OBS: o schema exato é definido pelo parser do pipeline (referências vivas:
# backend=external_apis, seed=action-plan). As chaves aqui são auto-descritivas;
# reconcilie com o parser se ele exigir nomes específicos.

apiVersion: v1
kind: PromotionManifest

service:
  name: vanna-clubpetro
  kind: backend                 # serviço HTTP (não é MFE)
  description: >
    Deploy do Vanna 2.0 (text-to-SQL sobre LLM) que responde perguntas em
    pt-BR consultando o ClickHouse Cloud (database gold) com RLS por tenant
    (program_id + store_id).
  owner: dados-plataforma        # TODO: confirmar squad/owner
  runtimePort: 8765

promotion:
  from: lab
  to: homolog
  # Onde o pipeline re-materializa o código (branch limpa, sem histórico do lab).
  kubernetesOverlay: k8s/hml

# ---------------------------------------------------------------------------
# Gate 0 — Stack
# ---------------------------------------------------------------------------
stack:
  language: python
  runtime: python-3.11
  framework: vanna-2.0 + fastapi + uvicorn
  packageManager: pip
  # Stack padrão do core é NestJS>=10/TypeORM0.3 (yarn) OU MFE React17/MUI5.
  # Python é NO-GO por padrão -> exceção formal abaixo (Gate 0).
  stackException:
    requested: true
    reason: >
      O serviço é um deploy da biblioteca Vanna 2.0, que é Python e não tem
      equivalente em NestJS. O núcleo (agente LLM, memória vetorial ChromaDB,
      runner RLS do ClickHouse e o web component <vanna-chat>) vem do upstream
      vanna-ai/vanna. Reescrever em Node significaria reimplementar toda essa
      cadeia — inviável e sem ganho. Mantém-se Python; todos os demais gates
      aplicáveis são cumpridos (ver abaixo).
    approvedBy: ""              # TODO: preencher com o aprovador humano do stackException

# ---------------------------------------------------------------------------
# Gate B — Migrations
# ---------------------------------------------------------------------------
migrations:
  applicable: false
  reason: >
    O serviço não possui schema relacional próprio. O ClickHouse Cloud
    (database gold) é gerido fora do serviço; o "treino" (train.py) apenas
    popula um vector store ChromaDB local, idempotente e reconstruível
    (rm -rf chroma_db/ && python train.py). Não há migrations TypeORM.
    Toda query ao ClickHouse é parametrizada via settings do clickhouse_connect
    (RLS), nunca por interpolação de string — ver rls_runner.py.

# ---------------------------------------------------------------------------
# Gate D — Atalhos / segurança
# ---------------------------------------------------------------------------
security:
  envVersioned: false            # apenas .env.example versionado; .env no .gitignore
  hardcodedSecrets: false        # segredos vêm de k8s Secret (envFrom), nunca do git
  hardcodedLabHost: false        # overlay homolog usa homologation.clubpetro.com
  npmrcVersioned: false          # sem .npmrc no repo

# ---------------------------------------------------------------------------
# Gate G — Isolamento de credenciais de banco
# ---------------------------------------------------------------------------
database:
  # Credenciais do ClickHouse em secret DEDICADO ao serviço (não genérico).
  credentialsSecret: vanna-clubpetro-db
  genericSecret: false           # NÃO usa sqlhomologation / sqluserhomolgeneric etc.
  engine: clickhouse-cloud
  database: gold

# ---------------------------------------------------------------------------
# Admissão de capacidade
# ---------------------------------------------------------------------------
capacity:
  replicas: 1                    # ChromaDB é SQLite-based; réplicas > 1 corrompem o store
  strategy: Recreate             # PVC ReadWriteOnce — não dá 2 pods montando ao mesmo tempo
  resources:
    requests:
      cpu: "200m"
      memory: "1Gi"
    limits:
      cpu: "1"
      memory: "2Gi"
  persistentVolume:
    size: 5Gi
    accessMode: ReadWriteOnce    # store vetorial + cache ONNX + CSVs

# ---------------------------------------------------------------------------
# Deltas (avisos — não bloqueiam)
# ---------------------------------------------------------------------------
deltas:
  A_architecture: >
    Tenant (program_id/store_id) resolvido via RequestContext e validado por
    regex ^[A-Za-z0-9_-]+$ (agent.py). O embed confiável passa os IDs por query
    param do <vanna-chat> — não há token JWT nesta arquitetura de embed.
  C_contract: >
    OpenAPI auto-servido pelo FastAPI (/openapi.json, /docs). Rotas de chat já
    versionadas: /api/vanna/v2/chat_sse|chat_websocket|chat_poll (upstream).
  E_ops: >
    Probes de liveness/readiness em GET /health; replicas: 1; Dockerfile
    multi-stage rodando como usuário non-root (uid 10001).
  F_ci: >
    CI/CD via .gitea/workflows/cd.yml (build remoto no Cloud Build + rollout
    no GKE). bitbucket-pipelines.yml N/A: o repo vive no Gitea self-hosted.
