--- title: GitLab Groups & Visibility --- # GitLab Groups, Subgroups & Visibility This document describes how Themelio uses GitLab groups and subgroups to organize repositories ([models](../../terms/model), [datasets](../../terms/dataset), [spaces](../../terms/space)), and the visibility rules that govern access. ## Group Hierarchy Repositories are organized by resource type first, then by Waldur project slug: ``` /{type}/{project-slug}/{repo-name} ``` For example: ``` models/ ├── pharos-nlp/ (Waldur project namespace) │ ├── bert-greek (private project) │ └── gpt-el (public project) ├── climate-ai/ │ └── weather-forecast-v2 (internal project) datasets/ ├── pharos-nlp/ │ └── greek-corpus (public project) ├── climate-ai/ │ └── era5-subset (private project) spaces/ ├── pharos-nlp/ │ └── bert-greek-demo (public project) ``` Each Waldur project maps to a subgroup under every top-level type group. When a Waldur proposal is accepted and a project is created, the corresponding subgroups are provisioned automatically. ## Visibility Rules GitLab enforces a strict visibility hierarchy: **a child cannot be more visible than its parent**. | Level | Who can see | | ---------- | ------------------------------------ | | `private` | Explicit project/group members only | | `internal` | Any authenticated GitLab user | | `public` | Anyone, including anonymous visitors | For a repository to support all three visibility levels, both its parent subgroup and grandparent group must be `public`. This is why: - **Top-level groups** (`models`, `datasets`, `spaces`) are created as **public**. - **Project subgroups** (e.g., `models/pharos-nlp`) are created as **public**. - **Individual repositories** can then be set to `private`, `internal`, or `public` by the project members with sufficient permissions. ## Namespace Provisioning When a Waldur proposal is accepted, the GitLab site agent provisions the namespace: 1. **Create a public subgroup** under each top-level type group, named after the Waldur project slug (e.g., `models/pharos-nlp`, `datasets/pharos-nlp`, `spaces/pharos-nlp`). 2. **Sync membership** from Waldur to GitLab. Project owners get GitLab Owner role (50) on the subgroup; project members get Developer role (30). 3. **Add all platform users as Guest** to the top-level groups, so they can browse public and internal repositories across all namespaces. Waldur is authoritative for membership — the membership sync pod overwrites any GitLab-side role changes. ## Access Control Summary | Resource | Role | Effect | | ------------------------------------------------- | -------------------- | ---------------------------------------------------------------- | | Top-level group (`models`) | Guest | Can browse public/internal repositories across all namespaces | | Own project subgroup (`models/pharos-nlp`) | Owner | Full control: create repositories, manage members, change settings | | Other project subgroup (`models/climate-ai`) | Guest (inherited) | Can see public/internal repositories, no write access | | Repositories within own project | Owner or Developer | Can set visibility, push, rename, delete (based on role) | ## Operator Notes ### Initial Setup Top-level groups are created by `gitops/scripts/create-top-level-groups.sh` during deployment. This script requires: - `GITLAB_ORIGIN`: The GitLab instance URL - `ROOT_PAT`: A root user personal access token with `api` scope ### About "Internal" Visibility GitLab's `internal` visibility means any authenticated user on the GitLab instance can see the resource. Since Themelio authenticates all users through Keycloak/[MyAccessID](../../terms/myaccessid), `internal` effectively means "visible to all platform users but not to anonymous visitors". This can be useful for repositories that should be shared within the platform but not indexed publicly.