Brasil Participativo — Decidim 0.32.x Module Ecosystem

Brasil Participativo — Module Ecosystem on Decidim 0.32.x

How the Brasil Participativo platform extends Decidim 0.32.1: a per-module inventory, the customization patterns we use instead of forking, and deep dives on multi-channel participation (WhatsApp), participatory texts, and the roadmap for a new form module.

Decidim 0.32.1 Ruby ~> 3.4 Multi-tenant (SaaS) AGPL-3.0

1. Overview

Brasil Participativo is the Brazilian federal government's citizen-participation platform, built on Decidim 0.32.1 and operated as a multi-tenant SaaS: a single deployment serves many organizations, each isolated in its own PostgreSQL schema via the decidim-apartment integration gem (participa-gem). Authentication is federated through the national GovBR login via omniauth-govbr.

Every customization ships as a self-contained Decidim engine — one gem per component, no fork of decidim-core. This document is both the internal map of that ecosystem and the material we share with the Decidim developer community, since upstream feature proposals are currently closed on MetaDecidim. Each feature that looks generalizable is explicitly marked as an upstream candidate in its own README.

Scope: only modules compatible with Decidim 0.32.x are documented here. Compatibility is anchored on the host application's Gemfile (decidim 0.32.1) and per-module compatibility commits (e.g. chore: upgrade for Decidim 0.32 compatibility).

2. Module inventory

Complete list of custom modules loaded by the host application. Official Decidim space modules (initiatives, conferences, elections) are used at 0.32.1 without modification and are omitted from the detail sections.

ModuleKindWhat it doesSource / branch
decidim-govbrlocal engineGovBR identity integration, organization theming, homepage content blocks, participatory-process admin extensionsin-repo
decidim-chatbotlocal engineScripted chatbot serving participants on WhatsApp (SERPRO broker)in-repo
decidim-apartmentinfra gemMulti-tenancy via schema-per-tenant (Apartment gem integration)GitLab · v0.1.0-rc
decidim-participatory_textscomponent engineParticipatory texts rebuilt on a Paragraph modelGitLab · main
decidim-questionnairesoverride gemProject-specific overrides on the decidim-forms engineGitLab · main
decidim-bp_proposalsoverride gemPer-step comment control on proposals and collaborative draftsGitLab · main
decidim-bp_meetingsoverride gemPer-step creation, comments and attachments on meetingsGitLab · main
decidim-bp_commentsoverride gemOfficial replies, 2-level threads, edit window, restricted reportsGitLab · main
decidim-government_spacescomponent engineOrgan/Sector hierarchy scoping participatory-process administrationGitLab · main
decidim-categoriescomponent engineHierarchical categories with soft delete, scoped per participatory spaceGitLab · main
decidim-extra_home_blocksopt-in enhancementSettings extensions on core homepage content blocksGitLab · main
decidim-extra_blockscomponent engineLayout-based content blocks (CTA, Hero, Fast Proposal, …)GitLab · main
decidim-community_templatesforkCommunity templates (upstream: decidim-ice), bumped to 0.32GitLab · core/bump-32
decidim-togglethird-partyRegister organization settings tabs for Decidim modulesoctree · main
decidim-ephemeral_participationthird-partyParticipation without registration (graphed from Decidim Barcelona)octree · main
omniauth-govbrauth strategyOmniAuth strategy for the national GovBR loginGitHub · main

In-repository engines

local decidim-govbr

path: ./decidim-govbr · GovBR user logic and theming

Holds everything specific to operating inside the Brazilian government ecosystem: GovBR user logic, organization color theming (Decidim::Govbr::Colors), homepage content blocks (Decidim::Govbr::Homepage::ContentBlocks, including a blog/news cell), participatory-process admin extensions (form validations, metadata, automatic step activation with duplication handling), and organization creation extensions for the system panel.

local decidim-chatbot

path: ./decidim-chatbot · scripted chatbot on messaging apps

"Scripted chatbot that serves participants on messaging apps such as WhatsApp." Ships its own admin engine (brokers, script publishing, editable texts), a YAML-defined conversation flow with a state machine, and a WhatsApp broker backed by SERPRO, the federal government's messaging provider. Detailed in Section 4.

Lappis custom modules (gitlab.com/lappis-unb/decidimbr)

decidim-bp_meetings upstream candidate

