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_singletonconstraint and theindex_ai_settings_on_singletonunique index. - Keeps the
singletoncolumn. It will be ignored and dropped in a later iteration. - Adds
validates :organization_id, uniqueness: true, allow_nil: trueonAi::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_settingswas database-enforced singleton, so duplicate non-nullorganization_idvalues cannot already exist. - The validation allows
nil, preserving compatibility whileorganization_idremains nullable. - The database unique index on
organization_idis already present from !226045 (merged).
References
- Issue: #531356
- Follows merged MR !226045 (merged), which added the nullable
organization_idcolumn, 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
-
Run the migration:
bundle exec rails db:migrate -
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 --checkbundle 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.