Relatório técnico · Revisão crítica

Classificação de Problemas Reportados: Core do Decidim × Customização (participa) × Gems LAPPIS

Análise verificada por leitura direta do código-fonte do Decidim core (/decidim), da aplicação de customização (/participa) e da gem local decidim-govbr. Inclui a descoberta de gems externas do GitLab LAPPIS que substituem módulos inteiros do Decidim e uma investigação dedicada sobre o impacto do multi-tenancy (schema-per-tenant via ros-apartment). Data de geração: 2026-08-14.

1. Sumário Executivo

Dos 53 apontamentos recebidos, a maior parte não é bug da customização: há limitações reais do core do Decidim, funcionalidades implementadas por gems externas do LAPPIS (que substituem módulos inteiros) e diversos casos resolvíveis apenas por configuração no painel admin. A customização (participa / decidim-govbr) é responsável por um bloco menor, mas que inclui bugs graves (erro 500, perda de dados).

18
Core do Decidim
(bugs + limitações + design)
14
Customização
(participa / decidim-govbr)
11
Gems externas LAPPIS
(GitLab)
7
Configuração / Uso
(painel admin)
3
Reproduzir
(evidência insuficiente)

Leituras-chave do relatório

  • Texto Participativo não é o módulo do core. O módulo em uso é a gem LAPPIS decidim-participatory_texts, não o decidim-collaborative_texts. Os 9 itens reportados pertencem à gem.
  • Há um bug de segurança no core: respostas de formulário são aceitas mesmo com o formulário encerrado, via POST direto (seção 5, erro 6).
  • Os campos "Setor / E-mail / Telefone / Responsável" não são campos novos: são remapeamentos de labels de campos existentes do core (seção 3). A obrigatoriedade, porém, foi adicionada pela customização.
  • Multi-tenant: Sidekiq, ActiveStorage e resolução de organização estão cobertos pela gem decidim-apartment. O risco real restante é a colisão de IDs no cache de OrganizationSettings (seção 12).
  • 5 bugs do core têm correção pontual identificada e são candidatos a PR upstream (seção 14).
ResponsávelQtd.Onde agir
Core Decidim 18 PRs upstream no repositório decidim/decidim (traduções pt-BR via Crowdin, fixes de código no core).
Customização 14 Repositório do participa e da gem local decidim-govbr.
Gems LAPPIS 11 Repositórios das gems no GitLab LAPPIS (decidim-participatory_texts, decidim-questionnaires, etc.).
Configuração 7 Painel admin / painel system — sem alteração de código. Requer treinamento ou documentação de uso.
Reproduzir 3 Reprodução em ambiente de staging antes de classificar.

2. Descoberta Crítica: Gems Externas do LAPPIS

Vários módulos reportados não são nem core nem customização direta

A exploração do participa revelou que o Gemfile instala gems externas do GitLab LAPPIS que substituem ou estendem módulos inteiros do Decidim. Problemas nesses módulos devem ser reportados/corrigidos nos repositórios das gems, não no core nem necessariamente no código da aplicação participa.

Gem LAPPISSubstitui / EstendeImpacto na lista de problemas
decidim-participatory_texts Texto participativo (módulo inteiro) Todos os 9 itens de "Texto Participativo" pertencem a esta gem, não ao decidim-collaborative_texts do core.
decidim-questionnaires Formulários / questionários Adiciona max_files por questão, mailer de confirmação, view read-only de respostas e o step setting allow_answers. Vários erros de formulário são da interação gem × core (seção 5).
decidim-bp_comments Comentários Comportamento de moderação/denúncia de comentários pode vir daqui.
decidim-bp_proposals Propostas Permissões e fluxo de avaliação customizados.
decidim-bp_meetings Reuniões Formulário de reunião customizado.
decidim-categories Categorias (sistema legado) Explica "categorias" aparecendo onde o core atual usa taxonomias.
decidim-government_spaces Espaços governamentais Papéis "órgão" e "setor" com permissões customizadas — não existem no core.
decidim-extra_home_blocks Blocos da home "Processos Abertos" é bloco custom desta gem, não o highlighted_processes do core.

3. Campos Remapeados (não são campos novos)

