JustCyber

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.

O que faz hoje

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.

O que fica com você

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
JustCyber News

Quer ver funcionando?

Demonstração com dado do seu ambiente, não com base de exemplo. É a única forma de saber se serve.