Feito com Chinaski

Changelog

Toda release com tag, da mais nova para a mais antiga. As notas são publicadas por release, em seu próprio conteúdo; veja os links de Full-changelog para os diffs de origem.

v1.11.0

2026-09-25

Minor release: o Chinaski agora pode funcionar inteiramente em um telefone Android, publicando para o Cloudflare R2, além de um novo block schedule para horários recorrentes e exceções com data.

Novidades

  • #255 (#7365): novo caminho de instalação baseado em Termux (install.sh --termux) que executa o admin completo (build, banco de dados, tudo) em um telefone Android sem root e sem systemd, mais um launcher de boot/widget idempotente (termux-start.sh) para que ele sobreviva ao fechamento e reinicie sozinho após uma reinicialização do telefone. Veja Publicando de um telefone.
  • #255: nova chave mestra deploy_auto_enabled em Settings → Deploy que coloca o deploy rsync e o deploy S3 atrás de um único toggle “Deploy automatically after a successful build”, de modo que um ou ambos os alvos podem ser ligados sem mudar silenciosamente o comportamento existente. Veja Implantação por SSH / rsync.
  • #255: novo tipo de block schedule. Um cronograma semanal recorrente (horários de culto, horários de funcionamento) mais uma lista de exceções com data futuras (fechamentos, eventos pontuais, cancelamentos), com dados estruturados schema.org Event automáticos. Veja Horários.
  • #255: o banner de status de build/deploy do admin agora caminha de “Building your update…” para “Publishing your update…” e daí para “Your update is live”, permanecendo preciso por todo o tempo em que uma sincronização estiver genuinamente executando, inclusive um upload lento por uma conexão de telefone.

Notas de atualização

Nenhum passo manual é necessário. Se o deploy SSH/rsync ou S3 já estava configurado e funcionando, a nova chave mestra deploy_auto_enabled é preenchida como ligada automaticamente durante a atualização, de modo que os deploys existentes continuam disparando sem nenhuma ação necessária.

v1.10.4

2026-09-23

Patch release: uma auditoria de responsividade mobile do tema padrão em todos os 32 tipos de block, além de vários bugs antigos descobertos pelo caminho.

Corrigido

  • #253: passagem completa de responsividade mobile no tema padrão. Os tipos de block text e grid não tinham nenhum CSS; o grid usava um grid-template-columns inline que não podia ser sobrescrito por uma media query mobile e agora usa propriedades customizadas de CSS. Corrigida uma divergência de nome de classe entre template e CSS que deixava os títulos dos blocks columns e grid sem estilo. O <pre> do code_block não tinha tratamento de overflow, então uma linha longa alargava a página inteira no mobile em vez de rolar dentro do block. Adicionado o estilo que faltava para heroes de dois botões e para a variante secundária de grupo de botões. Corrigido um overflow real do header em torno de 1024px de largura de viewport (entre o breakpoint mobile e a linha de navegação desktop presumidamente larga), que uma navegação realista dispara. O block de depoimento agora empilha abaixo de 480px em vez de espremer o avatar e a citação numa linha de largura fixa. O padding dos botões foi aumentado em todo o site para que as áreas de toque superem a diretriz de acessibilidade de ~44px.
  • #254: o manifest de build assinado do build.pl (private/build-manifest.json) era resolvido a partir do diretório de instalação do próprio script em vez de seguir CHINASKI_OUTPUT, então redirecionar a saída do build para outro lugar (por exemplo, um build de teste ou em sandbox) gravava silenciosamente o manifest no diretório private/ da instância ativa. Agora segue a localização do diretório de saída, sem nenhum efeito em qualquer deployment normal.
  • #254: btn_submissions e outras 30 strings do painel admin eram referenciadas por templates mas nunca definidas em nenhum idioma, então os admins viam o texto cru da chave (por exemplo “hdr_status”) em vez de rótulos reais. Encontradas por uma varredura completa de toda chamada t('...') contra as chaves realmente definidas. Adicionadas aos 4 idiomas.
  • #254: a variante de largura block-form__field--w-half / newsletter-form__field--w-half, oferecida no editor de campos de formulário, não tinha nenhum CSS: “half width” não fazia nada. Agora os campos ficam dois por linha no desktop, empilhando abaixo de 640px.
  • #254: builder/site_templates/_landing_block_styles.tt (usado pelo template independente landing.tt) estilizava apenas 15 dos 32 tipos de block. Os outros 17 eram renderizados completamente sem estilo nas landing pages; portado da correção de tema acima.

Notas de atualização

Nenhuma migração de banco de dados é necessária nesta release.

v1.10.3

2026-09-21

Patch release: correção de i18n no breadcrumb e no título do page_list.

Corrigido

  • #7290: o crumb raiz do breadcrumb estava fixo na string literal em inglês “Home”, independentemente do idioma real da página. Agora usa o título real, por idioma, da página inicial do site, recorrendo a “Home” apenas quando não existe nenhum para esse idioma.
  • #7291: o título “Also in X” gerado automaticamente pelo block page_list estava fixo em inglês. Agora usa uma tabela de prefixos por idioma (en/es/pt/fr).

Ambos já haviam sido corrigidos e verificados em produção neste site antes de esta release formalizar a correção no código, com cobertura de testes.

Notas de atualização

Nenhuma migração de banco de dados nem mudança de configuração é necessária nesta release.

v1.10.2

2026-09-21

Patch release: correções de escape de shortcodes e da verificação de links quebrados, além de duas novas configurações expostas no admin.

