Remove singleton enforcement from ai_settings

What does this MR do and why?

Removes database-level singleton enforcement from ai_settings so the table shape can eventually support one row per organization:

  • Post-deploy migration drops the check_singleton constraint and the index_ai_settings_on_singleton unique index.
  • Keeps the singleton column. It will be ignored and dropped in a later iteration.
  • Adds validates :organization_id, uniqueness: true, allow_nil: true on Ai::Setting.

SingletonRecord and Ai::Setting.instance are intentionally left unchanged. This means Rails code still preserves the existing singleton behavior in this slice. The finalize iteration replaces SingletonRecord alongside NOT NULL, populate_sharding_key, and the default-organization test fixture work.

Database notes

Index removal

The removed index_ai_settings_on_singleton unique index exists to enforce the old single-row table shape. Keeping it would prevent the future one-row-per-organization shape even after organization_id exists.

The index is on a constant boolean column used only for singleton enforcement. The table remains small, and Rails-level SingletonRecord still preserves current single-row application behavior in this slice.

The replacement uniqueness guarantee is index_ai_settings_on_organization_id, added in !226045 (merged).

Validation safety

The new organization_id uniqueness validation should not break existing records:

  • Before this sequence, ai_settings was database-enforced singleton, so duplicate non-null organization_id values cannot already exist.
  • The validation allows nil, preserving compatibility while organization_id remains nullable.
  • The database unique index on organization_id is already present from !226045 (merged).

References

  • Issue: #531356
  • Follows merged MR !226045 (merged), which added the nullable organization_id column, unique index, foreign key, and single-row backfill.
  • Follows merged MR !243041 (merged), which added the org-scoped lookup API behind a disabled feature flag.

How to set up and validate locally

  1. Run the migration:

    bundle exec rails db:migrate
  2. Confirm the singleton constraint and index are gone:

    ApplicationRecord.connection.check_constraint_exists?(:ai_settings, 'check_singleton') # => false
    ApplicationRecord.connection.index_exists_by_name?(:ai_settings, 'index_ai_settings_on_singleton') # => false

Validation

  • git diff --check
  • bundle exec rspec ee/spec/models/ai/setting_spec.rb spec/migrations/db/post_migrate/20260630111100_remove_singleton_from_ai_settings_spec.rb

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Alper Akgun

Merge request reports

Loading