Skip to content

Replace private/transparent with access mode in Processes and Assemblies#15895

Merged
alecslupu merged 69 commits intodevelopfrom
feature/enum-access-mode-spaces
Mar 24, 2026
Merged

Replace private/transparent with access mode in Processes and Assemblies#15895
alecslupu merged 69 commits intodevelopfrom
feature/enum-access-mode-spaces

Conversation

@andreslucena
Copy link
Copy Markdown
Member

@andreslucena andreslucena commented Jan 16, 2026

🎩 What? Why?

This PR changes the beahviour of private spaces, so instead of having the private/transparent checkboxes and logic - that is difficult to follow and document, we migrate to radio buttons with the three options (Open, Restricted, Transparent).

📌 Related Issues

⚠️ This (still) does not fully close #15720, as I need to do a final change in the form (reordering the form and implementing

Testing

  1. Starting point (before this PR, on develop)
  2. Sign in as admin
  3. Create the following spaces:
    2.1. Participatory process, without checking "Private process"
    2.2. Participatory process, checking "Private process"
    2.3. Assembly, without checking "Private space"
    2.4. Assembly, checking "Private space", without checking "Is transparent"
    2.5. Assembly, checking "Private space", checking "Is transparent"
  4. Export all these spaces to JSON
  5. Change to this branch
  6. Run bin/rails db:migrate data:migrate
  7. Follow the others checks in Testing

Migration

  1. Check out that the spaces have these following changes:
Before the migration After the migration
1.1. Participatory process, without checking "Private process" Access mode: open
1.2. Participatory process, checking "Private process" Access mode: restricted
1.3. Assembly, without checking "Private space" Access mode: open
1.4. Assembly, checking "Private space", without checking "Is transparent" Access mode: restricted
1.5. Assembly, checking "Private space", checking "Is transparent" Access mode: transparent

Creation

  1. Sign in as admin
  2. See that you can create new spaces with these access mode

Update

  1. Sign in as admin
  2. See that you can change the access mode in these spaces

API

  1. Sign in as admin
  2. Do the following query to check out the spaces: XXX

Open data

  1. Go to http://localhost:3000/open-data
  2. Click on "Download all the Open Data files"
  3. Wait for the files to be generated
  4. Click again
  5. Open the zip
  6. Check out the files and see the spaces there

Filters

  1. Sign in as admin
  2. Create a process or an assembly with these new access modes
  3. Click in filters -> Access mode -> any
  4. See that it gets filtered

Import (legacy)

  1. Sign in as admin
  2. Go to http://localhost:3000/admin/assemblies/imports/new
  3. Import any of these files, see that the legacy value gets converted to the new one
