Restore default on model features access levels
What does this MR do and why?
Restores the DB-level DEFAULT 20 (ENABLED) on
project_features.model_registry_access_level and
model_experiments_access_level.
!241157 (merged) dropped these
defaults (post-deploy migration 20260617130000) in the same release that
moved default population into a ProjectFeature after_initialize callback.
During the rolling deploy, application nodes still running the previous release
omit these columns from INSERTs and relied on the now-removed default,
inserting NULL into NOT NULL columns and raising PG::NotNullViolation.
This broke project creation in staging (qa-smoke /
ResourceFabricationFailedError, GitLab API 400).
Failing row (note the two trailing NULLs — only model_experiments and
model_registry, every other column populated):
PG::NotNullViolation: null value in column "model_experiments_access_level" ...
DETAIL: Failing row contains (..., null, null).Why restore DEFAULT 20 rather than drop NOT NULL?
- It stops the violation for any insert path that omits the column — robust regardless of whether the source is an un-upgraded node, a bulk insert, or a code gap.
- No NULL rows to back-fill: the
NOT NULLconstraint failed the bad inserts, so nothing persisted. DroppingNOT NULLwould instead permit NULLs and permanently loosen the schema. 20is the only safe static default: it is correct for public projects (open read) and, on non-public projects,ProjectPolicyalready gatesread_model_registry/read_model_experimentsto members (~public_project & guest), soENABLEDvsPRIVATEis observably identical. A staticPRIVATEdefault would instead break read on public projects.
This is a metadata-only change; existing rows are untouched and observable visibility is unchanged.
Follow-up
The visibility-based default should be re-introduced correctly across releases: keep the default while the populating callback ships, then drop it in a later release after that code is fully deployed everywhere, per https://docs.gitlab.com/development/database/avoiding_downtime_in_migrations/#changing-column-defaults