ADR 0023 — Federated GitLab group and repo ownership model

The GitLab side of ADR 0015: two top-level group trees (comptech-platform/ and divisions/), eleven ct-* role groups, eight operational repos, code-owner-enforced protected branches, and a fixed review-approver table.

Date: 2026-05-10 Status: Accepted. Implementation detail of ADR 0015; enforces the OpenShift platform boundary that ADR 0024 locks in.

Context

ADR 0015 accepted a federated GitOps repository architecture and named the ownership boundaries between OpenShift platform state, VM-hosted platform tools, and application delivery. What it deferred was the concrete GitLab side: group layout, role-group naming, project ownership, protected-branch rules, runner classes, and review expectations. Issue #68 under the Federated GitOps Architecture milestone required that those choices be formalized before more teams onboard.

The live GitLab is GitLab CE 18.11.1 on internal endpoint http://30.30.30.5, with the human-browser route at https://gitlab.apps.sub.comptech-lab.com. The initial federated group skeleton, the eleven ct-* role groups, the first operational repository (comptech-platform/openshift-ops/openshift-platform-gitops, project ID 12), and initial project shares are already in place; bootstrap implementation is tracked under readiness gate FG-1 (issue #83). This ADR locks the design choices behind that live state so future groups, repos, and teams are added against a documented baseline rather than ad-hoc operator judgement.

The planning artifacts already exist and remain the source of mechanics:

  • plans/federated-gitops-gitlab-access-matrix.md — group layout, repository inventory, role groups, branch protection, CI/runner matrix, promotion access.
  • plans/federated-gitops-gitlab-implementation-checklist.md — the execution sequence used to bring the design live.
  • connection-details/gitlab-operator-guide.md — the operator runbook for the live instance.

Decision

Adopt the federated GitLab group and repository model exactly as specified in the access matrix. The operator guide is the canonical source for live-state mechanics; this ADR locks the design choices behind it.

Group layout

Two sibling top-level group trees:

comptech-platform/
  openshift-ops/
  infra-ops/
  platform-services/
  tenant-registry/

divisions/
  <division>/

comptech-platform/ contains platform-owned operational state. divisions/ contains application-team state, organized one sub-group per division. The split prevents accidental write reach from application teams into platform repositories and gives the OpenShift/platform team a defensible namespace boundary.

Operational repositories

GitLab pathWrite ownerDefault readers
comptech-platform/openshift-ops/openshift-platform-gitopsOpenShift/platform team onlyplatform, security reviewers, auditors
comptech-platform/openshift-ops/openshift-cluster-buildOpenShift/platform team onlyplatform, auditors
comptech-platform/infra-ops/vm-platform-opsInfra/platform tools teamOpenShift/platform read, security reviewers, auditors
comptech-platform/platform-services/platform-tools-iacInfra/platform tools teamplatform read
comptech-platform/platform-services/platform-tools-configInfra/platform tools teamplatform read
comptech-platform/tenant-registry/openshift-tenantsOpenShift/platform teamtenant owners by approval
divisions/<division>/<division>-apps-monorepoDivision app teamplatform/CI/security as needed
divisions/<division>/<division>-gitopsDivision app team inside guardrailsOpenShift/platform retains maintainer for guardrails and emergency rollback

Application teams have no write access to openshift-platform-gitops, openshift-cluster-build, vm-platform-ops, platform-tools-iac, platform-tools-config, openshift-tenants, or any platform runner or admin configuration repository.

Creation order

Not every repository must exist immediately. The accepted creation order is:

  1. openshift-platform-gitops (live, project ID 12).
  2. vm-platform-ops when ownership and first service adoption are ready.
  3. openshift-cluster-build when cluster-build artifacts are ready to split out of planning docs.
  4. platform-tools-iac, platform-tools-config, and openshift-tenants only when their split proves useful — defer otherwise.
  5. Division repositories as teams onboard, one division pair per onboarding event.

Role groups

Eleven ct-* GitLab groups are the unit of access. Individual users join role groups, not projects, except for tightly scoped temporary exceptions recorded against an issue.

