GitLab Project Settings Standard¶
Canonical standard for GitLab estate governance, repository configuration, security posture, and lifecycle management across all Bluefly projects.
Related: Git Discipline, Git Standard (STD-016), Git Completion Contract (ES-GITCC), CI Portable Runner and Topology (ES-CI-RUNNER-TOPO-001), Auth & Secrets Constitution (STD-AUTH-001), Cedar Factory Authorization (STD-CEDAR-001).
1. Purpose¶
This standard defines the mandatory settings baseline, role profiles, security policies, branch topology rules, and audit/reconciliation procedures for all GitLab projects within the blueflyio namespace.
The objective is:
- Prevent configuration drift and accidental security exposure.
- Enforce immutable verification and branch protection.
- Establish least-privilege automation and credential boundaries.
- Standardize the project lifecycle from creation (master-template) to active maintenance and archival.
2. Authority Model¶
GitLab estate governance follows a strict hierarchy. Centralized enforcement takes precedence over repository-local configuration:
graph TD
A[GitLab Top-Level Group Settings] --> B[GitLab Security & Compliance Policies]
B --> C[GitLab Branch Rules & Push Rules]
C --> D[Master Template: Creation Baseline]
D --> E[Reconciliation Engine: blu-cli / API]
E --> F[Project-Specific Documented Exceptions]
| Layer | Authority / Mechanism | Scope | Responsibility |
|---|---|---|---|
| 1. Group Settings | GitLab UI / Group API (blueflyio) |
Group-wide | Enforce immutable global defaults (e.g. fork restrictions, 2FA, Duo lock). |
| 2. Security Policies | blueflyio/security-policies |
Scoped projects | Group-level Scan Execution Policies and Pipeline Execution Policies. |
| 3. Branch Rules | GitLab Branch Rules API | Per project / Branch | Restrict push, merge, force-push, and unprotect permissions. |
| 4. Master Template | blueflyio/master-template |
New projects | Gold-standard baseline for newly created repositories. |
| 5. Reconciliation | blu gitlab project reconcile / CLI |
Estate sweep | Detect drift, verify settings, and remediate existing projects one by one. |
| 6. Exceptions | Project receipt + Standard register | Exception only | Explicitly approved, time-bound deviations. |
3. Canonical Projects & Separation of Concerns¶
Four projects serve as distinct architectural anchors across the Bluefly platform. Their responsibilities must never be collapsed or conflated:
| Canonical Project | Role | Authority Boundary | What it is NOT |
|---|---|---|---|
blueflyio/master-template |
Project Creation Baseline | Defines repository skeleton, initial file structure, and default settings for new projects. | NOT the enforcement engine for existing projects. |
blueflyio/security-policies |
GitLab Security & Compliance | GitLab-native security policies: SAST, Secret Detection, Dependency Scanning, PEP. | NOT the implementation of application business logic. |
blueflyio/gitlab_components |
Reusable CI/CD Components | Catalog of reusable GitLab CI templates and pipeline components (minimal-ci, drupal-master, release-flow, etc.). |
NOT project-specific bespoke CI scripts. |
blueflyio/cedar-policies |
Application / Agent ABAC | Runtime authorization policies for ContractPlane, Gas City agents, and API gateways. | NOT GitLab project settings, branch protection, or git permissions. |
4. Project Profiles¶
Every repository in the estate must be classified under exactly one profile. Each profile inherits the BLUEFLY_BASELINE and adds justified delta rules:
┌─ INTERNAL_LIBRARY
├─ PUBLIC_LIBRARY
├─ DRUPAL_CONTRIB_READY
├─ DRUPAL_PRIVATE
├─ SERVICE
├─ DEPLOYABLE_APPLICATION
BLUEFLY_BASELINE ─────┼─ IAC
├─ DOCUMENTATION
├─ CI_COMPONENT
├─ SECURITY_POLICY
├─ POLICY_REPOSITORY
├─ MODEL_PROJECT
└─ ARCHIVED
Profile Matrix¶
| Profile | Visibility | Package Registry | Container Registry | Pages | Default Branch | Description / Delta |
|---|---|---|---|---|---|---|
INTERNAL_LIBRARY |
Private | Enabled | Disabled | Disabled | release/v0.1.x |
Internal packages (npm, composer). Publishes to GitLab Package Registry. |
PUBLIC_LIBRARY |
Public | Enabled | Disabled | Optional | release/v0.1.x |
Public open-source library. Public issues and MRs. |
DRUPAL_CONTRIB_READY |
Public / Private | Enabled | Disabled | Optional | release/v0.1.x |
Contrib-ready Drupal modules intended for Drupal.org sync (duadp, ottermon, etc.). |
DRUPAL_PRIVATE |
Private | Enabled | Disabled | Disabled | release/v0.1.x |
Internal Drupal modules, site templates, and private recipes. |
SERVICE |
Private | Optional | Enabled | Disabled | release/v0.1.x |
Backend services (APIs, collectors, background daemons). Publishes container images. |
DEPLOYABLE_APPLICATION |
Private | Optional | Enabled | Disabled | release/v0.1.x |
End-user apps, web interfaces, full Drupal site deployments. |
IAC |
Private | Disabled | Optional | Disabled | release/v0.1.x |
Infrastructure as Code (Terraform, Ansible, K8s manifests). Strict variables & runner locks. |
DOCUMENTATION |
Private / Public | Disabled | Disabled | Private / Public | release/v0.1.x |
Curated documentation repositories (BluCity-Docs). Pages enabled for documentation sites. |
CI_COMPONENT |
Private / Internal | Disabled | Disabled | Disabled | release/v0.1.x |
Shared CI catalog (gitlab_components). Component release flow enabled. |
SECURITY_POLICY |
Private | Disabled | Disabled | Disabled | main |
Group security policy repository (security-policies). Strict lock on mutation. |
POLICY_REPOSITORY |
Private | Optional | Disabled | Disabled | release/v0.1.x |
Machine-readable policies (cedar-policies, compliance schemas). |
MODEL_PROJECT |
Private | Enabled | Disabled | Disabled | release/v0.1.x |
Machine learning weights, MLflow models, training configurations. Model Registry enabled. |
ARCHIVED |
Private / Public | Read-only | Read-only | Disabled | Locked | Read-only retired project. Excluded from active security scans and CI pipelines. |
5. General Project Settings Baseline¶
All projects must conform to the following foundational settings:
| Setting | API Field | Baseline Value | Rationale |
|---|---|---|---|
| Visibility | visibility |
private (unless PUBLIC_LIBRARY / DRUPAL_CONTRIB_READY) |
Prevent accidental leak of proprietary source. |
| Default Branch | default_branch |
release/v0.1.x (or main for release-only/policy repos) |
Active feature/fix integration target. |
| Issues | issues_enabled |
true |
Issue tracking for requirements and beads context. |
| Merge Requests | merge_requests_enabled |
true |
Mandatory code delivery vector. |
| Wiki | wiki_enabled |
false |
BluCity-Docs is documentation authority; no competing wikis. |
| Snippets | snippets_enabled |
false |
Prevent untracked scratch/secret dumps. |
| Service Desk | service_desk_enabled |
false (unless public helpdesk) |
Reduce unmonitored inbound email surface. |
| Forking Access | forking_access_level |
disabled (internal) / enabled (public/contrib) |
Prevent unmonitored private forks. Group-level setting prevents external forks. |
| Auto DevOps | auto_devops_enabled |
false |
Standard pipelines use gitlab_components; avoid duplicate scans/deploys. |
6. Repository Settings & Push Rules¶
Push rules enforce commit sanity and prevent secret leakage at the pre-receive boundary:
| Rule | API Field / Setting | Baseline Value | Details |
|---|---|---|---|
| Prevent Secrets | prevent_secrets |
true |
GitLab pre-receive secret scanning blocks commits containing known credential formats. |
| Branch Name Regex | branch_name_regex |
^(?:(feature\/[0-9]+-[A-Za-z0-9._-]+...)) |
Standard prefix enforcement: feature/*, fix/*, chore/*, release/v0.N.x, main. |
| Deny Delete Tag | deny_delete_tag |
true |
Published tags are immutable release milestones. |
| Reject Unsigned Commits | reject_unsigned_commits |
false (until GPG estate rollout) |
Enforced per-environment when signing keys are provisioned. |
| Max File Size | max_file_size |
50 (MB) |
Prevent committing accidental large binaries/dumps into git history. |
7. Branch Rules & Protection¶
Bluefly enforces strict branch topology:
feature/*, fix/*, chore/* ──(MR + CI PASS)──► release/v0.1.x ──(Human Gate)──► main
Branch Rules Configuration¶
| Target Branch Pattern | Push Access | Merge Access | Force Push | Code Owner Approval Required | Unprotect Access |
|---|---|---|---|---|---|
release/v0.1.x |
No one (0) |
Developers + Maintainers (30) |
false |
true (where CODEOWNERS exists) |
Maintainers (40) |
release/* |
No one (0) |
Developers + Maintainers (30) |
false |
true |
Maintainers (40) |
main |
No one (0) |
Maintainers (40) |
false |
true |
Maintainers (40) |
- Direct Push:
No one(access_level: 0). ALL changes must enter through an MR. - Force Push:
allow_force_push: falseon all protected branches. - Promotion to
main: Maintainers only. Automation creates promotion MRs (release/v0.1.x → main) but does NOT auto-merge them.
8. Protected Tags¶
Tag naming indicates immutable releases:
| Tag Pattern | Create Access | Description |
|---|---|---|
v* |
Maintainers (40) / Release Automation Bot |
SemVer release tags (e.g. v0.1.5, v1.0.0). |
*-dev.* |
Maintainers (40) / CI Job Token |
Development sequence tags generated by release-flow. |
9. Merge Request Settings Baseline¶
| Setting | API Field | Baseline Value | Rationale |
|---|---|---|---|
| Pipeline Must Succeed | only_allow_merge_if_pipeline_succeeds |
true |
Red or unverified code must never enter protected branches. |
| Disallow Skipped Pipelines | allow_merge_on_skipped_pipeline |
false |
Prevent merging empty or un-evaluated changes. |
| Discussions Must Be Resolved | only_allow_merge_if_all_discussions_are_resolved |
true |
All reviewer and bot feedback must be addressed before merge. |
| Resolve Outdated Discussions | resolve_outdated_diff_discussions |
true |
Automatically resolve discussions when lines change. |
| Delete Source Branch | remove_source_branch_after_merge |
true |
Maintain a clean repository without abandoned feature branches. |
| Merge Pipelines | merge_pipelines_enabled |
true |
Test the merge commit result before landing. |
| Merge Trains | merge_trains_enabled |
true (where CI supports it) |
Serialize concurrent merges cleanly without race conditions. |
| Merge Method | merge_method |
rebase_merge (or merge per topology) |
Clean linear history on integration lines. |
| Squash Commits | squash_option |
default_on / always |
Consolidate feature branch WIP commits into coherent units. |
10. Merge Request Approvals Baseline¶
Merge approval rules ensure peer and code-owner review while preventing self-approval:
| Control | API Setting | Value | Rationale |
|---|---|---|---|
| Prevent Author Approval | merge_requests_author_approval |
false |
Authors cannot approve their own merge requests. |
| Prevent Committer Approval | merge_requests_disable_committers_approval |
true |
Users with commits in the MR cannot approve. |
| Disable Rule Override | disable_overriding_approvers_per_merge_request |
true |
Prevent authors from lowering required approvals in the MR UI. |
| Reset Approvals on Push | reset_approvals_on_push |
true |
New commits require re-verification. |
| Require Password to Approve | require_password_to_approve |
false |
Bot and standard automated pipelines use session tokens. |
11. CODEOWNERS & Approval Identity¶
GitLab approval identity is governed by standard rules:
- Canonical Owner: @bluefly (Thomas @ Bluefly.io).
- Forbidden Owners: Personal handles (@flux423, @tscola), duplicate usernames, or generic group aliases without backing identity.
- Every repository should contain a root .gitlab/CODEOWNERS or CODEOWNERS file defining ownership.
12. CI/CD Configuration & Component Integration¶
All projects must use component-based CI from blueflyio/gitlab_components:
# Standard .gitlab-ci.yml pattern
include:
- component: $CI_SERVER_FQDN/blueflyio/gitlab_components/minimal-ci@release/v0.1.x
- No Bespoke CI: Avoid maintaining standalone custom CI scripts in consumer repos.
- Component Upgrades: Target the moving channel
@release/v0.1.xfor shared components.
13. Pipeline Variables & Security¶
| Setting | API Field | Value | Rationale |
|---|---|---|---|
| Restrict User-Defined Variables | restrict_user_defined_variables |
true |
Prevent arbitrary pipeline execution with overridden variables. |
| Variable Override Role | ci_pipeline_variables_minimum_override_role |
no_one_allowed |
Lock variable definitions to governed configuration. |
| Secrets Storage | 1Password / Governed Env | No plaintext secrets | Plaintext secrets must never be committed to repository variables. |
14. CI Job Token Scope & Inbound Allowlist¶
GitLab CI_JOB_TOKEN cross-project access must be explicitly restricted:
| Setting | API Field | Value | Rationale |
|---|---|---|---|
| Job Token Scope Enabled | ci_job_token_scope_enabled |
true |
Prevent arbitrary external projects from using job tokens against this project. |
| Inbound Allowlist | job_token_scope (inbound) |
Explicit only | Add only projects with proven dependency relationships (e.g. gitlab_components, consumer sites). |
| Push Access via Job Token | ci_push_repository_for_job_token_allowed |
false (default) |
Enable ONLY on repos with explicit tag/release automation (a2a-collector, packages). |
15. Runners Infrastructure¶
- Primary: Reusable group-level runner infrastructure with tag
$BUILD_RUNNER_TAG. - Project Runners: Allowed only when isolated Docker/DDEV or specialized GPU/hardware requirements exist.
- Shared Runners: Enabled (
shared_runners_enabled: true).
16. Security Policies & Secret Push Protection¶
All projects must be enrolled in the security policy framework:
| Control | Mechanism | Value |
|---|---|---|
| Security Policy Project Link | blueflyio/security-policies |
Linked at group level |
| Secret Push Protection | secret_push_protection_enabled |
true |
| Pre-Receive Secret Detection | pre_receive_secret_detection_enabled |
true |
| SAST & Dependency Scanning | Enforced via Scan Execution Policy | Group-wide policy injection |
17. Container & Package Registry Retention¶
For projects utilizing the GitLab Container Registry (SERVICE, DEPLOYABLE_APPLICATION):
{
"container_expiration_policy": {
"cadence": "1d",
"enabled": true,
"keep_n": 10,
"older_than": "90d",
"name_regex": ".*",
"name_regex_keep": "^(v[0-9]+.*|latest|release-.*)$"
}
}
- Keep: Tag patterns matching immutable releases (
v*,latest). - Expire: Transient branch/MR preview container images older than 90 days.
18. Pages Access & Documentation¶
- Default:
pages_access_level: "private"(viewable only by project members). - Exception: Public documentation sites explicitly designated for external developer consumption.
19. Member & Access Token Management¶
- Inheritance: Membership must be inherited from the
blueflyiotop-level group. - Direct Members: Restricted to authorized service accounts and bot identities.
- Deactivated / Expired Accounts: Audited and purged during reconciliation.
20. Webhooks & Integrations¶
- Event-driven automation (e.g. Gas City event consumers, Cursor hooks) must use authenticated endpoints with SSL verification enabled.
- Webhooks must listen only to specific relevant event types (
push_events,merge_requests_events).
21. Per-Project Execution Loop (Reconciliation Operating Model)¶
Reconciliation across the estate is executed one project at a time:
graph TD
A[1. Identify Project & Profile] --> B[2. Snapshot Current Settings via API]
B --> C[3. Compare Current vs Expected Baseline]
C --> D[4. Classify Changes: Safe / Security / Workflow]
D --> E[5. Apply Settings via GitLab API]
E --> F[6. Read Back & Verify Settings via API]
F --> G[7. Test Delivery Behavior / Pipelines]
G --> H[8. Produce 48-Field Receipt]
H --> I[9. Close Project Receipt & Move to Next]
Required 48-Field Project Receipt Template¶
PROJECT=
PROJECT_ID=
PROFILE=
STANDARD_VERSION=STD-GITLAB-001
VISIBILITY=
DEFAULT_BRANCH=
BRANCH_RULES=
PROTECTED_TAGS=
PUSH_RULES=
PIPELINE_REQUIRED=
DISCUSSIONS_REQUIRED=
STATUS_CHECKS_REQUIRED=
APPROVALS=
CODEOWNERS=
CI_MODE=
GITLAB_COMPONENTS=
CUSTOM_CI=
AUTO_DEVOPS=
PIPELINE_VARIABLE_ROLE=
JOB_TOKEN_ALLOWLIST=
JOB_TOKEN_PUSH=
RUNNERS=
SECURITY_POLICY_LINKED=
SECRET_PUSH_PROTECTION=
SECRET_DETECTION=
SAST=
DEPENDENCY_SCANNING=
CONTAINER_SCANNING=
PACKAGE_REGISTRY=
CONTAINER_REGISTRY=
MODEL_REGISTRY=
CONTAINER_CLEANUP=
PAGES=
WIKI=
SNIPPETS=
SERVICE_DESK=
FORKING=
DIRECT_MEMBERS=
INHERITED_MEMBERS=
STALE_MEMBERS=
DEPLOY_KEYS=
DEPLOY_TOKENS=
ACCESS_TOKENS=
WEBHOOKS=
INTEGRATIONS=
DRIFT_FOUND=
DRIFT_FIXED=
EXCEPTIONS=
READBACK_VERIFIED=YES|NO
DELIVERY_TEST=PASS|FAIL|NOT_APPLICABLE
REMAINING_GAPS=
PROJECT_COMPLETE=YES|NO