A customização não adicionou novos campos ao formulário de processo participativo. Ela remapeou os labels de campos já existentes no core via locale pt-BR. Isso muda a natureza dos apontamentos: não há "campos faltando", há labels com semântica diferente do campo original — e validações de obrigatoriedade adicionadas pela customização.

Campo do core (Decidim)Label exibido (participa)Seção do formulário
developer_groupSetor / Grupo promotorDados complementares
local_areaTelefone ou E-mail institucional do setorDados complementares
meta_scopeResponsável pela consultaDados complementares
participatory_scopeLink da publicação no DOUDados complementares
targetData de publicação no DOUDados complementares

Origem da terminologia

A seção "Dados complementares" é um accordion do formulário simplificado do decidim-govbr, e o campo metadata do core foi traduzido como "Dados complementares" em participa/config/locales/.../pt-BR.yml:455 ("Informações adicionais" em pt-BR.yml:478). A obrigatoriedade desses campos vem de participatory_process_form_extensions.rb (govbr), que adiciona presence: true.

4. Texto Participativo decidim-participatory_texts (LAPPIS) — NÃO é o core

Correção importante

O módulo "Texto Participativo" dos apontamentos não é o decidim-collaborative_texts do core (documentos com sugestões em nível de nó DOM). É a gem decidim-participatory_texts do GitLab LAPPIS, instalada via Gemfile. O core decidim-collaborative_texts sequer possui comentários, moderação, denúncia ou anexos — Document e Suggestion não incluem Commentable nem Reportable, e um grep por "comment" em app/ retorna zero. Todos os itens abaixo são responsabilidade da gem LAPPIS.

ProblemaOrigemEvidência
Hiperlink sem destaque visual LAPPIS O core não estiliza <a> no corpo do documento. Verificar CSS/JS da gem participatory_texts.
Comentários em moderação — link não direciona LAPPIS Comentários neste componente foram adicionados pela gem; o link de moderação é implementação dela.
Tag "sendo avaliado" persiste após retorno LAPPIS Status intermediário de moderação de comentário não existe no core ("em avaliação" existe apenas em decidim-proposals, para propostas).
Erro ao inserir documento com vários parágrafos LAPPIS O core opera por nó DOM (firstNode/lastNode); não existe importador multi-parágrafo no core.
Exportar comentários pelo admin LAPPIS Core exporta apenas sugestões (SuggestionSerializer); comentários e sua exportação são da gem.
Anexos nos comentários LAPPIS Document do core não inclui HasAttachments; feature da gem.
Falta botão pré-visualizar inline LAPPIS Core tem apenas link "Preview" em dropdown (_actions.html.erb:54-59). Preview inline seria feature da gem.
Opção "mesclar parágrafos" LAPPIS Core tem "consolidate" (aplica sugestões em nova versão) — conceitualmente diferente. Mesclagem é da gem.
Comentários denunciados continuam visíveis LAPPIS No core, Reportable + ModerationTools escondem conteúdo reportado após ação do admin. Fluxo de denúncia deste componente é da gem.

Conclusão do módulo

9 de 9 itens são da gem LAPPIS decidim-participatory_texts. Os bugs devem ser reportados/corrigidos no repositório da gem. Nenhum item deste módulo é do core do Decidim.

5. Formulários / Surveys — investigação aprofundada decidim-forms / decidim-surveys (core) + decidim-questionnaires (LAPPIS)

Cada erro foi verificado diretamente no código: models, forms, controllers, commands, permissions, views e serializers do core, mais os overrides da gem decidim-questionnaires (v0.0.1, LAPPIS), que estende o decidim-forms via prepend/include e Deface.

O que a gem decidim-questionnaires (LAPPIS) adiciona

max_files por questão (migration + campo admin via Deface + controller Stimulus FilesLimitController + validação server-side); view read-only de respostas anteriores (_user_answers_readonly.html.erb via Deface); ConfirmationMailer custom; step setting allow_answers; fix de safe navigation em mandatory_conditions_fulfilled?; restauração de respostas ocultas após falha de validação. Não foram encontrados overrides de formulários no participa/app/ ou no decidim-govbr.

