Add Organizations::Stateful concern with state machine

What does this MR do and why?

This MR does two things:

1. Introduce Organizations::Stateful

Introduces an Organizations::Stateful concern modelled after Namespaces::Stateful, but stripped of concepts that don't apply to organizations (ancestor hierarchy, archival, transfers, state preservation).

States

Value Name Description
0 active Default. Organization is fully operational.
1 deletion_scheduled Soft-deleted. Invisible to non-admins. Reversible.
2 deletion_in_progress Hard-deletion worker is running.

Events

Event From To
schedule_deletion active deletion_scheduled
start_deletion deletion_scheduled deletion_in_progress
cancel_deletion deletion_scheduled / deletion_in_progress active
reschedule_deletion deletion_in_progress deletion_scheduled

Key differences from Namespaces::Stateful

  • No ancestor hierarchy, archival, state preservation, or transfer
  • deletion_scheduled_at stored in a dedicated typed column (not JSONB)
  • Cancel always returns to active

Model changes

  • Organizations::Organization includes Organizations::Stateful and delegates deletion_error / deletion_error= to organization_detail

2. Extract shared Stateful:: concerns

Namespaces::Stateful and Organizations::Stateful share significant identical logic. This extracts the common parts into a top-level Stateful namespace under app/models/concerns/stateful/ so both domain concerns include it, eliminating the duplication.

What was extracted

Module Extracted methods
Stateful::TransitionContext transition_args, transition_user
Stateful::TransitionCallbacks update_state_metadata, set_deletion_schedule_data, clear_deletion_schedule_data, set_deletion_error_data, update_state_metadata_on_failure, build_transition_error_message
Stateful::TransitionValidation ensure_transition_user
Stateful::TransitionLogging log_transition, log_transition_failure

Template methods

The two places where domain-specific knowledge is needed are bridged by two template methods that each including concern defines:

  • stateful_detail — returns the associated detail record (namespace_details or organization_detail)
  • stateful_log_metadata — returns the base log hash (e.g. { message: 'Namespace state transition', namespace_id: id })

Side-effect: standardised logging key in Namespaces::Stateful

Namespaces::Stateful::TransitionLogging was using the deprecated user_id: log key. The shared Stateful::TransitionLogging uses Labkit::Fields::GL_USER_ID consistently, fixing this as part of the extraction.


Files changed

New (shared concerns)

  • app/models/concerns/stateful/transition_context.rb
  • app/models/concerns/stateful/transition_callbacks.rb
  • app/models/concerns/stateful/transition_validation.rb
  • app/models/concerns/stateful/transition_logging.rb

New (Organizations::Stateful main concern)

  • app/models/concerns/organizations/stateful.rb — includes all 4 shared modules directly; defines stateful_detail and stateful_log_metadata

Modified (Namespaces::Stateful)

  • app/models/concerns/namespaces/stateful.rb — replaces include TransitionContext / include TransitionLogging with the shared modules; adds stateful_detail and stateful_log_metadata
  • app/models/concerns/namespaces/stateful/transition_callbacks.rb — now include ::Stateful::TransitionCallbacks; retains transfer-only methods
  • app/models/concerns/namespaces/stateful/transition_validation.rb — now include ::Stateful::TransitionValidation; retains validate_ancestors_state

Deleted (replaced by shared modules)

  • app/models/concerns/namespaces/stateful/transition_context.rb
  • app/models/concerns/namespaces/stateful/transition_logging.rb
  • app/models/concerns/organizations/stateful/transition_context.rb
  • app/models/concerns/organizations/stateful/transition_callbacks.rb
  • app/models/concerns/organizations/stateful/transition_logging.rb
  • app/models/concerns/organizations/stateful/transition_validation.rb

Config

  • config/bounded_contexts.yml — registers Stateful under platform: (required by Gitlab/BoundedContexts RuboCop cop)

Specs

  • spec/models/concerns/organizations/stateful_spec.rb — enum, state machine states, valid/rejected transitions
  • spec/models/concerns/stateful/transition_context_spec.rb
  • spec/models/concerns/stateful/transition_validation_spec.rb
  • spec/models/concerns/stateful/transition_callbacks_spec.rb
  • spec/models/concerns/stateful/transition_logging_spec.rb
  • spec/models/concerns/namespaces/stateful/transition_logging_spec.rb — updated to Labkit::Fields::GL_USER_ID

Depends on Add state to organizations and organization_det... (!230540 - merged) • Rémy Coutable • 19.0 (adds state, deletion_scheduled_at, state_metadata columns).

Part of Add Organizations::Stateful concern with state ... (#594306 - closed) • Rémy Coutable • 19.0

MR acceptance checklist

  • I have evaluated the MR acceptance checklist for this MR.
Edited by Rémy Coutable

Merge request reports

Loading