File Legacy value New value
[legacy-open-process.json](https://github.com/user-attachments/files/25707962/legacy-open-process.json) Private process (unchecked) Access mode: Open
[legacy-private-process.json](https://github.com/user-attachments/files/25707963/legacy-private-process.json) Private process (checked) Access mode: Restricted
[legacy-open-assembly.json](https://github.com/user-attachments/files/25707964/legacy-open-assembly.json) Private assembly (unchecked) Access mode: Open
[legacy-private-assembly.json](https://github.com/user-attachments/files/25707965/legacy-private-assembly.json) Private assembly (checked) - is transparent (unchecked) Access mode: Restricted
[legacy-transparent-assembly.json](https://github.com/user-attachments/files/25707966/legacy-transparent-assembly.json) Private assembly (checked) - is transparent (checked) Access mode: Transparent

Mind that the Transparent process ( Private assembly (checked) - is transparent (checked)) is added with this PR.

Export/Import (new spaces)

  1. Sign in as admin
  2. Export any kind of new process or assembly
  3. Import it
  4. See that the value matches

📷 Screenshots

image image

(Placeholder, still working on this)

♥️ Thank you!

Summary by CodeRabbit

  • New Features

    • Unified access modes (open, transparent, restricted) with access-mode selector in admin forms and API/GraphQL exposure.
  • Bug Fixes

    • Listings, visibility, alerts and follow-cleanup now respect access_mode; distinct messaging for restricted vs transparent spaces.
    • Open data, exports and serializers updated to emit access_mode consistently.
  • Chores

    • Removed legacy privacy flags, added migrations, translations and broad test updates.
  • UI

    • Newsletter recipient renamed from “private members” to “members” across UI and delivery flow.

github-actions[bot]
github-actions bot previously approved these changes Jan 16, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates Assemblies and Participatory Processes from using separate private_space and is_transparent boolean attributes to a unified access_mode enum with three values: Open, Restricted, and Transparent. The change replaces checkbox controls with radio buttons for better UX and simpler logic.

Changes:

  • Adds access_mode enum column to both assemblies and participatory processes
  • Replaces checkbox UI controls with radio buttons for access mode selection
  • Updates permissions, visibility checks, and serializers to use the new enum
  • Updates admin views, forms, locales, and specs to reflect the new access model

Reviewed changes

Copilot reviewed 43 out of 43 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
decidim-participatory_processes/db/migrate/20260111120010_add_access_mode_to_participatory_processes.rb Adds access_mode integer column to participatory processes
decidim-assemblies/db/migrate/20260111120000_add_access_mode_to_assemblies.rb Adds access_mode integer column to assemblies
decidim-participatory_processes/app/models/decidim/participatory_process.rb Defines access_mode enum with open and restricted values
decidim-assemblies/app/models/decidim/assembly.rb Defines access_mode enum with open, transparent, and restricted values; updates visibility logic
decidim-participatory_processes/app/forms/decidim/participatory_processes/admin/participatory_process_form.rb Replaces private_space attribute with access_mode
decidim-assemblies/app/forms/decidim/assemblies/admin/assembly_form.rb Replaces private_space and is_transparent attributes with access_mode
decidim-participatory_processes/app/commands/decidim/participatory_processes/admin/create_participatory_process.rb Updates to use access_mode instead of private_space
decidim-participatory_processes/app/commands/decidim/participatory_processes/admin/update_participatory_process.rb Updates to use access_mode instead of private_space
decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly.rb Updates to use access_mode instead of private_space and is_transparent
decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly.rb Updates to use access_mode instead of private_space and is_transparent
decidim-participatory_processes/app/views/decidim/participatory_processes/admin/participatory_processes/_form.html.erb Replaces checkbox with radio buttons for access mode
decidim-assemblies/app/views/decidim/assemblies/admin/assemblies/_form.html.erb Replaces two checkboxes with three radio buttons for access mode
decidim-participatory_processes/app/views/decidim/participatory_processes/admin/participatory_processes/_process_row.html.erb Updates display to show access mode instead of private/public
decidim-assemblies/app/views/decidim/assemblies/admin/assemblies/_assembly_row.html.erb Updates display to show access mode with transparent option
decidim-participatory_processes/app/serializers/decidim/participatory_processes/participatory_process_serializer.rb Serializes access_mode instead of private_space
decidim-assemblies/app/serializers/decidim/assemblies/assembly_serializer.rb Serializes access_mode instead of private_space and is_transparent
decidim-assemblies/app/serializers/decidim/assemblies/assembly_importer.rb Imports access_mode attribute
decidim-core/lib/decidim/participatory_space_resourceable.rb Updates visible? check to use open? and transparent?
decidim-core/lib/decidim/participatory_space/has_members.rb Updates public_spaces and private_spaces scopes
decidim-core/app/models/decidim/component.rb Updates access checks to use restricted? and transparent?
decidim-participatory_processes/app/permissions/decidim/participatory_processes/permissions.rb Updates permissions to check restricted? and transparent?
decidim-assemblies/app/permissions/decidim/assemblies/permissions.rb Simplifies permissions check for restricted access
decidim-participatory_processes/config/locales/en.yml Adds access mode translations
decidim-assemblies/config/locales/en.yml Adds access mode translations with transparent option
decidim-assemblies/spec/types/assembly_type_spec.rb Updates GraphQL spec to test accessMode field
decidim-assemblies/spec/system/private_assemblies_spec.rb Updates specs to use access_mode attribute
Comments suppressed due to low confidence (1)

decidim-core/lib/decidim/participatory_space/has_members.rb:43

  • The method private_space? no longer exists after the migration to access_mode. This should be changed to return true if open? or return true unless restricted?.
          return true unless private_space?

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

github-actions[bot]
github-actions bot previously approved these changes Jan 16, 2026
github-actions[bot]
github-actions bot previously approved these changes Jan 17, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces legacy boolean pair private_space / is_transparent with a new access_mode enum (open / transparent / restricted) across models, migrations, forms, serializers, API/GraphQL types, views, helpers, jobs, rake tasks and extensive tests; also renames newsletter/private-members surface to members. (50 words)

Changes

Cohort / File(s) Summary
Models & scopes
decidim-assemblies/app/models/.../assembly.rb, decidim-participatory_processes/app/models/.../participatory_process.rb, decidim-core/lib/decidim/participatory_space/has_members.rb, decidim-core/lib/decidim/participatory_space_resourceable.rb
Add ACCESS_MODES + enum :access_mode; replace private_space?/is_transparent? logic with open?/transparent?/restricted?; update scopes, visibility predicates and ransack exposure.
Migrations & data migrations
db/migrate/*add_access_mode_to_*.rb, db/data/*replace_legacy_fields_to_access_mode*.rb
Add integer access_mode columns with defaults; backfill access_mode from legacy private_space/is_transparent; some migrations define local AR classes for safe resets.
Forms, commands & controllers
*/forms/*_form.rb, */commands/*_create*.rb, */commands/*_update*.rb, */controllers/*_controller.rb
Replace :private_space/:is_transparent with :access_mode in fetch_form_attributes, permitted params and command inputs; add access_mode attribute and validations to forms.
Admin UI, views & partials
decidim-assemblies/app/views/.../_form.html.erb, .../_assembly_row.html.erb, .../_assemblies_thead.html.erb, decidim-assemblies/app/views/.../show.html.erb, decidim-admin/app/cells/.../attachments_privacy_warning/show.erb
Replace boolean controls with an access_mode radio group; templates render access_mode labels and separate alerts for restricted/transparent; update headers, data-labels and privacy warnings.
Serializers & importers
decidim-assemblies/.../assembly_serializer.rb, .../assembly_importer.rb, participatory_processes/.../participatory_process_serializer.rb, .../participatory_process_importer.rb
Serializers emit access_mode; importers add resolve_access_mode(attributes) to map legacy private_space/is_transparent to access_mode.
API / GraphQL types
decidim-api/lib/decidim/api/types/access_mode_enum.rb, decidim-assemblies/lib/decidim/api/assembly_type.rb, decidim-participatory_processes/lib/decidim/api/participatory_process_type.rb
Add AccessModeEnum and expose access_mode field; remove private_space/is_transparent GraphQL fields.
Permissions, helpers & predicates
decidim-assemblies/app/permissions/*, decidim-participatory_processes/app/permissions/*, decidim-core/app/controllers/concerns/*, decidim-core/app/helpers/menu_helper.rb, decidim-core/app/models/decidim/component.rb
Replace visibility checks with restricted?/transparent?; add/rename predicates (e.g., restricted_space?), guard calls with respond_to?, and adjust admin checks to admin?.
Jobs, commands & rake tasks
decidim-admin/app/commands/.../destroy_member.rb, decidim-admin/app/jobs/.../destroy_members_follows_job.rb, decidim-core/lib/tasks/upgrade/fix_deleted_members_follows.rake
Gate follow-deletion/cleanup on restricted? and transparent? checks; rename rake task and descriptions to members-focused wording.
Newsletter & recipients surface
decidim-admin/app/forms/.../selective_newsletter_form.rb, .../newsletters_controller.rb, .../newsletters_helper.rb, .../newsletter_job.rb, app/packs/src/.../newsletters.js, views, locales
Rename send_to_private_memberssend_to_members across form attribute, validations, permitted params, job extended_data, JS selectors, views, helpers and locales.
Tests, factories & specs
spec/**/*, */test/factories.rb
Extensive test updates and new shared_examples: replace private/private+transparent fixtures with access_mode traits (:open/:transparent/:restricted), update serializer/GraphQL expectations, add migration specs and new system specs for access modes.
Open Data & dev assets
*/open_data_*_serializer.rb, decidim-dev/lib/decidim/dev/assets/*
Open data serializers include access_mode; dev JSON fixtures updated to use access_mode strings instead of legacy booleans.
Presenters & logs
decidim-core/app/presenters/decidim/log/value_types/access_mode_presenter.rb, .../admin_log/*_presenter.rb
Add AccessModePresenter for log rendering; admin-log presenters include access_mode mapping for diffs.
Meetings, cells & UI helpers
decidim-meetings/.../online_meeting_cell.rb, decidim-meetings/.../_linked_spaces.html.erb, various helper/cell predicate renames
Rename predicates (private_non_transparent_space?restricted_space?, private_transparent_assembly?transparent_assembly?), update guards, warnings and translations.

Sequence Diagram(s)

sequenceDiagram
    participant AdminUI as Admin UI
    participant Controller as Controller
    participant Command as Command/Service
    participant Model as Model
    participant DB as Database
    rect rgba(0,128,0,0.5)
    AdminUI->>Controller: submit form(access_mode)
    Controller->>Command: invoke create/update with access_mode
    Command->>Model: build model(access_mode: value)
    Model->>DB: persist access_mode column
    DB-->>Model: persisted
    Command-->>Controller: return result
    Controller-->>AdminUI: render success/failure
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

type: change

Suggested reviewers

  • alecslupu

Poem

"I’m a rabbit in the migrations glen,
I hopped those booleans into modes again.
Open, transparent, restricted three—
members, hops, and specs in harmony.
Migrations done—hip hop hooray!"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/enum-access-mode-spaces

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
decidim-assemblies/app/serializers/decidim/assemblies/assembly_importer.rb (1)

38-59: Backward compatibility concern: importer still expects old attributes that are no longer exported.

The serializer now exports only access_mode (OpenDataAssemblySerializer line 42), but the importer still attempts to set private_space (line 38) and is_transparent (line 49) from import data. This creates a mismatch:

  • New exports won't have private_space/is_transparent — they'll be nil in imported data
  • The old attributes still exist in the database but are no longer part of the export format

While this won't cause failures (both columns allow nil), the importer should either:

  1. Remove the obsolete attributes if they're no longer needed
  2. Add logic to derive access_mode from old attributes for legacy data imports
🤖 Fix all issues with AI agents
In `@decidim-admin/app/cells/decidim/admin/attachments_privacy_warning_cell.rb`:
- Around line 10-16: Update the private_space? and transparent_space? methods to
defensively guard calls to restricted? and transparent? using respond_to? like
other admin components: in private_space? check
current_participatory_space.respond_to?(:restricted?) before calling restricted?
and also check respond_to?(:transparent?) before calling transparent?, and in
transparent_space? check respond_to?(:transparent?) before calling transparent?
so the cell no longer assumes those predicate methods always exist on
current_participatory_space.

In
`@decidim-assemblies/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb`:
- Line 47: The admin log currently shows raw integers for access_mode; add a
custom presenter for access_mode in
decidim::assemblies::admin_log::AssemblyPresenter (following the existing :area
and :assembly_type presenters) that maps integer values to their localized enum
labels (e.g., using the same I18n lookup pattern/function used by
:area/:assembly_type) so diffs display human-friendly strings like "open",
"transparent", "restricted" instead of 0/1/2.

In `@decidim-assemblies/spec/types/integration_schema_spec.rb`:
- Line 41: The test's expected assembly_data includes "accessMode" but the
GraphQL queries still request the old fields isTransparent and privateSpace,
causing mismatch or failing queries; update both the GraphQL query strings used
for the assemblies list (the "assemblies" query) and the single assembly query
(the "assembly(id:)" query) to request accessMode instead of (or in addition to)
isTransparent/privateSpace so the response will include accessMode and match
assembly_data, and ensure any assertions reference assembly_data["accessMode"]
accordingly.

In `@decidim-core/app/helpers/decidim/menu_helper.rb`:
- Around line 75-79: Update HasMembers#can_participate? to use the new
access_mode enum check by replacing any private_space? usage with restricted?
(i.e., change HasMembers#can_participate? to return false when restricted? and
the user is not a member), and ensure calls like
remove_private_space_if_not_member(process) remain consistent by keeping its
current restricted? check; additionally add a data migration that iterates
existing records and sets access_mode based on the legacy private_space boolean
(e.g., access_mode = :restricted when private_space is true, otherwise :open) so
tests and runtime behavior remain correct before removing the private_space
column.

In `@decidim-core/lib/decidim/participatory_space/has_members.rb`:
- Around line 49-55: The current self.public_spaces method incorrectly chains
open.transparent.published (AND semantics); instead make it select spaces whose
access_mode is either open OR transparent and published. Update the method
(referencing self.public_spaces and the scopes/methods open, transparent,
published and the access_mode enum) to, when respond_to?(:transparent) is true,
query for published records with access_mode in [open, transparent] (i.e. use an
OR/IN query or merge a where(access_mode: [...]) rather than chaining scopes);
if transparent is not supported, fall back to the existing open.published
behavior.

In
`@decidim-participatory_processes/app/permissions/decidim/participatory_processes/permissions.rb`:
- Around line 132-137: The can_view_private_space? method currently blocks
unauthenticated access for transparent processes by combining
process.restricted? || process.transparent?; change the access check so only
restricted processes require a logged-in user (i.e., use process.restricted?
alone), leaving transparent processes publicly viewable; keep the rest of the
logic (user.admin?, user_has_any_role?(user, process, broad_check: true),
process.users.include?(user)) unchanged so that authenticated users still get
role/admin checks for restricted cases.
♻️ Duplicate comments (7)
decidim-participatory_processes/db/migrate/20260111120010_add_access_mode_to_participatory_processes.rb (1)

3-10: Missing data migration for existing records.

The migration adds the column but doesn't transform existing private_space and is_transparent values to the new access_mode enum. Per the PR objectives, the mapping should be:

Old state New access_mode
private_space: false, is_transparent: false 0 (open)
private_space: false, is_transparent: true 1 (transparent)
private_space: true 2 (restricted)

Without data migration, all existing records default to 0 (open), potentially exposing previously restricted processes.

Proposed fix with data migration
 class AddAccessModeToParticipatoryProcesses < ActiveRecord::Migration[6.1]
   def up
     add_column :decidim_participatory_processes, :access_mode, :integer, null: false, default: 0
+
+    execute <<-SQL.squish
+      UPDATE decidim_participatory_processes
+      SET access_mode = CASE
+        WHEN private_space = true THEN 2
+        WHEN is_transparent = true THEN 1
+        ELSE 0
+      END
+    SQL
   end

   def down
     remove_column :decidim_participatory_processes, :access_mode
   end
 end

Verify if a separate data migration exists to handle this transformation:

#!/bin/bash
# Search for data migration handling access_mode transformation for participatory processes
rg -n -C5 'UPDATE.*decidim_participatory_processes.*access_mode|private_space.*access_mode' --type ruby
decidim-admin/app/jobs/decidim/admin/participatory_space/destroy_members_follows_job.rb (1)

10-12: Method name missing question mark on line 10.

The respond_to?(:transparent) check is inconsistent with the actual method call space.transparent? on line 12. This should be respond_to?(:transparent?).

Suggested fix
-          return unless space.respond_to?(:restricted?) || space.respond_to?(:transparent)
+          return unless space.respond_to?(:restricted?) || space.respond_to?(:transparent?)
decidim-admin/app/commands/decidim/admin/participatory_space/destroy_member.rb (1)

21-21: Method name missing question mark.

The respond_to?(:transparent) check should be respond_to?(:transparent?) to match the actual method being called.

Suggested fix
-          return if resource.participatory_space.respond_to?(:transparent) && resource.participatory_space.transparent?
+          return if resource.participatory_space.respond_to?(:transparent?) && resource.participatory_space.transparent?
decidim-assemblies/db/migrate/20260111120000_add_access_mode_to_assemblies.rb (1)

3-10: Missing data migration to backfill existing records.

The migration adds the column with default: 0 (open), but existing assemblies with private_space: true will incorrectly be set to open access instead of restricted/transparent. This could inadvertently expose previously private content.

Add SQL statements to map existing private_space and is_transparent values to the correct access_mode:

  • access_mode: 0 (open) when private_space = false
  • access_mode: 1 (transparent) when private_space = true AND is_transparent = true
  • access_mode: 2 (restricted) when private_space = true AND is_transparent = false
decidim-assemblies/app/models/decidim/assembly.rb (1)

100-103: Fix public_spaces scope chaining to avoid empty results.

open.transparent.published on Line 102 composes scopes with AND, which yields no records because a row can’t be both open and transparent. Use an OR or a single IN filter instead.

🐛 Proposed fix
-      open.transparent.published
+      where(access_mode: %i[open transparent]).published
decidim-participatory_processes/app/views/decidim/participatory_processes/admin/participatory_processes/_form.html.erb (1)

174-191: LGTM! All three access modes are now implemented.

The radio button group correctly includes all three access options (open, transparent, restricted), which aligns with the PR objectives and addresses the previous review feedback about the missing transparent option.

decidim-participatory_processes/app/views/decidim/participatory_processes/admin/participatory_processes/_process_row.html.erb (1)

17-24: LGTM! Transparent access mode is now handled.

The view correctly implements all three access mode states, addressing the previous review feedback about the missing transparent handling.

🧹 Nitpick comments (9)
decidim-participatory_processes/lib/decidim/participatory_processes/test/factories.rb (1)

60-66: New traits look correct, but consider updating the legacy :private trait for consistency.

The :transparent and :restricted traits correctly set the new access_mode attribute. However, the existing :private trait (lines 56-58) still sets private_space { true } using the old approach. Per the PR objectives, private_space: true maps to access_mode: :restricted.

Consider updating the :private trait to use the new access mode or deprecating it in favor of :restricted to avoid confusion in tests:

♻️ Suggested update to align `:private` trait
     trait :private do
-      private_space { true }
+      access_mode { :restricted }
     end

Alternatively, if backward compatibility is needed, deprecate :private and direct users to :restricted.

decidim-assemblies/db/migrate/20190215093700_reset_negative_children_count_counters.rb (1)

9-10: Prefer batched iteration to avoid loading all ids.

pluck loads all matching IDs into memory. Using find_each keeps this safe for large tables.

♻️ Proposed refactor
-    ids = Assembly.unscoped.where("children_count < 0").pluck(:id)
-    ids.each { |id| Assembly.unscoped.reset_counters(id, :children_count) }
+    Assembly.unscoped.where("children_count < 0").find_each do |assembly|
+      Assembly.unscoped.reset_counters(assembly.id, :children_count)
+    end
decidim-participatory_processes/db/migrate/20210310120750_add_followable_counter_cache_to_participatory_processes.rb (1)

4-6: Prefer ActiveRecord::Base for migration-local models.

This keeps migrations insulated from app-level concerns that might be mixed into ApplicationRecord.

♻️ Suggested change
-  class ParticipatoryProcess < ApplicationRecord
+  class ParticipatoryProcess < ActiveRecord::Base
     self.table_name = :decidim_participatory_processes
   end
decidim-admin/app/commands/decidim/admin/participatory_space/destroy_member.rb (1)

23-24: Comment is misleading.

The comment says "restricted or transparent spaces" but the code logic returns early if transparent (skipping the job), so it actually only runs for restricted non-transparent spaces.

Suggested fix
-          # When member is destroyed, a hook to destroy the follows of user on restricted or transparent spaces
+          # When member is destroyed, a hook to destroy the follows of user on restricted (non-transparent) spaces
           # and the follows of their children
decidim-participatory_processes/app/controllers/concerns/decidim/participatory_processes/admin/filterable.rb (1)

43-48: Duplicate private keyword and potential filter value mismatch.

  1. Line 44 declares private again, but line 14 already established a private section.
  2. The access_modes method returns the full hash (ACCESS_MODES), but scope_search_multi in the model is defined with ACCESS_MODES.keys (symbols). Depending on how the filter UI consumes this, you may want to return .keys for consistency.
♻️ Suggested fix
          def translated_decidim_participatory_process_group_id_eq(id)
            translated_attribute(Decidim::ParticipatoryProcessGroup.find(id).title)
          end

-          private
-
          def access_modes
-            ParticipatoryProcess::ACCESS_MODES
+            ParticipatoryProcess::ACCESS_MODES.keys
          end
decidim-participatory_processes/app/forms/decidim/participatory_processes/admin/participatory_process_form.rb (1)

34-36: Consider adding validation for access_mode.

The access_mode attribute is declared without validation. While Rails enums will raise an ArgumentError for invalid values, adding form-level validation provides better user feedback and prevents invalid submissions from reaching the model.

♻️ Suggested validation
        attribute :access_mode, String
        attribute :has_members, Boolean
        attribute :promoted, Boolean
+
+       validates :access_mode, inclusion: { in: Decidim::ParticipatoryProcess::ACCESS_MODES.keys.map(&:to_s) }
decidim-assemblies/app/views/decidim/assemblies/admin/assemblies/_form.html.erb (1)

208-225: Consider wrapping the radio group in a <fieldset> for semantics.

Line 209 already uses a legend; grouping these inputs with a fieldset improves accessibility semantics.

♻️ Suggested markup tweak
-      <div class="row column" id="access_mode">
-        <legend>
-          <%= t("access.label", scope: "decidim.assemblies.admin.assemblies.form") %>
-        </legend>
-        <div class="radio-group">
+      <div class="row column" id="access_mode">
+        <fieldset class="radio-group">
+          <legend>
+            <%= t("access.label", scope: "decidim.assemblies.admin.assemblies.form") %>
+          </legend>
           <%= label_tag nil, class: "form__wrapper-checkbox-label" do %>
             <%= form.radio_button :access_mode, :open %>
             <span><%= t("access.options.open", scope: "decidim.assemblies.admin.assemblies.form") %></span>
           <% end %>
           <%= label_tag nil, class: "form__wrapper-checkbox-label" do %>
             <%= form.radio_button :access_mode, :transparent %>
             <%= t("access.options.transparent", scope: "decidim.assemblies.admin.assemblies.form") %>
           <% end %>
           <%= label_tag nil, class: "form__wrapper-checkbox-label" do %>
             <%= form.radio_button :access_mode, :restricted %>
             <%= t("access.options.restricted", scope: "decidim.assemblies.admin.assemblies.form") %>
           <% end %>
-        </div>
+        </fieldset>
       </div>
decidim-assemblies/spec/serializers/decidim/assemblies/assembly_serializer_spec.rb (1)

35-35: LGTM!

The test correctly verifies that access_mode is included in the serialized output.

Consider adding additional test cases verifying serialization for each access mode variant (open, transparent, restricted) to ensure all enum values serialize correctly.

decidim-assemblies/app/views/decidim/assemblies/assemblies/show.html.erb (1)

19-22: LGTM!

The condition correctly uses restricted? to show the alert only when the assembly is restricted (members-only visibility), which matches the PR mapping where Restricted = only members can see and participate.

Consider updating the translation key from "private_space" to something like "restricted_space" for consistency with the new access mode terminology. This would help align user-facing text with the new "Restricted" concept.

github-actions[bot]
github-actions bot previously approved these changes Jan 21, 2026
github-actions[bot]
github-actions bot previously approved these changes Jan 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
decidim-core/lib/decidim/core/test/shared_examples/has_members.rb (1)

8-61: Add transparent access-mode coverage to the shared example.

Transparent spaces should be publicly visible; without a transparent fixture here, regressions in public/visible scopes could slip through. Consider adding a transparent_space and adjusting expectations accordingly.

🧪 Suggested test update
 let!(:open_space) do
   create(factory_name, access_mode: "open", published_at: Time.current)
 end
 
+let!(:transparent_space) do
+  create(factory_name, access_mode: "transparent", published_at: Time.current)
+end
+
 let!(:restricted_space) do
   create(factory_name, access_mode: "restricted", published_at: Time.current)
 end
@@
-    it { expect(scope).to eq([open_space]) }
+    it { expect(scope).to contain_exactly(open_space, transparent_space) }
@@
-      it { expect(scope).to contain_exactly(open_space) }
+      it { expect(scope).to contain_exactly(open_space, transparent_space) }
@@
-      it { expect(scope).to contain_exactly(open_space) }
+      it { expect(scope).to contain_exactly(open_space, transparent_space) }
@@
-      it { expect(scope).to contain_exactly(open_space, restricted_space) }
+      it { expect(scope).to contain_exactly(open_space, transparent_space, restricted_space) }
@@
-      it { expect(scope).to contain_exactly(open_space) }
+      it { expect(scope).to contain_exactly(open_space, transparent_space) }
🤖 Fix all issues with AI agents
In `@decidim-core/lib/decidim/participatory_space/has_members.rb`:
- Around line 57-58: The private_spaces class method calls transparent
unconditionally which can raise NoMethodError for models without that scope;
update decidim::participatory_space::has_members#private_spaces to mirror
public_spaces by checking respond_to?(:transparent) and return
restricted.or(transparent) only when transparent exists, otherwise return
restricted alone so models without the transparent scope don't error.

In
`@decidim-participatory_processes/lib/decidim/api/participatory_process_type.rb`:
- Line 18: Update the field description for :access_mode to accurately reflect
all enum values; the current description "(open or restricted)" omits the
TRANSPARENT option. Locate the declaration field :access_mode,
Decidim::Api::Types::AccessModeEnum in participatory_process_type.rb and change
the human-readable description to include "open, transparent or restricted" (or
equivalent wording that lists all three enum values) so API docs match the
AccessModeEnum.
🧹 Nitpick comments (6)
decidim-assemblies/spec/forms/assembly_form_spec.rb (1)

86-87: Consider asserting the access_mode default/validity in this spec.

Now that access_mode drives visibility, a small expectation (e.g., defaulting to "open" or rejecting invalid values) would guard regressions.

Also applies to: 151-152

decidim-assemblies/spec/system/assemblies_spec.rb (2)

259-273: Align test naming with the new access_mode terminology.

The context and variable names still use “private/transparent”, which no longer matches the access_mode model. Consider renaming for clarity and consistency.

♻️ Suggested rename
-context "when the assembly has children private and transparent assemblies and related assemblies block is active" do
-  let!(:private_transparent_child_assembly) { create(:assembly, organization:, parent: assembly, access_mode: :transparent) }
-  let!(:private_transparent_unpublished_child_assembly) { create(:assembly, :unpublished, organization:, parent: assembly, access_mode: :transparent) }
+context "when the assembly has children transparent assemblies and related assemblies block is active" do
+  let!(:transparent_child_assembly) { create(:assembly, organization:, parent: assembly, access_mode: :transparent) }
+  let!(:transparent_unpublished_child_assembly) { create(:assembly, :unpublished, organization:, parent: assembly, access_mode: :transparent) }
@@
-    expect(page).to have_link translated(private_transparent_child_assembly.title)
-    expect(page).to have_no_link translated(private_transparent_unpublished_child_assembly.title)
+    expect(page).to have_link translated(transparent_child_assembly.title)
+    expect(page).to have_no_link translated(transparent_unpublished_child_assembly.title)

276-287: Rename “private and not transparent” to “restricted” for clarity.

This block still uses the old model naming. Updating it to “restricted” will keep test intent aligned with the access_mode enum.

♻️ Suggested rename
-context "when the assembly has children private and not transparent assemblies" do
-  let!(:private_child_assembly) { create(:assembly, organization:, parent: assembly, access_mode: :restricted) }
-  let!(:private_unpublished_child_assembly) { create(:assembly, :unpublished, organization:, parent: assembly, access_mode: :restricted) }
+context "when the assembly has children restricted assemblies" do
+  let!(:restricted_child_assembly) { create(:assembly, organization:, parent: assembly, access_mode: :restricted) }
+  let!(:restricted_unpublished_child_assembly) { create(:assembly, :unpublished, organization:, parent: assembly, access_mode: :restricted) }
decidim-api/lib/decidim/api/test/component_context.rb (1)

128-138: Duplicate test context detected.

There are two identical "when user is member" context blocks at lines 128-132 and 134-138. This appears to be a copy-paste duplication that adds redundant test coverage.

♻️ Proposed fix
       context "when user is member" do
         let!(:current_user) { create(:user, :confirmed, organization: current_organization) }
         let!(:member) { create(:member, user: current_user, participatory_space: participatory_process) }
         it_behaves_like "graphQL visible resource"
       end

-      context "when user is member" do
-        let!(:current_user) { create(:user, :confirmed, organization: current_organization) }
-        let!(:member) { create(:member, user: current_user, participatory_space: participatory_process) }
-        it_behaves_like "graphQL visible resource"
-      end
-
       context "when user is normal user" do
decidim-participatory_processes/spec/types/integration_schema_spec.rb (1)

274-329: Add a transparent process to actually exercise the new access mode.

The context name mentions transparent spaces, but none are created. This misses coverage for the “visible but members-only participation” path.

♻️ Suggested test adjustment
       let!(:participatory_process2) { create(:participatory_process, organization: current_organization) }
       let!(:participatory_process3) { create(:participatory_process, organization: current_organization) }
+      let!(:transparent_process) { create(:participatory_process, :transparent, organization: current_organization) }
       let!(:restricted_process) { create(:participatory_process, :restricted, organization: current_organization) }

@@
         expect(response["participatoryProcesses"]).to include(
           { "id" => participatory_process.id.to_s },
           { "id" => participatory_process2.id.to_s },
-          { "id" => participatory_process3.id.to_s }
+          { "id" => participatory_process3.id.to_s },
+          { "id" => transparent_process.id.to_s }
         )
@@
         expect(response["participatoryProcesses"]).to include(
           { "id" => participatory_process.id.to_s },
           { "id" => participatory_process2.id.to_s },
-          { "id" => participatory_process3.id.to_s }
+          { "id" => participatory_process3.id.to_s },
+          { "id" => transparent_process.id.to_s }
         )
@@
         expect(response["participatoryProcesses"]).to include(
           { "id" => participatory_process.id.to_s },
           { "id" => participatory_process2.id.to_s },
           { "id" => participatory_process3.id.to_s },
+          { "id" => transparent_process.id.to_s },
           { "id" => restricted_process.id.to_s }
         )
@@
         expect(response["participatoryProcesses"]).to include(
           { "id" => participatory_process.id.to_s },
           { "id" => participatory_process2.id.to_s },
           { "id" => participatory_process3.id.to_s },
+          { "id" => transparent_process.id.to_s },
           { "id" => restricted_process.id.to_s }
         )
decidim-participatory_processes/lib/decidim/participatory_processes/test/factories.rb (1)

55-61: Consider adding an :open trait for consistency with the three-access-mode model.

The ParticipatoryProcess model defines three access modes (open, transparent, restricted) via the enum ACCESS_MODES = { open: 0, transparent: 1, restricted: 2 }, with open as the default. The factory currently includes only :transparent and :restricted traits. Adding an explicit :open trait would improve test clarity and make the access mode explicit across all three cases.

Suggested addition
+    trait :open do
+      access_mode { :open }
+    end
+
     trait :transparent do
       access_mode { :transparent }
     end

github-actions[bot]
github-actions bot previously approved these changes Jan 23, 2026
github-actions[bot]
github-actions bot previously approved these changes Jan 23, 2026
github-actions[bot]
github-actions bot previously approved these changes Jan 23, 2026
coderabbitai[bot]
coderabbitai bot previously requested changes Mar 19, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@decidim-assemblies/app/views/decidim/assemblies/admin/assemblies/_form.html.erb`:
- Line 206: The view is referencing the top-level constant
Assembly::ACCESS_MODES which is incorrect; replace that with the fully-qualified
model reference used elsewhere—use Decidim::Assembly.access_modes.keys (matching
assembly_form.rb) in the loop that currently reads
Assembly::ACCESS_MODES.keys.each do |mode| so the form iterates the canonical
enum values from Decidim::Assembly.
- Around line 201-212: The legend element must be the first child of a fieldset
to semantically bind the radio buttons; wrap the existing radio group (the div
with id "access_mode" that iterates Assembly::ACCESS_MODES.keys and renders
form.radio_button) inside a <fieldset>, move the current <legend> to be the
first child of that fieldset, and transfer the id "access_mode" (or add it) onto
the fieldset so the group is correctly identified for assistive tech; keep the
label_tag block and form.radio_button usage intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4cadc992-6b5b-48c1-b752-e04160a9807e

📥 Commits

Reviewing files that changed from the base of the PR and between f4d5162 and aa534f8.

📒 Files selected for processing (1)
  • decidim-assemblies/app/views/decidim/assemblies/admin/assemblies/_form.html.erb

github-actions[bot]
github-actions bot previously approved these changes Mar 19, 2026
github-actions[bot]
github-actions bot previously approved these changes Mar 19, 2026
github-actions[bot]
github-actions bot previously approved these changes Mar 19, 2026
github-actions[bot]
github-actions bot previously approved these changes Mar 19, 2026
github-actions[bot]
github-actions bot previously approved these changes Mar 19, 2026
Copy link
Copy Markdown
Contributor

@alecslupu alecslupu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - Merging with Codecov failing pipeline.

Copy link
Copy Markdown
Contributor

@alecslupu alecslupu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a double check, i have found a bug, where the non members can add comments to transparent space.

To reproduce:

  1. Visit the nightly, login as admin.
  2. Identify an assembly, mark it as transparent
  3. Login in another browser with user1...
  4. See that you cannot add any comments to resources in that space

On develop:

  1. visit any space.
  2. mark it as transparent
  3. login as user@example ...
  4. See that you can add comments even though you should not be able to .

@alecslupu
Copy link
Copy Markdown
Contributor

alecslupu commented Mar 20, 2026

After a double check, i have found a bug, where the non members can add comments to transparent space.

The problem seems to be decidim-core/app/models/decidim/component.rb line 107, which, when removed will make the things work as expected.

github-actions[bot]
github-actions bot previously approved these changes Mar 24, 2026
@andreslucena
Copy link
Copy Markdown
Member Author

After a double check, i have found a bug, where the non members can add comments to transparent space.

Nice catch!

I fixed it:

image

I added specs for this "edge case" as it is an important part of the "Transparent" feature (basically the main aspect of it!!)

@andreslucena
Copy link
Copy Markdown
Member Author

This is ready for another round @alecslupu

Copy link
Copy Markdown
Contributor

@alecslupu alecslupu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment