Implement Organizations Read-Only Mode
## Problem statement We need to be able to disable write access to a given Organization while their migration (eg. to a Protocell) is in progress. This is **not** the same as instance-wide Maintenance Mode: the Organization's content (groups, projects, settings etc) should remain readable but not editable, with a banner indicating the Organization is in read-only mode. The design is formalized in [ADR 010: Organization Read-Only Mode](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/organization/decisions/010_organization_read_only_mode/). In summary: * A per-Organization state on `Organizations::Stateful`: `active → read_only_initialization → read_only` (and back), with a `reason` recorded for audit (migration, isolation, incident, billing, legal) * Enforcement keyed off `Current.organization` at every write surface: controllers, REST API (Grape), GraphQL mutations, `Gitlab::GitAccess`, Container Registry, LFS, and Sidekiq * Org-scoped Sidekiq jobs drain; cron workers skip read-only Organizations; BBMs are paused on the source Cell * A cutover readiness contract gates the data-copy step on a fully drained source Cell * An authentication exemption keeps sign-in working (existing `users` row updates allowed; new `users` row creation blocked) The POC (gitlab-org/gitlab!228743) validated the approach and will not be merged; production implementation builds on the merged unified state machine (gitlab-org/gitlab!230909). ## Exit criteria * Write requests (web UI, GraphQL mutations, REST API, git push, registry push, LFS upload) to an Organization in `read_only_initialization` or `read_only` fail with a structured error (`503` + `Retry-After` for time-bounded reasons, `403` otherwise); reads continue to work * Authentication remains available; no new `users` rows are created for a read-only Organization * Org-scoped Sidekiq jobs drain and cron workers skip the read-only Organization, observable via structured logs * A cutover readiness check reports when the source Cell is fully drained for the Organization * New pipelines are blocked and in-flight CI jobs are cancelled on entering read-only * All pages owned by the Organization show a prominent read-only banner * Rollout is gated by environment- and Organization-scoped feature flags, default-off on Self-Managed/Dedicated <!-- STATUS NOTE START --> ## Status 2026-07-09 # Organizations Read-Only Mode — Weekly Status *Read-only mode (writes paused while an Organization moves between Cells) advanced on two fronts: sign-in stays reachable with cascading auth writes now blocked, and the Sidekiq background-job org-scoping design is settled on a single pattern.* 🕐 **total hours spent this week by all contributors**: 20 ## 🎉 achievements * Rewrote ADR 010's Sidekiq org-scoping rule ([!20345](https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/20345), reviewed with Rutger) to standardize on the existing `Current.organization` job-payload context — one pattern, retiring the argument-derived resolver. * Opened [!243952](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243952) (reviewed by Ryan Cobb) to block cascading auth-time writes (SAML/LDAP group and Duo-seat sync) into a read-only Org's data while keeping sign-in exempt. * Opened [!243972](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243972) re-landing the remaining auth-controller exemptions so sign-in, SSO, and password-reset stay reachable while an Org is read-only. ## 🚫 blockers * [!243972](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243972) and [!244690](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/244690) have only GitLab Duo assigned — need a human maintainer review to merge. * ADR 010 rewrite [!20345](https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/20345) still needs DRI sign-off before the org-scoping decision can land. ## ▶️ next * Land [!20345](https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/20345), then merge [!244690](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/244690) removing the now-superseded `OrganizationResolver`. * Get human review and merge [!243972](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243972) and [!243952](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243952). * Start [#604826](https://gitlab.com/gitlab-org/gitlab/-/work_items/604826): resolve `Current.organization` for KAS agent-token and deploy-token requests (a read-only enforcement blind spot). * Continue `organization_read_only_enforcement` flag rollout ([#603377](https://gitlab.com/gitlab-org/gitlab/-/work_items/603377)) and follow-ups [#603918](https://gitlab.com/gitlab-org/gitlab/-/work_items/603918) / [#599101](https://gitlab.com/gitlab-org/gitlab/-/work_items/599101) (enqueue-time and cron org context). _Copied from https://gitlab.com/groups/gitlab-org/-/epics/20404#note_3539105606_ <!-- STATUS NOTE END -->
epic