const { djb2Hash } = require('./hash'); // Hash estavel do texto exato que seria enviado -- usado como parte da chave de // idempotencia (junto com report_date/run_type). Duas mensagens com o mesmo conteudo no // mesmo dia nunca devem gerar dois envios reais. function computeMessageHash(text) { return djb2Hash(String(text || '')); } // SEND_ENABLED e o gate principal de "isso pode realmente sair pro Slack" -- nunca depende de // editar codigo (missao "finalizacao para producao", secao 22). Runs 'manual' tem uma segunda // trava: mesmo com SEND_ENABLED=true (producao), clicar "Execute Workflow" NAO envia de // verdade a menos que FORCE_SEND tambem esteja ligado -- protege contra envio acidental por // alguem testando/depurando em producao (missao "correcao final", secao 16/17). function shouldSendByConfig(config, runType) { if (!config || !config.sendEnabled) return false; if (runType === 'manual' && !config.forceSend) return false; return true; } // Idempotencia: so conta como "ja enviado" um registro com status 'success' para a MESMA // data + tipo de execucao + hash de mensagem. Um retry apos falha (status 'failed') nao // bloqueia um novo envio -- so um sucesso anterior bloqueia. function alreadySentSuccessfully(existingRecords, { reportDate, runType, messageHash }) { return (existingRecords || []).some((record) => ( record && record.status === 'success' && record.report_date === reportDate && record.run_type === runType && record.message_hash === messageHash )); } // Decisao unica de "devo mandar pro Slack agora" -- centraliza os dois motivos possiveis de // NAO enviar (SEND_ENABLED=false, ou ja enviado com sucesso hoje) num so lugar auditavel. function evaluateSendGuard({ config, existingRecords, reportDate, runType, messageHash }) { if (!shouldSendByConfig(config, runType)) { const reason = runType === 'manual' && config && config.sendEnabled ? 'manual_run_needs_force_send' : 'send_disabled'; return { shouldSend: false, reason }; } if (alreadySentSuccessfully(existingRecords, { reportDate, runType, messageHash })) { return { shouldSend: false, reason: 'already_sent' }; } return { shouldSend: true, reason: 'ok' }; } function buildEnvioDigestRecord({ reportDate, runType, messageHash, sentAt, status, errorDetail }) { return { report_date: reportDate, run_type: runType, message_hash: messageHash, sent_at: sentAt, status, error_detail: errorDetail || null, }; } module.exports = { computeMessageHash, shouldSendByConfig, alreadySentSuccessfully, evaluateSendGuard, buildEnvioDigestRecord, };