Corrigido

  • #7212: os expansores de shortcode ([form:slug​], {{block:name​}}, {{stack:name​}}, {{document:slug​}}) não expandem mais dentro de <pre>/<code>. Uma página de docs que mostra a sintaxe como exemplo literal não dispara mais um erro de renderização nem bloqueia a promoção.
  • #7215: _detect_broken_links não antepõe mais em duplicidade o diretório de idioma a hrefs que já carregam um prefixo do idioma ativo com lang_url_mode=path, o que vinha gerando falsos positivos em todo link interno corretamente escrito num site multilíngue em modo path.

Adicionado

  • #7214: campo org_email adicionado em Settings > Organization, ao lado de org_phone. O encanamento de JSON-LD no lado do builder já existia, mas não havia campo na UI do admin para defini-lo.
  • #6018: build_jobs (workers de build em paralelo) exposto em Settings > General, antes configurável apenas por SQL direto ou pela variável de ambiente CHINASKI_JOBS. Em branco preserva o comportamento existente de detectar automaticamente o número de CPUs.

Notas de atualização

Nenhuma migração de banco de dados nem mudança de configuração é necessária nesta release.

v1.10.1

2026-09-17

Patch release: correções nas units systemd de deploy/, sem mudanças no app nem no banco de dados.

Corrigido

  • #247: StartLimitIntervalSec/StartLimitBurst estavam em [Service] nos templates systemd por instância (chinaski@.service, chinaski-mcp@.service), onde o systemd os ignora silenciosamente. Movidos para [Unit], onde de fato são respeitados. Sem esta correção, uma instância que falha de forma persistente (por exemplo, uma cujo diretório de trabalho foi excluído) reinicia para sempre em vez de desistir após 5 falhas em 60s e ficar em failed.
  • #248: o chinaski-backup@.timer tinha um comentário inline ao final de Persistent=true (Persistent=true # catch up...), que o parser de units do systemd não consegue tratar: ele falhava ao interpretar o valor e o descartava silenciosamente, então um backup diário perdido enquanto o host estava desligado nunca era recuperado no boot. Comentário movido para a própria linha.

Notas de atualização

Instalações existentes: copie novamente os três arquivos de deploy/ (chinaski@.service, chinaski-mcp@.service, chinaski-backup@.timer) para /etc/systemd/system/ e execute systemctl daemon-reload. Nenhuma migração de banco de dados nesta release.

v1.10.0

2026-09-16

Minor release. Quatro correções de bugs desde a v1.9.0.

Correções

  • Forms: campos do tipo date nunca eram validados no servidor: um POST direto contornando o seletor de datas do navegador deixava passar sem filtro uma entrada malformada, ou até markup/links de spam, em um campo de data. Agora são validados como YYYY-MM-DD.
  • Settings: a regeneração do favicon falhava silenciosamente em atualizar o favicon.svg num novo upload se o arquivo tivesse o dono errado (por exemplo, de um deploy que não refez o chown), enquanto as variantes PNG/ICO eram atualizadas normalmente e a UI relatava sucesso. O favicon.svg agora é removido (unlink) antes de ser reescrito, igual ao tratamento já existente para PNG.
  • Builder: o sitemap nunca emitia a raiz simples do site quando home_redirect apontava para uma página comum em vez do blog; e URLs relativas de og:image/twitter:image (inválidas segundo a especificação OG) agora são tornadas absolutas em páginas, posts e no índice do blog.
  • Breadcrumbs: o crumb do blog estava fixo na palavra literal “Blog” em vez de usar o blog_index_title configurado no site: instâncias com um rótulo de blog ou prefixo de permalink personalizado (por exemplo “Notes” em /notes/) recebiam uma trilha de breadcrumb que não combinava com a nomenclatura da própria navegação/URL.

Suíte completa: 122 arquivos, 9.687 testes, todos passando.

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.9.0…v1.10.0

v1.9.0

2026-08-31

Minor release: um importador de arquivos Markdown permite criar posts/páginas em rascunho diretamente de arquivos .md (com YAML front matter), além de um lote de 8 bugs reportados em produção corrigidos em Posts/Pages do admin, na montagem de permalinks/links e no tratamento de favicon.

✨ Funcionalidades e UX