#Erro reportadoVeracidadeOrigemTenant?Severidade
1 Não apresenta quantidade de arquivos nem extensões aceitas ✅ Verdadeiro LAPPIS + Core Não Média
2 Formulário não enumera as questões ✅ Verdadeiro Core Não Limitação
3 Anexos não visíveis na confirmação da resposta ✅ Verdadeiro LAPPIS Possível (mailer via Sidekiq) Média
4 Não exibe qtd. máxima de arquivos mesmo configurada ✅ Verdadeiro LAPPIS Não Média
5 Condicionantes não executadas conforme configuração ✅ Verdadeiro (4 bugs) Core + LAPPIS Não Alta
6 Respostas enviadas mesmo com formulário encerrado ✅ Verdadeiro — segurança Core Não Crítica
7 Quebra de HTML no item de exportação ✅ Verdadeiro Core Não Média
8 Formulário "encerrado" mesmo com datas ativas ⚠️ Configuração + UX LAPPIS + Config Não Alta
9 Edição de respostas enviadas não funciona ⚠️ Configuração + possível bug LAPPIS + Config Não Média

Evidências por erro

  • Erro 1/4 — info de arquivos: o core não tem max_files no model Question. A gem LAPPIS adiciona o campo e o enforcement (Stimulus + validação), mas não renderiza texto visível informando o limite nem as extensões aceitas. Fix na gem: exibir help text no partial answers/_files.html.erb.
  • Erro 2 — numeração: QuestionReadonlyCell#position calcula a posição, mas ela vai apenas para o atributo invisível data-response-idx. Nenhum partial renderiza o número. Ausência de feature no core e na gem.
  • Erro 3 — confirmação: após submeter, o core redireciona com flash (sem página de confirmação). A gem adiciona a view read-only e o ConfirmationMailer — verificar se _user_answers_readonly.html.erb renderiza links de arquivos e se o mailer está chegando (depende do middleware de tenant do Sidekiq).
  • Erro 5 — condicionantes, 4 bugs do core: (a) not_equal com resposta vazia retorna nil (display_condition.rb:36-42); (b) divergência JS × Ruby no tipo match multi-idioma (JS usa só o locale atual, Ruby itera todos); (c) responded não detecta questões de ordenação (hidden fields fora do seletor JS); (d) inputs disabled quando o JS falha. A gem corrigiu parcialmente com safe navigation e restauração de respostas ocultas.
  • Erro 6 — SEGURANÇA: o check survey.open? existe só na view. O action respond não verifica abertura; a permission class sempre permite :respond; o command ResponseQuestionnaire não checa open?. Um POST direto a /surveys/:id/respond grava resposta em formulário encerrado. O allow_answers da gem controla exibição por etapa, não o backend.
  • Erro 7 — HTML na exportação: UserResponsesSerializer#translated_question_key usa o body rich text da questão sem sanitização nas chaves do CSV. Fix: strip_tags(translated_attribute(body)).
  • Erro 8 — "encerrado" mesmo ativo: Survey#open? (survey.rb:51-60) retorna false se allow_responses estiver desmarcado, independente das datas. A gem adiciona um segundo toggle (allow_answers por etapa) sem documentar a interação — a confusão entre os dois toggles é a causa provável.
  • Erro 9 — edição: requer 3 condições simultâneas (usuário logado + allow_editing_responses + survey aberto). Se o survey fechou, a edição é bloqueada mesmo com o checkbox marcado. Adicional: verificar se o override Deface da view read-only não quebrou o link para edit_survey_path.

Ação prioritária — Erro 6 (segurança)

Adicionar verificação de abertura no backend do core: before_action no controller de surveys ou check de survey.open? no command ResponseQuestionnaire. Hoje a proteção é apenas visual (a view esconde o formulário).

6. Colegiados / Assembleias decidim-assemblies (core)

ProblemaOrigemEvidência
Assembleia puxa todos os processos ao criar Core AssemblyForm#processes_for_select (assembly_form.rb:102) busca todos os processos da organização sem filtro. Comportamento nativo.
Typo "assambleia" (3 ocorrências) Core decidim-assemblies/config/locales/pt-BR.yml linhas 8, 162 e 238. Correto: "assembleia". Bug de tradução (Crowdin).
Só admin geral deleta comentário Customização No core, nenhum admin deleta comentário — só o autor (Permissions:39-43, DeleteComment:23). Admins apenas escondem via moderação. A deleção por admin foi adicionada via decidim-bp_comments (LAPPIS) ou decidim-government_spaces.

