Programação Por Equipe DevBras

Capa do artigo: Automação no Trello sem vazar o token: a API chamada do lugar certo

Automação no Trello sem vazar o token: a API chamada do lugar certo

Mova cartões pela API do quadro a partir do servidor ou do CI, com token de escopo mínimo, fora do código, fora do log e sem duplicar cartão quando o evento chega duas vezes.

Terça, 16h. O deploy termina e o cartão "Corrigir frete grátis" pula sozinho de "Em revisão" para "Em produção". A equipe adora. Duas semanas depois, alguém abre o JavaScript do painel interno e acha, no meio do código, a chave e o token do Trello. Aquele token não move só aquele cartão: ele lê e escreve em todos os quadros que a pessoa que o gerou enxerga.

A resposta curta: a chamada à API do quadro roda no servidor ou no job de CI, nunca no navegador nem num script versionado. O token fica em variável de ambiente ou no cofre de segredos, pertence a uma conta de serviço que só participa do quadro necessário, tem o menor escopo que resolve e nunca aparece em log. E toda ação que cria algo guarda o identificador do evento, para que o mesmo aviso chegando duas vezes não gere dois cartões.

Por que o token do quadro é uma chave da equipe

Na API do Trello, uma requisição se identifica com duas peças: a API key, que identifica o aplicativo, e o token, que representa um usuário que autorizou esse aplicativo. Quem tem as duas age como aquele usuário, dentro do escopo concedido. Se o token foi gerado com leitura e escrita, ele pode criar, mover, arquivar e comentar em qualquer quadro daquela pessoa, inclusive nos que não têm nada a ver com a automação.

Por isso o raciocínio "é só um script que move cartão" engana. O script é pequeno; a credencial, não. Colocar o token no front é publicá-lo: qualquer visitante abre as ferramentas do navegador e copia. Colocar no repositório é entregá-lo a todo mundo que tem ou terá acesso ao Git, incluindo forks, backups e o notebook do estagiário que saiu ano passado.

O mesmo vale para outros quadros e gerenciadores de tarefa com API: o padrão de risco é idêntico. O exemplo aqui usa Trello porque é o que o post original cita, mas os passos servem para qualquer ferramenta que autentica por token pessoal.

O caso: mover o cartão quando o deploy termina

A equipe de uma loja virtual usa um quadro "Sprint" com as listas "A fazer", "Em revisão" e "Em produção". A regra: quando o pipeline publica uma versão, cada cartão citado nos commits (por exemplo, com o identificador curto do cartão na mensagem) vai para "Em produção". A automação roda como último passo do job de deploy, que já tem acesso a segredos.

Como gerar um token com o menor poder possível

  1. Crie uma conta de serviço (por exemplo, "bot-deploy") e convide essa conta apenas para o quadro "Sprint". O token herda o que a conta enxerga; se ela só vê um quadro, o estrago máximo fica limitado a ele.
  2. Gere a API key no painel de desenvolvedor do Trello, logado com a conta de serviço.
  3. Autorize com escopo e validade definidos. A tela de autorização aceita parâmetros como scope e expiration. Peça read,write só se a automação escreve, e evite never quando der para renovar periodicamente.
  4. Guarde key e token como segredos do CI, nunca num arquivo .env commitado.
  5. Anote onde o token é usado, para saber o que quebra quando você revogar e gerar outro.
https://trello.com/1/authorize?key=SUA_API_KEY&name=bot-deploy&scope=read,write&expiration=30days&response_type=token

Confira os valores aceitos na documentação oficial antes de usar; o ponto aqui é o princípio: escopo mínimo e prazo de validade, em vez de "acesso total para sempre".

Como chamar a API do servidor, sem expor nada

O script abaixo roda em Node 18 ou mais novo, que já tem fetch. Ele lê as credenciais do ambiente, envia o token no cabeçalho Authorization em vez de pendurá-lo na URL, e nunca imprime a URL ou os cabeçalhos quando algo falha.

// mover-cartao.js: roda no job de deploy, nunca no navegador
const KEY = process.env.TRELLO_KEY;
const TOKEN = process.env.TRELLO_TOKEN;
const LISTA_PRODUCAO = process.env.TRELLO_LISTA_PRODUCAO;

if (!KEY || !TOKEN || !LISTA_PRODUCAO) {
  console.error('Faltam TRELLO_KEY, TRELLO_TOKEN ou TRELLO_LISTA_PRODUCAO');
  process.exit(1);
}

async function moverCartao(idCartao) {
  const url = new URL('https://api.trello.com/1/cards/' + encodeURIComponent(idCartao));
  url.searchParams.set('idList', LISTA_PRODUCAO);

  const resposta = await fetch(url, {
    method: 'PUT',
    headers: {
      Authorization: 'OAuth oauth_consumer_key="' + KEY + '", oauth_token="' + TOKEN + '"',
      Accept: 'application/json'
    }
  });

  if (!resposta.ok) {
    throw new Error('Trello respondeu ' + resposta.status + ' para o cartão ' + idCartao);
  }
  return resposta.json();
}