Importador de arquivos Markdown para Posts e Pages (PR #242) - Uma nova rota /admin/import-markdown, com link a partir das listas de Posts e de Pages, aceita um único arquivo ou um lote de até 100 arquivos .md (40 MiB no total) e cria posts/páginas em rascunho a partir deles, substituindo a solução improvisada anterior de escrever HTML à mão diretamente no banco de dados. - YAML front matter opcional (title, slug, language, meta_title, meta_description, category, tags, date) preenche os campos; valores ausentes recorrem ao primeiro título H1 do arquivo e depois a um nome de arquivo formatado. - Toda importação entra como rascunho: nunca publica automaticamente e nunca mexe no agendamento de publicação, por decisão explícita de design. - O isolamento de erros por arquivo reporta arquivos ruins pelo nome sem fazer o resto do lote falhar.

🐛 Correções

Lote de bugs do admin de Posts: 8 problemas reportados em produção (PR #241) - Restaurar um rascunho (Posts e Pages) não salvava nada silenciosamente: o corpo da requisição não estava sendo lido corretamente, e um bug de seletor de formulário também mirava o <form> errado na página de edição de Posts. - Os links “View” do admin e o seletor interno de links montavam URLs de posts/páginas de forma incorreta para páginas aninhadas e configurações de permalink/idioma não padrão, divergindo do que o builder do site realmente publica. - Aprovar um post ou página pendente (workflow de revisão) nunca o colocava de fato no ar: mudava o status de revisão, mas não o flag de publicação. - O conteúdo do editor acumulava espaços em branco perdidos e deriva de formatação a cada ciclo de salvamento; agora é normalizado no servidor. - Publicar um post podia disparar um aviso espúrio do navegador de “changes not saved” que abortava a requisição. - Um bug real de permissão no upload de favicon em produção (arquivos com dono root após o deploy) podia quebrar silenciosamente as atualizações de favicon e os rebuilds do site. - Um placeholder ausente no template do block hero quando nenhuma imagem está definida

⬆️ Atualização

Nenhum passo manual. Todas as mudanças de schema/configuração desta release são aplicadas automaticamente no próximo boot.

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.8.0…v1.9.0

v1.8.0

2026-08-27

Minor release: os formulários ganham campos condicionais, rastreamento de lido/não lido e um link de resposta; a série de modularização termina com Forms e Blocks extraídos para seus próprios plugins; webhooks, jobs, navegação, redirecionamentos, tratamento de datetime/MIME e e-mail/SMTP passam por refatorações centralizadas guiadas por auditoria; além de um lote de correções de bugs reais, incluindo um bug de favicon/rebuild em produção, uma violação de FK na restauração de revisões e várias lacunas em verificações de permissão do admin.

✨ Funcionalidades e UX

Forms: campos condicionais, rastreamento de não lidos, link de resposta (PR #229) - condition_field agora é um dropdown com os campos já existentes do formulário (chega de nomes de campo digitados livremente), com validação no servidor e sugestões de valor via datalist para origens select/radio/checkbox. - As submissões rastreiam o estado lido/não lido: linhas não lidas ganham um badge “new”, a lista de formulários mostra “12 (3 new)” e há um “Mark all read” em um clique. - Um botão “Reply” no detalhe da submissão abre um link mailto: já endereçado quando reply_to_field aponta para um campo com aparência de e-mail.

🔧 Refatorações

Forms e Blocks extraídos para seus próprios plugins, encerrando a série de modularização (PR #221, PR #240) - lib/Chinaski/Plugin/Forms.pm e lib/Chinaski/Plugin/Blocks.pm agora são donos de toda a superfície de rotas de forms e de blocks/snippets/stacks, seguindo o padrão já estabelecido de Plugin::Media/Plugin::Settings; só a mudança de Forms reduz o cms.pl em quase 2.000 linhas. - Em Blocks, adicionalmente: create/update agora usam validação com coleta de erros e renderização de formulário compartilhada (igual a pages/posts), a tabela block_types do banco vira a única fonte da verdade em vez de um array paralelo @BLOCK_TYPES, e um partial compartilhado de seletor de cor substitui o equivalente a 21 templates de seletores duplicados.

Ordenação de redirecionamentos, navegação e formulários centralizada (PR #230, PR #231) - A lógica de create/update/importação CSV/percurso de cadeia de redirecionamentos foi consolidada em helpers compartilhados; a importação CSV agora usa o mesmo parser RFC-4180 do resto do sistema em vez de um split feito à mão. - _swap_sort_order e _next_sort_order agora são compartilhados entre navegação, snippets e campos de formulário em vez de três implementações separadas; a validação de create/edit da navegação foi centralizada (~85 linhas removidas).

Webhooks, jobs agendados e relatórios de saúde centralizados (PR #235, PR #236, PR #237) - Publicação/despublicação agendada, jobs recorrentes em segundo plano e resumos de saúde de backup foram deduplicados entre seus consumidores de admin e de API. - O despacho de retry de webhooks, a validação de URL e o wrapper de job em segundo plano da restauração de backup foram centralizados; os hooks before_dispatch foram reorganizados em estágios nomeados; helpers de status de build/uso de disco são compartilhados entre o dashboard, o health e os endpoints de API.

Datetime e MIME unificados; higiene de e-mail/SMTP e migrações (PR #238, PR #239) - Um único par de helpers compartilhados de conversão local↔UTC substitui laços repetidos por rota; um novo módulo Chinaski::MIME é a fonte canônica do mapeamento MIME↔extensão em mídia, formulários e entrega de documentos. - A configuração de conexão SMTP (incluindo a correção de CRLF que fecha a injeção de cabeçalhos) foi consolidada em um único remetente; a documentação de migrações e os helpers de verificação de existência foram limpos; 22 novas chaves de i18n x 4 idiomas fecham as strings de admin que restavam fixas no código.

🐛 Correções

Excluir o favicon não disparava um rebuild (PR #223): excluir um favicon limpava a configuração, mas deixava o ícone antigo no ar em output/ (e portanto no site público) até que uma mudança não relacionada disparasse o próximo build. Encontrado em produção na instância roiwire (defasado por ~1h44m).

O upload de favicon estragava imagens-fonte não quadradas (PR #225): uma imagem-fonte larga/baixa (por exemplo, um logo wordmark) produzia silenciosamente um recorte embaralhado em vez de um ícone; uploads com mais de 1,25:1 fora do quadrado agora são rejeitados com um erro claro.

A restauração de revisão de block sempre falhava para blocks comuns (PR #222): a restauração gravava '' em vez de NULL para form_id/content_json, violando as constraints de FK/CHECK em qualquer block que não fosse de formulário nem estrutural.

A decodificação JSON do diff de revisões usava o decodificador errado em um de dois casos (auditoria do PR #224 + correção do PR #232): decompress_value retorna bytes crus para linhas comprimidas, mas uma string já decodificada para as não comprimidas; um único decodificador JSON genérico estava errado em um dos casos, qualquer que fosse o escolhido. Dois pontos de chamada (preview de revisão de snippets, diff genérico de pages/posts) reintroduziram isso logo depois de a primeira auditoria corrigi-lo em outro lugar; agora ambos ramificam em utf8::is_utf8 no momento da decodificação.

O Turnstile mostrava uma falsa nota “could not be loaded” sob um widget funcionando (PR #227).

A suíte de testes vazava sidecars .db-wal/.db-shm e diretórios de docs por execução, enchendo o disco da máquina de CI duas vezes (PR #234): adicionada a limpeza adequada, além de uma rede de segurança em cron para processos de teste encerrados à força.

O lote de caça a bugs do admin desta sessão (7 correções, sem números de ticket, encontradas por auditoria direta do código e não pelo backlog): - Os links “View” da página de busca resolviam contra o subdomínio do admin em vez do site ativo (sempre davam 404) e não levavam em conta os slugs pais de páginas aninhadas. - Criar/atualizar/excluir/operações em massa de redirecionamentos não tinham nenhuma verificação de permissão de entidade: qualquer editor com qualquer outra permissão podia gerenciar redirecionamentos, independentemente do que de fato lhe foi concedido. - O publish de Documents não checava o status da versão no servidor, permitindo que um não-admin forçasse no ar uma versão rejeitada, embora a UI já ocultasse essa opção; duplicate/delete estavam sem qualquer verificação de permissão. - O create de Snippets perdia o código enviado, mostrando uma página de erro genérica numa colisão de nome, em vez do re-render amigável que o update já tinha. - O delete de Themes não verificava se o tema existia no banco antes de remover seu diretório em disco. - O create de Users não aplicava o formato de nome de usuário que a importação CSV já exige. - O update de Nav zerava silenciosamente o sort_order quando o campo era omitido da requisição, em vez de preservar a posição do item.

⬆️ Atualização

Nenhum passo manual. A migração 061 (form_submissions.read_at) e todas as outras mudanças de schema desta release são aplicadas automaticamente pelo caminho normal de migração no próximo boot.

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.7.1…v1.8.0

v1.7.1

2026-07-22

Patch release: os formulários ganham tipos de schema JSON-LD amigáveis a SEO, três novos tipos de campo (date, regras de validação, checkbox de consentimento), uma UI de admin mais densa e acessível, e uma correção de bug real de produção na edição de páginas/posts.

✨ Funcionalidades e UX

Tipos de schema JSON-LD: Article, FAQ, Product, Event, HowTo (#2559, PR #216) - schema_type opcional em páginas e posts: escolha FAQ, Product, Event ou HowTo (posts ficam limitados a Article/FAQ, pois posts não têm os campos de produto/evento que sustentariam os demais) e o builder emite os dados estruturados correspondentes automaticamente. - Novos editores de perguntas/respostas de FAQ e de passos de HowTo no formulário de página.

Forms: tipo de campo date, validação por campo, checkbox de consentimento (PR #218) - Novo tipo de campo date, renderizado como um <input type="date"> nativo. - Regras de validação por campo (comprimento mínimo/máximo, valor mínimo/máximo e padrão regex) aplicadas tanto no cliente (atributos HTML5) quanto no servidor ao enviar. - Novo tipo de checkbox consent para reconhecimento da política de privacidade, com um link configurável que abre em nova aba.

Admin de Forms: aba de configurações mais densa e lista de campos mais acessível (PR #217) - A aba Form Settings agora tem seções recolhíveis em vez de uma longa rolagem, com uma barra Save fixa. - A lista de Fields mostra tipo/obrigatório como badges, tem áreas de toque maiores, e os botões de reordenar são corretamente desabilitados no topo/fim da lista, com rotulagem ARIA completa.

🔧 Refatorações

Configurações de PWA e lista de assets centralizadas (PR #215) - O builder e o caminho de exclusão de favicon em Settings agora compartilham uma única fonte da verdade para os nomes de arquivo dos assets de PWA gerados, em vez de duas listas que podiam divergir silenciosamente.

🐛 Correções

Atualizações de páginas e posts podiam falhar com “no such table: main.*_old” (PR #214) - Uma referência remanescente de uma migração antiga fazia com que page_snippets, post_snippets, page_area_blocks e outras 3 tabelas de junção pudessem apontar para tabelas que não existiam mais, quebrando as atualizações de páginas/posts existentes (criar novos ainda funcionava) em qualquer instância em execução desde aproximadamente a v1.6.1 ou anterior.

Polimento do admin de Forms (PRs #212, #213) - Editar um campo de formulário não te joga mais de volta para a aba Settings. - Os erros de validação de Add Field não apagam mais o que você havia digitado. - Foi adicionado um aviso de alterações não salvas na aba Settings. - O diálogo de confirmação de exclusão na lista de formulários agora diz corretamente “moved to trash” em vez de sugerir exclusão permanente. - Falhas de SMTP agora registram um motivo específico em vez de um erro genérico. - Um upload de tema corrompido agora relata “corrupt archive” em vez do enganoso “missing required files”.

⬆️ Atualização

Nenhum passo manual. Se você está rodando uma instância anterior a esta release, a correção de atualização de página/post (PR #214) é aplicada automaticamente pelo caminho normal de migração no próximo boot.

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.7.0…v1.7.1

v1.7.0

2026-07-22

Minor release: backup/restore extraído para seu próprio plugin, Backups e API Keys promovidos a páginas de verdade, e as telas de admin de Posts concluem sua migração para o design system.

✨ Funcionalidades e UX

Backups e API Keys agora são páginas de verdade, não abas de settings (PR #209) - /admin/backups e /admin/api-keys são rotas canônicas com suas próprias URLs; os links antigos /admin/settings?tab=backups / ?tab=api-keys agora dão 302 para elas. - O template de settings de 1.796 linhas foi dividido em partials por aba (templates/admin/settings/_*.html.ep) em vez de um monólito; 344 atributos style= inline foram extraídos para classes CSS compartilhadas.

🔧 Refatorações

Backup/restore extraído para Chinaski::Plugin::Backups (PR #208) - Todas as 10 rotas /admin/backups/**, 3 rotas /api/backups** e ~30 helpers de apoio saíram do cms.pl para seu próprio plugin, seguindo o mesmo padrão das extrações anteriores de Media/Settings. - O tratamento de criação de backup e de resultado de restauração agora é compartilhado entre as rotas de admin e de API, em vez de cada uma duplicar sua própria lógica.

As telas de admin de Posts concluem a migração do design system po-* → chinaski-* (PR #210) - Declarações font-family inline e literais de cor fora dos tokens foram removidos dos templates de formulário/lista, lixeira e diff de revisão de Posts.

🐛 Correções

  • Uma condição de corrida no timeout de restauração de 120s, em que o resultado tardio de um subprocesso podia ser aplicado silenciosamente depois de a requisição já ter mostrado ao usuário um erro de “timed out”.

⬆️ Atualização

Nenhum passo manual. Se você tem /admin/settings?tab=backups ou ?tab=api-keys nos favoritos ou com link em algum lugar fora do app, atualize para /admin/backups / /admin/api-keys (os links antigos ainda funcionam via redirecionamento, só com um salto a mais).

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.6.1…v1.7.0

v1.6.1

2026-07-06

Patch release: corrige a dependência Crypt::PBKDF2 ausente.

  • O cms.pl usa o Crypt::PBKDF2 diretamente para a migração de hash de senha, mas ele nunca foi declarado no cpanfile, então qualquer instância 1.6.0 que ainda não tivesse o módulo instalado entrava em crash-loop na inicialização (Can’t locate Crypt/PBKDF2.pm in @INC). Corrigido declarando a dependência no cpanfile.

v1.6.0

2026-07-06

Minor release: tudo o que foi mesclado desde a v1.5.3.

  • Reforço de backup: manifest.json com SHA-256 por arquivo em todo arquivo compactado, PRAGMA integrity_check antes de arquivar, publicação local atômica, validação de caminho de restauração nas 4 origens, verificação pós-backup (backup_runs) com badges Verified, retenção configurável com poda, métricas de backup em /admin/metrics, preview de restauração em dry-run + confirmação, tipo/schema por linha na aba Backups, ponte de data-loading-text para formulários.
  • Builder: as páginas expõem suas páginas filhas publicadas aos templates como ‘children’; o page_list compartilha o mesmo mapa pré-calculado.
  • Editor de posts: WYSIWYG restaurado na página de novo post (SyntaxError de JS na chave de autosave), paridade completa de design system em dois painéis com Pages, botões de revisão via formaction.
  • O preview compartilhável de página renderiza blocks guiados por content_json (faq, pricing_table, …) em vez de apenas o título.
  • MCP: gerenciador de processos, health, log de retry, sessões, descoberta, operações em massa, resources.
  • Segurança: uploads de mídia SVG rejeitados; hash de senha de posts.
  • Refatorações: despacho de webhooks unificado em Chinaski::Webhook; biblioteca de mídia extraída para Chinaski::Plugin::Media.

Todos os quatro PRs de features passaram por code review antes do merge; as correções da revisão estão nos commits squashed dos PRs. Suíte completa verde no CI para a árvore final mesclada.

v1.5.3

2026-07-03

Landing pages, formulários e uma passagem de reforço de segurança, além de um lote de limpeza de integridade de dados/velocidade de build.

✨ Funcionalidades e UX

Landing pages sem tema - Novo template raw.tt: o admin escreve um documento HTML completo como corpo da página, sem wrapper de header/footer/CSS do site, para landing pages que não devem carregar a marca do site. Os shortcodes {{block:...}} continuam sendo resolvidos. - Novo landing.tt: a mesma postura sem marca, mas com uma folha de estilo padrão autocontida cobrindo todos os 15 tipos de block, de modo que blocks de hero/CTA/stat etc. renderizam com um estilo razoável sem CSS escrito à mão. - O dropdown de template agora lista também os templates fornecidos pelo tema e preserva o template de uma página numa troca de tema, em vez de corrompê-lo silenciosamente para a primeira opção em ordem alfabética. - A aplicação do password gate agora verifica se o template resolvido de fato implementa o gate (e não apenas o nome de arquivo raw.tt), fechando um bypass em que qualquer template sem gate podia entregar conteúdo protegido por senha sem nenhuma UI de gate. - O bulk-create ganhou um seletor de template e um body_template compartilhado com mail-merge de {{title}}/{{slug}}, para que N páginas de um mesmo design possam ter títulos distintos sem editar cada uma à mão.

Forms - Captura de atribuição de marketing: parâmetros UTM, click IDs (gclid/fbclid/msclkid/ttclid) e a URL completa da landing page são extraídos do header Referer e armazenados na submissão, respeitando DNT/GPC. Lista de submissões reformulada (filtros de origem/campanha, badge de origem derivado) e uma nova tela de detalhe de submissão única. - Submit-gate do Turnstile: um remetente rápido não recebe mais um falso “Bot verification failed”; o envio fica retido até o widget emitir um token e depois é reenviado automaticamente. - Pré-preenchimento de campos públicos de formulário a partir de parâmetros de query da URL, cobrindo campos text/email/checkbox/checkboxes/address. - Conteúdo de corpo distinto por item no bulk-create via items_input: cole blocos repetidos de título/corpo em vez de um único template compartilhado para todos os itens. - Histórico de revisões de formulário: cada salvamento de settings/campos tira um snapshot da versão anterior; veja uma lista de revisões, compare com a atual (diff) e restaure. - Armazenamento normalizado de submissões: as respostas das submissões agora são gravadas em uma tabela consultável submission_values (além do blob legado, por compatibilidade), mais um tipo de campo number. - Cotas de upload por formulário e armazenamento privado: limite o tamanho total de upload por formulário e, opcionalmente, armazene os arquivos enviados fora do diretório público, com uma rota de download exclusiva para admin.

Posts e pages - Os area blocks (hero/CTA/stat) agora renderizam em posts, não apenas em páginas: eram coletados silenciosamente, mas nunca passados ao template de post. - Seletor de ponto focal da imagem destacada: um seletor visual X/Y persistido por página/post, aplicado via object-position na marcação de imagem responsiva.

Ferramental de build - Seeder de fixtures de benchmark + instrumentação permanente de tempo por fase no builder, estabelecendo a linha de base contra a qual o restante da série de velocidade de build será medido.

🔒 Segurança

Mensagens de bloqueio, headers e limitação de caminhos de abuso - As mensagens de bloqueio com tempo de espera exato foram substituídas por uma mensagem genérica em login/forgot-password/conta suspensa, fechando um vazamento de informação. - Header Permissions-Policy adicionado, restringindo recursos do navegador que este CMS nunca usa. - Entradas Disallow isca no robots.txt apontando para caminhos honeypot monitorados. - Atraso tarpit em falhas de login, submissões de formulário com limite de taxa e acessos ao honeypot: não bloqueante, para que o tráfego legítimo não seja retido enquanto um atacante gasta tempo de relógio.

Fingerprinting do servidor, abuso de registro, logs forenses - O header de resposta Server: Mojolicious (Perl) foi suprimido. - Limitação de taxa por IP em /register (toda tentativa falha conta, não apenas username-taken/falha de DB, fechando uma lacuna em que submissões malformadas podiam inundar o endpoint sem nunca acionar o bloqueio), além de uma verificação de existência de username em tempo constante. - Eventos de segurança de alto sinal agora também são enviados a um log externo somente de acréscimo (permissões 0600), de modo que o registro forense sobreviva a um comprometimento do banco SQLite. - Endpoints honeypot (/wp-login.php, /.env, /phpmyadmin etc.) identificam scanners automatizados. Alcance no site público: a config de exemplo do Caddy (deploy/chinaski.Caddyfile.example) agora também faz proxy desses caminhos para o app nos vhosts públicos, não apenas em admin.*; um deploy de produção que usa a config Caddy ativa precisará aplicar o bloco de proxy equivalente manualmente (veja Atualização).

🐛 Correções e reforço

  • Integridade de dados / escala (Phase 40): blocks/globals.content_json agora são validados como JSON no momento da escrita (UI, API, importações) com uma constraint CHECK correspondente no SQLite; build_log limitado a 1000 linhas; consultas ilimitadas de ancestrais de página foram limitadas com LIMIT; a renumeração de sort-order de nav_items foi corrigida; o script de backup agora faz checkpoint do WAL e vacuum.
  • Lote de quick wins: CRLF removido dos rótulos de campo antes de chegarem aos corpos de e-mails de notificação (fecha uma lacuna de falsificação do corpo do e-mail); removido o fallback falsificável de X-Country-Code no geo-blocking; corrigido o pré-preenchimento após falha de validação para campos address e checkbox de múltiplos valores; os tokens de referência de submissão agora são um valor CSPRNG aleatório em vez de um reversível/enumerável.
  • SRI/cache: as URLs de CSS do admin agora têm cache-busting por hash de conteúdo, e o hash de integrity frágil da tag de script do Turnstile (que a Cloudflare rotaciona sem aviso) foi removido.
  • i18n: as strings de tradução do admin foram extraídas do cms.pl para Chinaski::I18n, sem mudança de comportamento.
  • Lista de Posts: um crash no filtro do lado do cliente (lançado por uma linha de header/fila sem os atributos data que o seletor presumia) que quebrava a filtragem de todas as linhas sempre que existia um post agendado, agora alcançável por filtros restaurados via URL.
  • CI: corrigida uma falha intermitente do teste documents_module causada por um caminho de arquivo compartilhado /tmp/private entre execuções de teste concorrentes como root/sem privilégios no mesmo host de CI.
  • Passagens de revisão pós-merge no trabalho de landing pages e formulários acima encontraram e corrigiram vários bugs reais antes/depois do merge, incluindo: um bug de reinterpolação de mail-merge e uma lacuna de escape de atributo (attribute breakout) no bulk-create; um vazamento de arquivo enviado e uma condição de corrida TOCTOU na aplicação da cota de upload; um vazamento da poda automática por retenção que nunca liberava cota; snapshots de revisão sendo registrados mesmo quando o salvamento que os precedia falhava; um falso positivo na visualização de diff após a restauração; um erro de digitação que quebrava a renderização de campos address na página de detalhe da submissão; uma migração de valores de submissão não transacional/não idempotente; e uma regressão de Permissions-Policy que quebrava o fullscreen de vídeo incorporado nas rotas de preview.

⬆️ Atualização

Nenhum passo manual de banco de dados: as mudanças de schema são aplicadas automaticamente e de forma idempotente na inicialização; bancos mais antigos são atualizados no local.

Um passo manual se você está usando o exemplo de Caddy fornecido como ponto de partida para sua própria config: o bloco de proxy de caminhos honeypot adicionado a deploy/chinaski.Caddyfile.example precisa ser copiado para sua config Caddy ativa e aplicado (docker restart caddy ou equivalente) para que as sondagens de scanners contra o site público cheguem ao logging/tarpit do app; o arquivo de exemplo deste repositório foi atualizado, mas o Caddyfile de um deploy ativo é mantido separadamente e não é tocado por esta release.

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.5.2…v1.5.3

v1.5.2

2026-06-30

Correções

  • Exclusão em massa de submissões: every_param('ids') retorna um arrayref; a falta da desreferência @{} fazia com que o array nunca fosse desempacotado e zero linhas fossem excluídas em toda tentativa de exclusão em massa.

v1.5.1

2026-06-30

Correções de bugs

  • fix(forms): SMTP LOGIN auth without Authen::SASL: Net::SMTP->auth exige o Authen::SASL, que não está instalado; substituído por uma troca manual de AUTH LOGIN tanto em _send_form_email quanto em _send_admin_email. Os e-mails de formulário e de notificação de build agora funcionam.
  • fix(forms): missing btn_delete_selected translation: o botão de exclusão em massa na página de submissões mostrava o nome cru da chave em vez de “Delete selected” (nos 4 idiomas). A exclusão em massa de submissões de formulário agora funciona.

v1.3.0

2026-06-14

Release da Phase 80 (Pages), mais uma correção de segurança e uma migração de segurança de atualização.

✨ Features & UX (Phase 80: Pages)

  • Search: filtro q= de título/slug no servidor nas listas de páginas e posts, combinando com sort/dir + paginação.
  • Workflow de revisão: aprovar uma página/post agora envia e-mail ao criador do conteúdo (espelhando o fluxo de rejeição) e registra isso na trilha de auditoria.
  • Round-trip de exportação/importação: as exportações CSV de páginas e posts agora emitem o conjunto completo de colunas na ordem da importação (metadados OG, URL canônica, agendamento, parent_id, recurring, …); os datetimes de agendamento são convertidos para o fuso horário do site para que a reimportação faça o round-trip.
  • Acessibilidade: aria-sort em cabeçalhos ordenáveis, aria-labels em inputs de campos personalizados e checkboxes de selecionar tudo, role=status/aria-live no flash de informação, indicação não baseada em cor nas mudanças do diff de revisão.
  • Os flashes de ações em massa agora nomeiam o que fizeram; os timestamps de revisão são renderizados no fuso horário do site.

🔒 Segurança

  • Os tokens de acesso a documentos agora usam um CSPRNG. Substitui um token derivado de rand não criptográfico + entradas previsíveis por um segredo bearer de 256 bits vindo de /dev/urandom, igual aos tokens de sessão/chave de API. Os tokens existentes continuam válidos; nenhuma migração é necessária.

🐛 Correções e reforço

  • Os re-renders de formulário de edição com erro (falhas de validação e de permissão) agora preservam os dados enviados, incluindo o estado dos checkboxes dos painéis de snippet/area.
  • A exportação JSON de posts não usa mais SELECT *: uma lista explícita de colunas exclui password_hash das exportações compartilháveis.
  • Segurança de atualização: adicionada uma migração idempotente de inicialização de og_image_url para pages/posts, ordenada antes da reconstrução de tabela da phase41 que lê a coluna, para que bancos anteriores a ela sejam atualizados sem problemas.

⬆️ Atualização

Nenhum passo manual. As mudanças de schema são aplicadas automaticamente e de forma idempotente na inicialização; bancos mais antigos são atualizados no local. Os tokens de documentos emitidos sob o esquema anterior continuam válidos.

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.2.3…v1.3.0

v1.2.0

2026-06-12

Novidades

Novos tipos de block (14)

Text, Button Group, Divider, Spacer, Heading, Pricing Table, Feature Grid, Callout, FAQ, Code Block, Team, Timeline, Logo Bar, Audio: todos em Template Toolkit + CSS puros, seguros para air-gap, com formulários de admin e testes de renderização.

Stacks e composição

  • Rastreamento de dependências, visão de uso e painel de blast-radius
  • Histórico de revisões com restauração
  • Rota independente de Preview Stack

Pages e Posts (Phase 47)

  • Campos personalizados, painel de Authors, painel de Translations na barra lateral
  • Módulo Documents
  • Migrações 026 a 039 automatizadas na inicialização

Health e build

  • Endpoint estruturado /health com status e latência por verificação
  • Suíte de validação pré-promoção (validate_build) com verificações de HTML, sitemap e links
  • Guarda de promoção para failover sempre online

Segurança

  • XSS em estilos de block: allowlist de valores CSS em todos os campos de estilo; filtro | html em todos os 33 templates de block; JSON-LD de FAQ gerado via JSON::PP (sem escape feito à mão)
  • Sanitização de URLs de conteúdo: javascript: e outras URLs que não sejam http/https são removidas de content_json no momento de salvar, em todos os tipos de block
  • CSRF: guarda de token adicionada em POST /register e POST /forgot-password
  • Timing de login: verificação bcrypt fictícia quando o username não é encontrado; o tempo de resposta não revela mais a existência da conta
  • TTL de sessão: as sessões agora expiram (8 h por padrão, 30 d com remember-me); sessões anteriores à migração sem TTL são podadas na primeira inicialização
  • Aplicação de permissões em Pages: guarda can_edit_entity_type('pages') em todas as 17 rotas antes desprotegidas
  • Pages require_approval: bulk-publish e publish-now respeitam o workflow de aprovação para editores não admin

Correções

Backups - SQLite Online Backup API para snapshots consistentes (elimina a condição de corrida com o WAL) - Helper compartilhado _backup_paths: os quatro caminhos de restauração usam convenções de diretório idênticas - Os metadados da tabela de temas são exportados para themes.json em todo arquivo compactado; restaurados nas quatro rotas de restauração - Corrigida a assinatura SigV4 por query-string do DO Spaces: a paginação além de 1000 objetos agora funciona - Limite de upload de 50 MiB na restauração - Mudanças nas credenciais de Backup/DO Spaces não disparam mais um rebuild completo do site - Erros de credencial/rede do S3 são exibidos em vez de mostrar silenciosamente uma lista vazia

Pages e operações em massa - Revisões fantasma corrigidas: save_revision movido para dentro da transação de optimistic-lock - Exclusão e duplicação de página única envolvidas em transações; a duplicação agora copia page_area_blocks - Bulk publish/unpublish/schedule/unschedule agora são todos atômicos - Lista de IDs em massa limitada a 500; lista de revisões limitada a 500

Admin - Move-up/down de snippets reescrito para trocar itens adjacentes numa transação (antes era cegamente ±1) - Adicionados wrappers de transação para o move-up/down de campos de formulário - O flash de erro da importação CSV foi sanitizado (erro completo registrado apenas no servidor) - i18n: corrigido o duplo escape de entidades HTML no helper t - Resolvidos N+1 queries, listas ilimitadas e ineficiências de build - Adicionadas as migrações de inicialização 035 e 039 para colunas de atribuição de stack (corrige o crash do builder em deploys novos)


Notas de atualização

  • As migrações 026 a 039 rodam automaticamente na primeira inicialização; nenhum SQL manual é necessário.
  • A coluna user_sessions.expires_at é adicionada automaticamente; as sessões existentes são invalidadas no primeiro reinício (todos os admins precisarão fazer login novamente).
  • O sidecar themes.json é incluído nos backups a partir desta versão. Backups antigos restauram normalmente; o sidecar simplesmente está ausente.

v1.1.2

2026-06-05

Novidades

Correções

  • Build: recuperada a verificação de links quebrados em subdomínio: hrefs absolutos agora são resolvidos contra a raiz do idioma no modo subdomínio; reforçada a validação de last_built contra timestamps futuros/inválidos
  • Build: revertida a renderização incremental inteligente em favor de duas salvaguardas corrigidas (evita que páginas desapareçam após builds incrementais)
  • Bulk create: para de cortar títulos que contêm vírgulas; corrigido o escape de aspas no helper de título do bulk_create
  • i18n: reparados os helpers de título quebrados e chaves de léxico mal aninhadas; adicionada a chave de léxico btn_upload que faltava
  • Auth: exige autenticação de admin na rota de dashboard /admin

Tarefas gerais

  • Branding: avatar da SBS definido como favicon

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.1.0…v1.1.2

v1.1.0

2026-06-05

Novidades

Features

  • Painel de sugestão de links internos: gaveta do editor que examina o conteúdo do corpo e sugere menções sem link de páginas/posts publicados, com ações Link it / Link 1st / Link All / Skip e acessibilidade por teclado
  • Acompanhamento de progresso de build em tempo real: barra de progresso ao vivo, contagens de páginas/posts e exibição do item atual no dashboard do admin durante os builds
  • Sistema de prevenção de falhas de build: verificação de segurança quando 0 páginas são renderizadas, override pela variável de ambiente CHINASKI_FORCE_FULL, endpoint de monitoramento /api/health, validação de data futura em last_built, script de rebuild forçado e script de monitoramento via cron

Correções

  • i18n: reparado UTF-8 com dupla codificação / mojibake em caracteres acentuados maiúsculos (É, Ú, À, Ã etc.) nas traduções ES, FR, PT
  • Templates: corrigidas as diretivas de título nas páginas de dashboard e de busca
  • CMS: $DOCS_DIR declarado antecipadamente antes do primeiro uso

v1.0.2

2026-06-04

O que mudou

  • fix(i18n): fix remaining mojibake for uppercase accented chars (É, Ú, À) by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/79

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1.0.1…v1.0.2

v1.0.1

2026-06-04

O que mudou

  • feat(editor): move page action buttons to top of sidebar by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/44
  • feat(blocks): add page_list block type by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/45
  • fix(favicon): generate and deploy favicon.svg on upload by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/46
  • feat(i18n): Group A: translate auth layout, login, and register by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/47
  • feat(i18n): Group B: translate pages and posts templates by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/48
  • fix(builder): render [form:slug​] shortcodes inline instead of iframe by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/49
  • feat(i18n): Group F: translate forms builder and translation workflows by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/50
  • feat(i18n): Group G: settings, themes, and calendar by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/51
  • fix: add design brief upload UI to themes generate panel by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/52
  • fix: use per-language subdomain for View link in pages admin by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/53
  • i18n: Group I: dashboard, admin tools, and maintenance by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/54
  • i18n: Group J: flash messages in cms.pl by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/55
  • feat(documents): make published documents publicly accessible by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/56
  • feat: build performance + configurable API rate limit by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/57
  • fix: six one-liner bug fixes: settings and search by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/58
  • fix: search UX and settings layout bugs by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/59
  • fix(build): increase timeout and lock TTL; add page-list block styles by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/60
  • fix: settings correctness and search result quality by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/61
  • fix: settings tab data, security_contact validation, webhook events by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/62
  • fix: API key banner visibility and audit_log retention by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/63
  • fix: pages list: add page-jump input to pagination by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/64
  • fix: search results: full action set and resolved URL paths by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/65
  • fix: search results: body match context excerpt by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/66
  • fix: move settings audit and snapshots to dedicated History tab by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/67
  • feat: expose API key rate limit in settings UI by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/68
  • fix: trim verbose settings panel hint texts by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/69
  • fix: move DO Spaces credentials from Integrations to Backups tab by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/70
  • fix: cancel dashboard build-poll timer on page unload by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/71
  • fix: History tab routing and DO Spaces credential reset by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/72
  • feat(schema): Organization JSON-LD on every page by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/73
  • fix(builder): skip stale cleaner on incremental builds by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/74
  • fix(cms): forward-declare $DOCS_DIR before first use by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/75
  • fix(templates): use double quotes for title tags containing t by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/76
  • fix(i18n): repair double-encoded UTF-8 in all translation strings by @bigjohncobb in https://github.com/bigjohncobb/chinaski/pull/78

Changelog completo: https://github.com/bigjohncobb/chinaski/compare/v1…v1.0.1

Leia este site em