JustCyber News
A notícia de segurança que sai em inglês de manhã chega ao seu blog em português, revisada por gente, no mesmo dia.
A Newsroom é a redação da marca JustCyber — um blog e um Instagram, não um produto por cliente. Um worker faz o poll de 13 fontes públicas declaradas em código: imprensa técnica internacional, imprensa brasileira, alertas do CERT.br, o NVD 2.0 e o catálogo de exploração ativa da CISA. Cada item novo entra deduplicado por hash de URL. Cada item novo entra deduplicado por hash de URL: reprocessar o mesmo feed não cria linha. A mesma matéria republicada em outra URL entra como item próprio, mas é casada pelo hash de conteúdo e marcada como derivada do original. Falha de rede numa fonte é registrada e isolada; o ciclo continua.
A partir de um item curado, o pipeline roda quatro etapas — ranquear, resumir, redigir e escrever a legenda — sempre pelo Gateway de IA da plataforma, nunca chamando o provedor direto. O custo de IA é somado ao longo das quatro etapas e gravado no post como total, ao fim da redação e de novo ao fim da legenda, junto do modelo usado na redação. O detalhe por chamada fica na trilha de uso e de egresso do Gateway, não no post. Antes de o artigo virar rascunho, um detector determinístico mede a fração da fonte reproduzida no texto, por n-gramas de quatro palavras; acima do teto (0,5 por padrão) o post é reprovado com o motivo gravado. A atribuição da fonte com link é anexada por código, não confiada ao modelo.
A IA sugere, a pessoa decide. O pipeline só leva o post até rascunho. Submeter à revisão, aprovar, rejeitar, agendar e publicar são ações humanas, com escopo por ação e chave de idempotência. Publicar emite os eventos de canal no outbox dentro da mesma transação que muda o estado: ou os dois acontecem, ou nenhum. As tabelas news_* vivem no plano de plataforma com RLS forçado, e todo acesso — staff, rota pública e worker — passa pelo pool de plataforma.
Capacidades em operação
Cada item corresponde a funcionalidade que existe no código e é alcançável por um usuário com o escopo correto.
-
Ingestão de 13 fontes com deduplicação por hash
RSS, Atom, NVD 2.0 e CISA KEV, cada fonte declarando peso de curadoria, idioma e trilha editorial no registry — hoje metadado guardado no banco, ainda não usado no ranqueamento: a nota sai do modelo a partir do título, do resumo e dos CVEs. url_hash é único, então reprocessar o mesmo feed não duplica; cross-post é casado por content_hash e marcado como derivado do original. O parser é stdlib: não depende de biblioteca de feed.
-
Pipeline editorial de IA em quatro etapas
Ranqueia (score, severidade, relevância para o Brasil), resume, redige o artigo em português e escreve legenda e carrossel de Instagram. Rank, resumo e redação são essenciais: falha do Gateway marca o post como falho com o motivo. A legenda é enriquecimento: se falhar, o post segue como rascunho sem legenda.
-
Anti-plágio determinístico, com número gravado
Coeficiente de contenção sobre n-gramas de quatro palavras: quanto do TÍTULO E DO RESUMO da fonte — que é tudo o que a plataforma coleta, e tudo o que o modelo recebe — reapareceu no artigo. O corpo da matéria original não é baixado e, portanto, não entra na conta. Dividir pela fonte, e não pela união, pega cópia literal parcial num artigo longo. Acima do teto configurável o post vira falho com motivo 'similaridade alta'. Mesma entrada, mesmo número.
-
Atribuição da fonte garantida por código
Se o modelo não incluiu o link da fonte, o pipeline anexa ao fim do artigo antes de salvar. Não depende de o LLM lembrar da regra.
-
Máquina de estados editorial com revisão humana
submit_review, approve, reject, schedule e publish. Cada aresta é validada e transição inválida devolve conflito, não erro genérico. Aprovar e rejeitar carimbam quem revisou; agendar exige data futura; agendar e publicar exigem que o artigo já tenha slug.
-
Card de marca gerado offline, sem navegador
Imagem 1080x1080 e carrossel de até 10 compostos com Pillow: manchete, kicker com fonte e severidade, data e wordmark, na paleta da marca. Sem rede na composição, sem custo de IA, mesma entrada gera os mesmos bytes. Sobe para o bucket de capas e grava a URL no post.
-
Publicação transacional por outbox
O evento de canal é gravado na mesma transação da mudança de estado. Agendamento vira available_at no evento e o relay despacha na hora certa. Publicação por canal é idempotente por (post, canal): reentrega não republica. Falha de um canal é registrada com erro e não derruba o post.
-
Blog público com ISR e feed sem autenticação
Duas rotas públicas expõem apenas posts com status publicado. O Next revalida a rota a cada 300 segundos e o publicador dispara revalidação sob demanda com segredo compartilhado em header, para o artigo aparecer sem esperar o TTL.
-
Instagram pelo Graph API, fail-closed
Container por imagem, container de carrossel, publish. Só aceita URL HTTPS cujo host seja o do bucket de marca — defesa contra SSRF, porque o Graph busca a imagem a partir da URL que enviamos. Erro do Graph é persistido sanitizado: status e código estruturado, nunca o corpo bruto do upstream.
-
Rotação do token long-lived do Instagram
Rotação do token long-lived do Instagram: um job periódico renova o token junto ao Graph, persiste a nova credencial cifrada com envelope KMS e alerta uma vez por janela antes de expirar — o token em claro nunca vai a log nem ao payload do broker. Limite conhecido: o publicador ainda lê o token da variável de ambiente JC_IG_ACCESS_TOKEN, não da credencial rotacionada. Hoje a rotação serve de trilha e de aviso; trocar o token em uso continua sendo passo manual de operação.
-
Defesa contra injeção de prompt na fonte
O conteúdo da notícia entra numa cerca de dado não confiável e qualquer variante forjável do delimitador (espaços, maiúsculas, fechamento) é neutralizada dentro dos campos da fonte antes de ir ao modelo.
-
Isolamento de plataforma verificado no banco
As tabelas news_* têm FORCE ROW LEVEL SECURITY. Sob o pool de tenant a consulta em news_post aborta em vez de devolver zero linha em silêncio — a migration 0039 trocou o fail-open por fail-closed usando comparação de coluna uuid contra o GUC.
Entregáveis
- Fila editorial em /app/newsroom, com filtro por estado e contagem total real da fila (o COUNT ignora o cursor de paginação, então o total não encolhe a cada página).
- Tela de detalhe do post: artigo, resumo, severidade, CVEs, similaridade com a fonte, modelo usado, custo de IA, motivo de falha e situação por canal. Quem revisou é gravado no banco e devolvido pela API, mas ainda não aparece na tela.
- Artigo em português no blog público /blog/[slug], com resumo, severidade, CVEs e link para a fonte original.
- Card 1080x1080 de marca e carrossel de até 10 imagens no bucket de capas.
- Post no Instagram com legenda e carrossel, quando o canal está configurado.
- Feed público em JSON: /api/v1/newsroom/public/posts e /api/v1/newsroom/public/posts/{slug}.
O que este módulo não faz
Três travas concretas, e é melhor saber antes de contratar. (1) Nenhum código de produção cria linha em news_post: a ingestão grava só news_source_item, e o único INSERT em news_post está em teste e na migration. Sem uma promoção item -> post, a fila editorial nasce vazia mesmo com a ingestão rodando corretamente. (2) O escopo news:post:publish, exigido pelo serviço nas ações schedule e publish, NÃO existe no catálogo de RBAC — o catálogo tem apenas news:post:read, news:post:review e news:source:manage. Nenhum papel pode recebê-lo, então agendar e publicar são inalcançáveis pela API enquanto o escopo não for criado. (3) JC_NEWS_ENABLED é falso por padrão: com a flag desligada, a task de ingestão retorna 'skipped' sem buscar nada. Além disso: não há rota para editar texto — o revisor aprova, rejeita, agenda ou publica o que a IA escreveu, sem corrigir uma palavra pela API. As fontes são fixas em código; news:source:manage apenas dispara um ciclo de ingestão, não faz CRUD de fonte. É um único blog e um único Instagram da marca JustCyber: não é multi-tenant, não existe newsroom por cliente. O Instagram recusa fail-closed sem credencial completa ou sem imagem hospedada no host do bucket configurado. Não há métricas de audiência, ferramenta de SEO, newsletter, LinkedIn, X nem agendamento recorrente.
Declaramos o limite porque software de segurança que promete tudo não é auditável. Se o que falta aqui é o que você precisa, o serviço consultivo cobre — ou dizemos que não cobre.
Conecta com
- Gateway de IA da plataforma, com trilha de uso e de egresso por chamada
- Outbox transacional e relay Celery (fila dedicada newsroom)
- Blog Next.js com ISR e rota de revalidação assinada por segredo compartilhado
- Instagram Graph API v21 (container, carrossel, publish)
- Bucket S3-compatível para as capas de marca
- RBAC de staff da plataforma (escopos negados a papéis de tenant)
Controle de acesso
O acesso é concedido por escopo, não por perfil genérico. Quem só precisa ler não recebe permissão de escrita, e a barreira é o banco de dados, não a interface.
- news:post:read
- news:post:review
- news:source:manage
Quer ver funcionando?
Demonstração com dado do seu ambiente, não com base de exemplo. É a única forma de saber se serve.