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
- 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.
- Gere a API key no painel de desenvolvedor do Trello, logado com a conta de serviço.
- Autorize com escopo e validade definidos. A tela de autorização aceita parâmetros como
scopeeexpiration. Peçaread,writesó se a automação escreve, e eviteneverquando der para renovar periodicamente. - Guarde key e token como segredos do CI, nunca num arquivo
.envcommitado. - 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?
Referência: https://developer.atlassian.com/cloud/trello/rest/api-group-actions/