7. Blog decidim-blogs (core) + bloco custom (govbr)

ProblemaOrigemEvidência
Botão de confirmar horário coberto pelo rodapé Reproduzir Core usa datetime_field :published_at + sticky footer com submit. Em viewports curtos o sticky pode cobrir o campo. CSS do sticky é do core, mas customizações gov.br podem agravar. Reproduzir antes de classificar.
Edição de comentário a qualquer tempo Core Design can_update_comment? só checa authored_by?; sem limite temporal. Comportamento nativo por design (verificar se decidim-bp_comments faz override).
Comentários bloqueados mostram opções de interação Customização Core esconde tudo em hidden?/deleted? (comment/show.erb:6-10). Se opções aparecem, é regressão em override do decidim-bp_comments ou da customização.
Título da notícia sem negrito na home Core CardGCell#title_class retorna "h4 text-secondary", sem font-bold explícito.
Sem botão "Ver mais" na home Customização O participa usa o bloco custom blog_news do decidim-govbr, não o HighlightedPosts do core (que renderiza "See all" apenas com single_component). O botão é responsabilidade do bloco custom.

8. Processos Participativos decidim-participatory_processes (core) + overrides govbr

ProblemaOrigemEvidência
Erro 500 ao atualizar datas Customização O core (UpdateParticipatoryProcess) valida e retorna 422. O participa tem command custom UpdateParticipatoryProcessDates + controller override + ParticipatoryProcessDateForm. O 500 vem do código custom.
Perda de dados ao selecionar categoria Customização O core não tem campo "categoria" (usa taxonomias; <select> sem auto-submit nem redirect). O redirect/perda está no form override do participa ou na gem decidim-categories (LAPPIS).
Avaliadores sem acesso a avaliar Configuração O core exige EvaluationAssignment explícito (permissions.rb:13, 93-98). Fluxo nativo: admin seleciona propostas → Ações → Atribuir ao avaliador.
Categorias não aparecem na aba do processo Customização O core não tem aba "categorias" no menu admin (taxonomias ficam no form). A aba é da gem decidim-categories (LAPPIS).
Imagem CTA não aparece na home Configuração O bloco hero é default! e suporta background_image. Ausência = configuração do bloco no admin.
Campos Setor/E-mail/Telefone/Responsável obrigatórios Customização São remapeamentos de campos core (ver seção 3). As validações presence: true foram adicionadas por participatory_process_form_extensions.rb (govbr).
Descrição sem limite de caracteres; nomenclatura inconsistente Customização Core não valida length. "Dados complementares" / "Informações adicionais" são traduções custom (pt-BR.yml:455, :478).
PROCESSOS e INICIATIVAS não aparecem na home Configuração São content blocks opcionais. O participa usa o bloco custom open_processes (govbr). Depende do layout da home no admin.
PROCESSOS ABERTOS não relaciona processos Customização "Processos Abertos" é o bloco custom open_processes registrado em decidim-govbr/.../homepage/content_blocks.rb — não o highlighted_processes do core. Bug no código custom.
Espaço de Iniciativas desabilitado Configuração O menu de iniciativas é data-driven: só renderiza se houver InitiativesType com scopes na organização.
"Dados complementares" exibidos diferente na home Customização Terminologia do participa (locale override). A exibição depende do content block usado.
Ordem "Dados do Processo" antes de "Etapa e Duração" Configuração A ordem dos content blocks é configurável pelo admin no painel.
Bloco de Reuniões com %{count} bruto Core highlighted_meetings_for_component/show.erb:12 chama t(...see_all) sem passar count:; a locale pt-BR define see_all: "Ver todos (%{count})". Bug confirmado (também em decidim-accountability).

9. Propostas decidim-proposals (core) + decidim-bp_proposals (LAPPIS)

ProblemaOrigemEvidência
Avaliadores não conseguem avaliar Configuração Core exige EvaluationAssignment explícito. Fluxo nativo. Se decidim-bp_proposals muda permissões, verificar a gem.
Admin de órgão/setor não modera comentário Customização "Órgão" e "setor" são papéis do decidim-government_spaces (LAPPIS); o core tem apenas :moderator/:admin de espaço. A permissão diferencial é da gem.
Alerta de limite de votos Core Existem maximum_votes_reached e no_votes_remaining (_remaining_votes_count.html.erb, _voting_rules.html.erb). Tag nativa.
Redimensionamento automático de imagens Core AttachmentUploader gera variantes lazy (thumbnail 237px, big 1000px) mas não redimensiona a original — apenas valida máx. 8000px. Limitação do core.