Role groupGitLab roleScope
ct-gitlab-adminsOwnertop-level operational groups; very small admin group
ct-openshift-platform-maintainersMaintaineropenshift-ops/*, tenant boundaries
ct-openshift-platform-reviewersReporter or DeveloperOpenShift platform review/read
ct-infra-platform-maintainersMaintainerinfra-ops/*, selected platform-services/*
ct-infra-platform-reviewersReporter or Developerinfra review/read
ct-cicd-platform-maintainersMaintainerCI templates, runner config, Jenkins shared libraries
ct-security-reviewersReporter or Developerplatform and app GitOps policy/security review
ct-auditorsReporterselected operational repos, read-only
ct-<division>-app-maintainersMaintainerdivision source and app GitOps repos only
ct-<division>-developersDeveloperdivision app source repos
ct-<division>-release-approversDeveloper or Maintainerdivision app GitOps promotion paths

The bootstrap sandbox already has ct-sandbox-app-maintainers, ct-sandbox-developers, and ct-sandbox-release-approvers instantiated under this pattern.

Initial project shares

openshift-platform-gitops (project ID 12) is shared with:

  • ct-openshift-platform-maintainers: Maintainer.
  • ct-openshift-platform-reviewers: Reporter.
  • ct-security-reviewers: Reporter.
  • ct-auditors: Reporter.

ct-sandbox-* groups have no platform-GitOps access. The same share pattern is applied to each new operational repository at creation time.

Branch protection baseline

Every operational repository runs with:

  • default branch main, protected;
  • force push disabled;
  • direct push to main disabled except for named break-glass maintainers;
  • merge-request flow required for normal changes;
  • one approval for non-production repos, two for production-impacting repos;
  • code-owner approval required for protected paths;
  • pipeline required before merge where validation jobs exist;
  • stale-approval dismissal enabled for production-impacting repos where the GitLab edition supports it;
  • MR templates for platform, infra, runner, and release repos.

Production-impacting repositories are openshift-platform-gitops, openshift-cluster-build, vm-platform-ops, and production application GitOps paths.

Review rules

Minimum approval expectations are fixed:

Change typeRequired approvers
OpenShift cluster-wide operator/platform changeOpenShift maintainer + second platform reviewer
Tenant onboarding or namespace policy changeOpenShift maintainer + tenant owner acknowledgement
Production AppProject/RBAC/NetworkPolicy changeOpenShift maintainer + security reviewer
VM platform tool changeInfra maintainer + service owner
HAProxy or PowerDNS production-impacting changeInfra maintainer + affected service owner
GitLab/Jenkins/Nexus admin/config changeInfra maintainer + CI/CD maintainer where relevant
GitLab Runner privilege/tag changeInfra maintainer + CI/CD maintainer + security reviewer
App build template changeCI/CD maintainer + app representative
App production promotionApp release approver + required pipeline evidence

CODEOWNERS files express path-level review ownership and complement the project shares. The CODEOWNERS baselines for openshift-platform-gitops, future vm-platform-ops, and division app GitOps repositories are defined in the operator guide and the access matrix; this ADR locks them in by reference.

Endpoints

The internal LAN endpoint http://30.30.30.5 is the only endpoint used by automation, Argo CD, Jenkins, GitLab Runner, and platform tooling. The public route https://gitlab.apps.sub.comptech-lab.com is for human browser access only. This boundary is part of the ownership model because public-route use by automation breaks the network assumption the access controls rely on.

Alternatives considered

Single super-group. Put every repository under one top-level GitLab group with role groups distinguishing ownership. Rejected — a single group makes it easy to accidentally grant a role group too broadly and removes the visual boundary between platform-owned and division-owned state. The two-tree split is cheap to operate and gives platform a defensible namespace.

Flat repo model. Skip the openshift-ops/, infra-ops/, platform-services/, and tenant-registry/ sub-groups and put every platform repository at the same level under comptech-platform/. Rejected — it forces every project share to be per-repository and removes the ability to apply a maintainer/reviewer group share at the sub-group level. The current sub-group structure makes the share model tractable.

Per-team ownership of everything. Give each application division a maintainer role on platform repositories so their CI can perform direct cluster changes when needed. Rejected — it violates ADR 0015’s core ownership boundary and would make the OpenShift GitOps pull model in ADR 0018 unenforceable. Application changes flow through application GitOps repositories, constrained by Argo CD AppProjects and namespace policy owned by the platform team.

Defer the formal model until more divisions exist. Operate the current single live division (sandbox) informally and only write the ADR when a second division onboards. Rejected — issue #68’s acceptance criterion was explicit that repo/group names, owners, write permissions, protected branches, and review rules must be documented before more teams are onboarded.

Consequences

Easier

  • New divisions onboard against a fixed group/repo template rather than operator recollection.
  • Access reviews scan eleven ct-* groups instead of per-project user lists.
  • Application teams move independently inside their division repositories without touching platform state.
  • The OpenShift platform team retains a single defensible boundary for cluster, tenant, and policy state.
  • Audit and security review have a documented baseline to compare live GitLab state against, making drift detection straightforward.

Harder

  • More groups and repositories than a single monorepo. Initial setup for a new division is multi-step and must follow the onboarding sequence in the operator guide.
  • CODEOWNERS, project shares, and protected branches must be applied consistently at every repo’s creation, or the model silently weakens.
  • GitLab CE may not support every approval-rule feature the review table assumes. Where a rule cannot be enforced natively, compensating controls (CODEOWNERS, protected branches, validation pipelines, MR evidence) must be recorded.

Residual decisions

The access matrix records the following as open and they are not resolved here:

  • Final naming for the existing ct-* role groups if the eleven-group list proves too coarse or too fine in practice.
  • Whether openshift-tenants should be a separate repository or a folder inside openshift-platform-gitops for the first phase. The access matrix describes it as optional; this ADR does not force creation.
  • Whether platform-tools-iac and platform-tools-config should be separate repositories immediately or deferred until vm-platform-ops becomes too large.
  • Whether application GitOps repositories should be one per division or one per application for high-risk teams.
  • Whether production branches should require signed commits immediately or in a later hardening phase.

The GitLab CE merge-control and CODEOWNERS-enforcement decision noted in the operator guide remains open under FG-1 and is required to fully close issue #83.

The existing gitlab-vm-docker runner is not the future trusted platform runner. Until protected runner classes are created under the GitLab Runner Operating Model milestone, the runner side of this model is enforced by convention only.

References

  • Source: opp-full-plat/adr/0023-federated-gitlab-group-repo-ownership.md
  • Parent architecture decision: ADR 0015
  • OpenShift platform GitOps boundary: ADR 0024
  • ACM + OpenShift GitOps pull model: ADR 0018
  • Nexus-only supply chain: ADR 0019
  • Workspace execution governance: ADR 0016
  • Access matrix: opp-full-plat/plans/federated-gitops-gitlab-access-matrix.md
  • Implementation checklist: opp-full-plat/plans/federated-gitops-gitlab-implementation-checklist.md
  • Operator runbook: opp-full-plat/connection-details/gitlab-operator-guide.md
  • Readiness gates: opp-full-plat/plans/federated-gitops-readiness-gates.md
  • GitHub issues: zeshaq/opp-full-plat #68 (closed by this ADR), #83 (FG-1 implementation)

Last reviewed: 2026-05-12