const cartoes = process.argv.slice(2);
Promise.all(cartoes.map(moverCartao))
  .then(() => console.log('Movidos: ' + cartoes.length))
  .catch((erro) => {
    console.error(erro.message);
    process.exit(1);
  });

A documentação do Trello também mostra key e token como parâmetros de query. Funciona, mas a URL completa costuma parar em log de proxy, de servidor e de ferramenta de monitoramento. No cabeçalho, o risco de vazar por acidente cai bastante.

No GitHub Actions, o passo fica assim, com os valores vindo de segredos do repositório:

- name: Mover cartões para "Em produção"
  run: node scripts/mover-cartao.js $CARTOES
  env:
    TRELLO_KEY: ${{ secrets.TRELLO_KEY }}
    TRELLO_TOKEN: ${{ secrets.TRELLO_TOKEN }}
    TRELLO_LISTA_PRODUCAO: ${{ vars.TRELLO_LISTA_PRODUCAO }}
    CARTOES: ${{ steps.cartoes.outputs.ids }}

Evento repetido não pode virar cartão duplicado

Mover um cartão para a mesma lista duas vezes não faz mal: o resultado é o mesmo. Criar é diferente. Se a automação abre um cartão "Incidente" a cada alerta do monitoramento, e o alerta é reenviado porque a primeira resposta demorou, a equipe acorda com três cartões iguais.

A saída é a mesma de qualquer integração que recebe evento: guardar o identificador do evento numa tabela com chave única e só agir se ele ainda não existe. É o mesmo princípio de idempotência no pagamento, aplicado a um quadro.

CREATE TABLE automacao_quadro (
  id_evento  VARCHAR(100) PRIMARY KEY,
  id_cartao  VARCHAR(50),
  criado_em  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- 1. Tenta reservar o evento. Se a chave já existe, o INSERT falha e você para aqui.
INSERT INTO automacao_quadro (id_evento) VALUES ('alerta-2026-10-14-0315-disco');

-- 2. Cria o cartão na API e grava o id devolvido.
UPDATE automacao_quadro SET id_cartao = '6710b2c9e4' WHERE id_evento = 'alerta-2026-10-14-0315-disco';

Com o id do cartão guardado, o próximo alerta do mesmo incidente vira comentário no cartão existente, e não um cartão novo.

Quando alguém sai da equipe ou o token vaza

Tirar a pessoa do quadro não invalida um token que ela gerou para uma automação. Se o token pessoal dela alimentava o script, ele continua funcionando com o acesso que ela ainda tiver em outros lugares. Por isso a conta de serviço importa: a credencial não depende de quem está empregado.

Se o token apareceu num commit, num print ou num chat, revogue primeiro e limpe depois. Gere o novo, atualize o segredo do CI, rode o deploy de teste e só então revogue o antigo nas configurações de aplicativos autorizados da conta. A ordem e o motivo estão em segredo no Git se troca antes de limpar, e o caso parecido de bots está em token de bot não vai no Git.

Erros comuns

  • Chamar a API direto do JavaScript da página: o token fica visível para qualquer visitante, que passa a agir como o dono do token em todos os quadros dele.
  • Usar o token pessoal do líder técnico: a automação ganha acesso a todos os quadros que ele vê e para de funcionar, ou continua funcionando indevidamente, quando ele muda de função.
  • Logar a URL completa no erro: com o token na query, o log vira um cofre aberto que fica guardado por meses e é lido por mais gente que o código.
  • Pedir escopo de conta e validade infinita por preguiça: um vazamento que poderia expirar em 30 dias e ficar restrito a leitura vira acesso permanente de escrita.
  • Criar cartão sem guardar o id do evento: cada reenvio do webhook ou do alerta gera um cartão duplicado e a equipe perde a confiança no quadro.
  • Tratar o cartão movido como entrega feita: a automação mostra que o deploy rodou, não que o problema foi resolvido; o critério de pronto continua sendo humano, como lembra cartão no quadro não é a tarefa concluída.

Checklist

  • A busca por "token" e pela própria key no repositório, incluindo histórico, não encontra nada.
  • Nenhuma chamada à API do quadro sai do navegador.
  • O token pertence a uma conta de serviço que só participa dos quadros necessários.
  • O escopo é o mínimo e a validade não é infinita sem motivo escrito.
  • Key e token vêm de segredo do CI ou de variável de ambiente do servidor.
  • Mensagens de erro e logs mostram status e id do cartão, nunca URL completa ou cabeçalho.
  • Ações que criam cartão consultam uma tabela de eventos já processados.
  • Existe um passo escrito para revogar e trocar o token, e alguém já o executou uma vez.

Abra agora o repositório da automação e procure pela sua API key. Se ela aparecer em algum commit, quem mais teve acesso a esse histórico e o que essa pessoa conseguiria fazer no seu quadro hoje?

Avalie este artigo

Referência: https://developer.atlassian.com/cloud/trello/rest/api-group-actions/