10. Reuniões decidim-meetings (core) + decidim-bp_meetings (LAPPIS)

ProblemaOrigemEvidência
Outlook baixa o mesmo arquivo do Apple Core Correto _add_to_calendar_modal.html.erb:7,10: ambos usam ics_url. Não é bug — Outlook e Apple Calendar consomem o mesmo formato .ics; só o Google Calendar usa URL web separada. Desclassificar.
Não é possível selecionar categoria ao criar reunião Reproduzir Core suporta taxonomias em reuniões (BaseMeetingForm inclui HasTaxonomyFormAttributes). O form custom do decidim-bp_meetings e o legado decidim-categories podem interferir. Verificar qual form está ativo.

11. Login / Plataforma / Outros decidim-core

ProblemaOrigemEvidência
Quebra de HTML no label "Senha" Core decidim-core/config/locales/pt-BR.yml:716: chave shown_password vazia → data-shown-password="". O JS faz fallback em inglês ("Your password is shown"). Bug de localização.
Data da reunião em formato US (mês/dia) no admin Core admin/agenda/_form.html.erb:16,20: strftime("%m/%d/%Y %R") hard-coded. Deveria usar I18n.l.
Interface em inglês para não autenticados Configuração O fallback é o default_locale da organização (locale_router_detector.rb:14,34). Configurar no painel system.
Redirect de link de proposta quebra após login Reproduzir Depende de stored_location_for (Devise). O participa usa login gov.br (omniauth-govbr); provável interação com o OAuth custom. Reproduzir.
Templates quebram a visualização Customização Core: templates (proposal_answer, questionnaire, block_user) sem problema estrutural. O participa tem override community_templates com cell custom + catálogo. Bug na customização.
Botão de download de arquivos nas contribuições Core Download/exportação só existe no admin (permissão :export). Na visão pública não há botão de download em lote. Limitação do core.

12. Impacto do Multi-Tenant ros-apartment + decidim-apartment (LAPPIS)

A aplicação usa schema-per-tenant no PostgreSQL. A pergunta investigada: quais problemas reportados só acontecem no tenant e não ocorreriam em single-tenant?

Arquitetura em 3 camadas

CamadaComponenteFunção
Engineros-apartment ~> 3.2.0Isola dados em schemas PostgreSQL separados por tenant.
Integraçãodecidim-apartment (LAPPIS)Mapeia host → schema via tabela apartment_distribution_keys; DetectOrganizationMiddleware faz Organization.first no schema correto.
Patchactive_storage_apartment_patch.rbTroca tenant em requests do ActiveStorage.

Correção à análise preliminar

Uma primeira hipótese apontava "Sidekiq sem middleware de tenant" como crítico. Estava errada: a gem decidim-apartment já fornece SidekiqTenantMiddleware (troca o tenant durante a execução do job), ActiveJobWithTenant (injeta o tenant nos argumentos no enqueue) e ApartmentDiskStorage/ApartmentS3Storage (prefixam os paths de arquivo com o tenant). Em produção, o cache Redis também usa namespace: proc { Apartment::Tenant.current }.

Riscos reais que permanecem

RiscoStatusEvidência e impacto
Colisão de ID no cache OrganizationSettings.@registry Crítico decidim-core/lib/decidim/organization_settings.rb: cache class-level indexado por organization.id. Em schema-per-tenant, tenants diferentes podem ter organization.id == 1 (sequences são por schema) — o segundo tenant recebe as settings cacheadas do primeiro.
Pode explicar: formulário "encerrado" mesmo ativo, componentes não aparecendo na home, configs de componente erradas.
ActionCable sem troca de tenant Alto application_cable/connection.rb e channel.rb são stubs vazios — sem middleware de tenant para WebSocket. Mensagens de um tenant podem chegar a outro (relevante se o texto participativo usa edição colaborativa em tempo real).
mattr_accessor globais do módulo Decidim Alto ~30 configurações globais (default_locale, mapas, etc.) compartilhadas entre tenants, setadas no boot. Pode explicar "interface em inglês para não autenticados" se o fallback usa Decidim.default_locale (global) em vez de current_organization.default_locale.
Drift de schema_migrations entre tenants Médio Migrations falhando em um tenant deixam tabelas faltando só nele. Operacional, não de código.