Customizations to decidim-meetings · each feature lives in lib/decidim/bp_meetings/features/<feature>.rb with its originating requirement linked in the header

  • per_step_creation — step-scoped control of participant event creation (generalizable; upstream candidate).
  • per_step_comments — step-scoped "citizen can comment" control; deliberately hides the core's vestigial global/step comment settings from the admin form.
  • per_step_attachments — step-scoped attachments, including citizen upload on the meeting form, which exists in no core version (ref: decidim/decidim#5726).

Documented breaking change: creation_enabled_for_participants semantics move from global to step-scoped, with per-step default false — admins must re-enable creation per step.

decidim-bp_proposals

Customizations to decidim-proposals · same feature-file convention as bp_meetings

  • per_step_comments — step-scoped comment gating applied to both Proposal and CollaborativeDraft, with default true so existing organizations see no behavior change.

Step-scoped proposal creation itself is not reimplemented here — the core manifest already provides :step.creation_enabled on 0.32.

decidim-bp_comments

Customizations to decidim-comments · applied via prepend on the core, no fork

  • Official replies — citizens comment at the base level; only administrative profiles reply. Two-level tree; admin replies are badged "Resposta Oficial".
  • Edit window + moderation — regular authors edit/delete their own comment for 5 minutes; global admins delete anything; report button restricted to admin/moderator.

Wiring: config.to_prepare prepends on Permissions, CommentForm, CommentCell and DeleteComment.

decidim-government_spaces

Org-chart-scoped process administration · additive module (no-op until Organs/Sectors exist)

Scopes participatory-process administration to a two-level government hierarchy — Organ → Sector. Organization admins build the hierarchy and invite scoped admins; a scoped admin manages only processes reachable through their memberships and can do everything a native process admin can except delete. Scoped admins are never admin: true, and access is computed live from memberships, so revoking a membership instantly revokes access.

decidim-categories

Replaces the native categorization with a hierarchical, space-scoped system

  • Own data model (decidim_categories_categories) with infinite hierarchy via parent_id, scoped per participatory space.
  • Soft delete ("trash") via deleted_at — historical relationships survive deletion.
  • Business rules injected into Proposals and Meetings forms/commands: category selection is mandatory, only leaf nodes selectable, sibling subcategories mutually exclusive.
  • UI injection via Deface; backend injection via concerns + prepend on form objects and commands.

decidim-questionnaires

Overrides on the forms engine (decidim-forms) that powers Surveys, Meetings and Consultations · no new component manifest

Applies concern-based overrides (commands, controllers, forms, helpers, models) inside Decidim::Questionnaires::Engine#to_prepare, plus Deface view overrides and view-path mirroring to win the ActionView lookup. Explicitly tracks the 0.32 renames (Answer → Response, add_documents → …). This is the established pattern any new form module would follow (see Section 6).

decidim-participatory_texts

Participatory texts rebuilt on a dedicated Paragraph model · main branch carries the 0.32 compatibility upgrade

A from-scratch engine for participatory texts, introducing a Paragraph model as its base structure. Recent work covers visible links and safe deletion, and comment-export fixes. Detailed in Section 5.

decidim-extra_home_blocks

Opt-in enhancements to core homepage content blocks — organization and process homepages

Instead of re-registering (which the core registry forbids), the module mutates the already-registered manifest in an after: initializer: swaps the cell for a subclass, adds a settings form cell and new settings, keeping the core's default behavior. Cells inherit core views so upstream markup changes keep applying. Example feature: the process "extra data" block gains a timeline_display setting rendering an inline, expanded step timeline in place of the core's modal button.

decidim-extra_blocks

Layout-based content blocks for organization, process, process-group and assembly homepages

Admins pick a layout from a gallery (CTA, Hero, Fast Proposal, …), freeze it on the block, then edit layout-specific settings; participants see a cached, mobile-first section.

Forks and third-party modules

fork decidim-community_templates

Upstream: decidim-ice/decidim-module-community_templates · fork branch core/bump-32

Decidim-ICE's community-templates module, bumped to Decidim 0.32 so the platform can import participatory-process templates.

third-party decidim-toggle & decidim-ephemeral_participation

Maintained by Octree (Vocacity) · main branches

decidim-toggle — registers organization settings tabs for Decidim modules (one form, one command, one read API per gem), giving the chatbot and other modules a standard settings surface. decidim-ephemeral_participation — lets citizens participate without registration, graphed from Decidim Barcelona; provisional by design until the equivalent lands in core.

infra decidim-apartment (participa-gem)

gitlab.com/lappis-unb/decidimbr/infra/participa-gem · branch v0.1.0-rc

Integration of the Apartment gem (ros-apartment 3.4) for Decidim: one PostgreSQL schema per organization/tenant, with default configurations for distributed Decidim deployments. This is what turns the single deployment into a SaaS.

3. Customization approach

Four patterns recur across the ecosystem — all aimed at staying mergeable with upstream:

  1. One engine per component, one file per feature. Each customization gem targets a single core component (meetings, proposals, comments). Inside it, every feature lives in lib/decidim/bp_*/features/<feature>.rb with a header explaining the reason and linking the originating requirement — so an upstream port is a copy-paste plus a PR description.
  2. prepend + config.to_prepare, never fork. Behavior changes ride on concerns prepended onto core classes at boot (permissions, forms, commands, cells). No core file is edited; upgrades re-apply cleanly.
  3. Deface and view-path mirroring for markup. Small UI injections use Deface overrides; wholesale view replacements mirror the Decidim path so ActionView lookup resolves the engine's copy.
  4. Manifest mutation over re-registration. For content blocks, the already-registered core manifest is mutated in an after: initializer (the registry raises on duplicate names), subclassing the cell so upstream view inheritance is preserved.
Explicit upstream candidacy. Feature READMEs state whether a feature is a generalizable upstream candidate (e.g. bp_meetings' per_step_creation) or deliberately Brazil-specific (hiding the core's vestigial settings from the admin form). This makes the docset usable as a proposal backlog now that MetaDecidim's feature-suggestion channel is closed.

4. Deep dive — multi-channel participation (WhatsApp)

Participation over WhatsApp is implemented by the decidim-chatbot engine, in this repository. The module's own summary: "Scripted chatbot that serves participants on messaging apps such as WhatsApp." It depends on decidim-admin, decidim-core and decidim-proposals at the host Decidim version.

4.1 Architecture

  • Broker layer — pluggable messaging providers under lib/decidim/chatbot/brokers/. The production broker is SerproWhatsapp, targeting SERPRO's WhatsApp API, the federal government's sanctioned messaging channel. Admin UI includes broker toggles, settings and broker tests.
  • Conversation layer — a fixed script transcribed from the product team's "Textos BP Genérico" document (config/flows/general_script.yml). The script is a YAML state machine: states carry steps, fallbacks, if_empty/requires_vote transitions, and escalation notices (reminder on the second consecutive miss, silence from the third; media handled separately). Admins edit only message variables; structural changes go through code review, deploy, and bin/rails chatbot:validate, which checks structure and WhatsApp message limits.
  • Runtime — inbound messages are processed asynchronously (ProcessInboxJob on Sidekiq), rendered through a template/renderer pair, and answered through the broker. A terminal simulator and printer support development and script review without a phone.
  • Identity — when the conversation needs an authenticated action, the bot issues a one-time identification page link (IdentifyController), valid for 1 hour, one send per issue; GovBR login completes on the site.
  • Multi-tenancy — tenant-aware (lib/decidim/chatbot/tenant.rb), so each organization in the SaaS runs its own script instance and broker configuration.

4.2 Participation features

  • Voting by chat — participants pick a proposal by name; the saved vote is a first-class state variable (vote, ranking) shared between site and chat.
  • Live ranking — the bot can report the top-3 across site and chat votes.
  • Directed to the site — when an action requires the web app, the script routes the citizen to site_url or the identification flow.
  • Phone lock — per-phone constraints prevent duplicate/abuse flows.
Why this matters for the community: it is a complete pattern for Decidim ⇄ WhatsApp participation — scripted flows, provider-brokered messaging, one-time identity handoff, tenant isolation — implemented as a standard engine with an admin surface (via decidim-toggle), ready to be discussed with the developer group as an alternative to closed MetaDecidim feature proposals.

5. Deep dive — participatory texts

decidim-participatory_texts is a from-scratch engine for participatory texts rather than an override of the core component. Its foundational commit introduces the gem structure and a Paragraph model as the document's base unit; the main branch carries an explicit chore: upgrade for Decidim 0.32 compatibility commit, anchoring the module to the 0.32.x line.

  • Paragraph-centric model — documents decompose into paragraphs, the granularity at which citizens comment and interact.
  • Visible links and safe deletion — the most recent feature work (visible links; safe paragraph deletion).
  • Comment export fixes — export includes corrected for comments.

The module complements the chatbot flow: long-form normative documents are the content type most often pushed to WhatsApp audiences, and paragraph-level granularity is what makes chat-based voting and ranking (Section 4) workable for real consultations.

6. Roadmap — new form module

Intent only. A new form module is on the product roadmap ("textos participativos e eventualmente novo módulo de form"). Scope is not yet defined; this section records the established technical path it will follow, not a commitment of features.

The pattern is already proven in-repo by decidim-questionnaires:

  1. Live on top of the core forms engine (decidim-forms) rather than forking it — no new component manifest unless the product needs one.
  2. Wire behavior via concerns included in Engine#to_prepare; keep view changes in Deface overrides or mirrored view paths.
  3. Track core renames per Decidim version (0.32 renamed Answer → Response across the questionnaire surface).
  4. Document each feature with its originating requirement and upstream candidacy, so the module can double as a proposal backlog.

7. References

All links verified reachable (HTTP 200) at the time of writing. Compatibility statements refer to Decidim 0.32.x only.

Brasil Participativo · Lappis/UnB · AGPL-3.0 · Generated for the Decidim developer community — share freely.