Resolvido pela gem decidim-apartment (não é problema)

Hipótese inicialVeredito
Sidekiq executa jobs no schema erradoCobertoSidekiqTenantMiddleware + ActiveJobWithTenant na engine da gem.
Blobs do ActiveStorage vazam entre tenantsCoberto — storage com prefixo por tenant + patch no BaseController.
Lookup de organização pelo host erradoCobertoDetectOrganizationMiddleware faz Organization.first após o switch.
Cache Redis compartilhado entre tenantsCoberto — namespace por tenant em produção.

Veredito por apontamento

CategoriaQtd.Descrição
Provavelmente tenant ~4 Vinculados ao cache de OrganizationSettings (formulário encerrado, componentes na home) e ao default_locale global.
Possivelmente tenant ~4 Callback OmniAuth gov.br, redirect pós-login, imagens/CTA, ActionCable (se usado).
Não é tenant ~45 Bugs de locale, limitações de design do core, customizações govbr e gems LAPPIS — ocorrem igual em single-tenant.

Como testar se um problema é do tenant

  1. Reproduzir no tenant afetado e confirmar o erro.
  2. Logar o schema ativo no momento do erro: Rails.logger.info "Schema: #{Apartment::Tenant.current}".
  3. Comparar com outro tenant (ou ambiente single-tenant): se o problema some, é tenant.
  4. Para suspeitas de settings: inspecionar Decidim::OrganizationSettings — se o registry já foi populado por outro tenant com o mesmo organization.id, há colisão.
  5. Para jobs: verificar se o argumento "tenant" está presente no payload do job no Sidekiq.

Fix recomendado (maior impacto, menor esforço)

Resolver a colisão do OrganizationSettings.@registry indexando o cache também pelo tenant:

# config/initializers/organization_settings_tenant_safe.rb
# Indexa o registry por (tenant, organization.id) em vez de só organization.id,
# evitando colisão quando dois tenants têm organization.id == 1.

13. Correções em Relação à Análise Anterior

Análise anterior diziaRevisão concluiu
"Outlook baixa o mesmo arquivo do Apple" é bug Não é bug. Ambos consomem .ics; só o Google Calendar usa URL web. Desclassificar.
Core não redimensiona imagens de propostas Parcial: o core gera variantes lazy (thumbnail/big), mas não redimensiona a imagem original (só valida máx. 8000px). Limitação, não ausência total.
Texto Participativo = decidim-collaborative_texts do core Errado: o módulo em uso é a gem LAPPIS decidim-participatory_texts. Todos os 9 itens mudam de "customização" para "gem LAPPIS".
Campos Setor/E-mail/Telefone/Responsável são campos novos São remapeamentos de labels de campos core via locale. O que a customização adicionou foi a obrigatoriedade.
"Sidekiq sem middleware de tenant" é crítico Errado: a gem decidim-apartment já cobre Sidekiq, ActiveJob e storage. O risco real é a colisão de ID no OrganizationSettings.
"Ver mais" do blog some por limitação do core O participa usa o bloco custom blog_news (govbr), não o HighlightedPosts do core. O botão é responsabilidade do bloco custom.
"Processos Abertos" é configuração do bloco do core É o bloco custom open_processes do decidim-govbr. Se não lista processos, é bug do código custom.

14. Priorização e Recomendações

Bugs do core com correção identificada — candidatos a PR upstream

  • Typo "assambleia"decidim-assemblies/config/locales/pt-BR.yml linhas 8, 162, 238. Fix: "assembleia" (via Crowdin).
  • shown_password vaziodecidim-core/config/locales/pt-BR.yml:716. Fix: "Sua senha está visível".
  • strftime("%m/%d/%Y") hard-codeddecidim-meetings/.../admin/agenda/_form.html.erb:16,20. Fix: I18n.l.
  • %{count} literalhighlighted_meetings_for_component/show.erb:12 sem passar count:. Fix: passar count: meetings.count.
  • HTML sem sanitização na exportaçãoUserResponsesSerializer. Fix: strip_tags(translated_attribute(body)).
  • Respostas aceitas em formulário encerrado (segurança) — adicionar check de survey.open? no controller/command.
PrioridadeAçãoResponsável
P0 Erro 6 de formulários: backend aceita respostas em formulário encerrado (POST direto). Bug de segurança no core. Core (upstream) + hotfix local
P0 Colisão de ID no OrganizationSettings.@registry — settings de um tenant vazando para outro. Customização (initializer) / Core (upstream)
P1 Erro 500 ao atualizar datas de processo (command custom UpdateParticipatoryProcessDates). Customização
P1 Confusão allow_answers (etapa, gem) × allow_responses (survey, core) — causa do "encerrado mesmo ativo". Unificar ou documentar. LAPPIS + treinamento admin
P1 Perda de dados ao selecionar categoria no form de processo (redirect não existente no core). Customização
P1 4 bugs de condicionantes (not_equal vazio, match multi-idioma JS×Ruby, sorting, disabled sem JS). Core
P2 Texto visível de limite de arquivos e extensões; anexos na confirmação; view read-only de edição. LAPPIS (decidim-questionnaires)
P2 Bloco "Processos Abertos" não lista processos; botão "Ver mais" do blog; templates quebrados. Customização (govbr)
P2 5 fixes pontuais do core (typo, shown_password, strftime, %{count}, sanitização CSV). Core (upstream)
P3 Treinamento/documentação para os 7 itens de configuração (checkboxes de formulário, content blocks, locales, atribuição de avaliadores). Operação
P3 Reproduzir os 3 itens ambíguos (botão coberto por rodapé, redirect pós-login gov.br, categoria em reunião). QA

Constatação final sobre formulários

O módulo decidim-forms/decidim-surveys é excepcionalmente limpo para multi-tenancy: zero estado mutável em nível de classe, escopo correto via cadeias de associação e validação cross-organization no model Response. Nenhum dos 9 erros de formulário é causado pelo multi-tenant e nenhum pelo decidim-govbr ou participa/app/ diretamente — a responsabilidade se divide entre o core e a gem LAPPIS decidim-questionnaires.

15. Pesquisa Web: Bugs Conhecidos Upstream (GitHub / MetaDecidim / CVEs)

Busca realizada no GitHub (decidim/decidim issues, discussions e security advisories), MetaDecidim e bases de CVE, cruzada com os 9 erros de formulário deste relatório. Vários erros reportados internamente já são bugs públicos confirmados no upstream — o que reforça a classificação "core" e indica que alguns já têm PR de correção aberto.

Condicionantes (Erro 5) — fortemente confirmado upstream

ReferênciaStatusRelação com nossos erros
#17193 — Editar condição corrompe a questão dona (decidim_question_id sobrescrito) Aberto 2026-06 Condição vira auto-referente e a questão nunca exibe corretamente. Explica "condicionantes não executadas conforme configuração". PR de fix #17194 aberto.
#10815 — Questões obrigatórias com condições: seleção default indevida, condições não reabrem, sucesso sem responder obrigatórias Reportado v0.27 Confirma falhas de validação server-side × JS nas condicionantes (nossos bugs 5a/5d).
#10253 — Múltiplas condições: só a última é salva Reportado Admin configura N condições e só 1 persiste — "não executadas conforme a configuração".
#10374 — Dropdown de "opção de resposta" vazio ao criar condição "Equal" em templates Reportado 2023 Impossibilidade de configurar condições corretamente em templates de questionário.
Discussion #13437 — "Slim conditionals on surveys" Discussão 2024 O próprio design group do MetaDecidim reconhece que "survey conditionals are not working well" e discute simplificar a feature. Sinal de que o problema é reconhecido upstream.

Numeração de questões (Erro 2) — confirmado upstream

ReferênciaStatusRelação
#13207 — Numeração das questões "pula" quando há questões condicionais ocultas; numeração do backend ≠ frontend Reportado desde v0.24 Confirma que a numeração visível de questões é problemática no core — afeta todas as instalações.

Status "encerrado" e datas (Erro 8) — bugs de data confirmados

ReferênciaStatusRelação
#14502 — Timezone bug nas datas de início/fim do survey (Decidim::Attributes::TimeZone ignora o offset no parse) Reportado até v0.29 Datas podem mudar conforme o timezone do servidor — explica formulário exibido como encerrado/ativo em horário errado, mesmo com datas "corretas".
#14994 — Survey salva com datas vazias mantendo as anteriores (faltam validações presence: true) Reportado v0.30 Admin acha que limpou/alterou datas e o survey mantém as antigas — mais uma fonte de "encerrado mesmo ativo".
#17362 — Não é possível responder survey de teste com espaço não publicado Aberto 0.31.4 / 0.32 Gating de publicação espaço × componente × survey confunde admins — mesmo padrão de UX dos nossos erros 8/9.

Exportação e confirmação (Erros 3 e 7)

ReferênciaStatusRelação
#4829 — Export CSV/XLS não baixa texto livre vinculado a questão de múltipla escolha Reportado 2019 Histórico longo de problemas na exportação de respostas de survey.
#12135 — Export PDF de respostas quebra (wicked_pdf_stylesheet_pack_tag indefinido); e-mail nunca é enviado Reportado v0.26 Export/confirmação dependem de job em background que pode falhar silenciosamente.
MetaDecidim #17385 — E-mail de confirmação com respostas (PDF) só funciona para usuários registrados Documentado Confirma a lacuna do Erro 3: participantes anônimos não recebem nem veem nada após responder.

Edição de respostas (Erro 9) — feature nova, maturidade baixa

ReferênciaStatusRelação
Blog v0.30.0 — "Enable users to edit their survey answers" (#13800) Feature v0.30 (2025-04) A edição de respostas é feature nova (v0.30). Bugs e arestas são esperados; reforça a hipótese de problema no override da gem LAPPIS ou na configuração.

Segurança — advisories relevantes

ReferênciaSeveridadeRelação
GHSA-3cx6-j9j4-54mp / CVE-2025-65017 — exportações de dados privados com colisão de UUID → vazamento de dados entre exports High 0.30.0–0.30.3, 0.31.0.rc1 Verificar a versão do Decidim no participa: se estiver em 0.30.0–0.30.3, exports privados (incl. respostas de formulário) podem vazar dados. Corrigido em 0.30.4 / 0.31.0.
v0.31.0 release notes — inclui fix "decidim-forms: Error saving survey" e renomeação de permissão answer → respond (PR #14940) Info Quem atualizou para 0.31 precisa rodar bin/rails decidim_surveys:upgrade:fix_survey_permissionsse não rodou, permissões de responder surveys podem estar quebradas (candidato a explicar erros 8/9).

Não encontrado upstream — nosso Erro 6 (segurança)

Não localizamos issue público sobre "survey encerrado aceita respostas via POST direto" (ausência de check survey.open? no controller/command). É candidato a reporte de segurança privado ao time Decidim (security@decidim.org / GitHub Security Advisories), não issue público.

Impacto da pesquisa na classificação

  • Erro 5 (condicionantes): promovido a "bug upstream confirmado e reconhecido" — 4 issues + 1 discussion oficial. Fix de #17193 a caminho (PR #17194).
  • Erro 2 (numeração): confirmado upstream (#13207) — não é só ausência de feature, é bug conhecido desde v0.24.
  • Erro 8 ("encerrado" mesmo ativo): além da hipótese de configuração, há 2 bugs upstream de datas (#14502 timezone, #14994 datas vazias) e 1 de gating de publicação (#17362) que podem produzir exatamente esse sintoma. Rebaixar a confiança em "só configuração".
  • Erro 9 (edição): feature nova (v0.30); verificar se a rake task de permissões do upgrade 0.31 foi executada.
  • Ação nova: checar a versão do Decidim do participa contra o CVE-2025-65017 (exports privados).

Relatório gerado em 2026-08-14, com base em investigação por leitura direta de código (grep, models, controllers, views, permissions e locales) em /mnt/data/code/presidencia/decidim/ (core), /mnt/data/code/presidencia/participa/ (aplicação Rails) e /mnt/data/code/presidencia/participa/decidim-govbr/ (gem local). As classificações marcadas como "Reproduzir" exigem confirmação em ambiente de staging.