GitLab Service Account Standard — STD-GITLAB-SA-001¶
Purpose¶
Every autonomous agent role that performs source operations against GitLab — push, MR create/update/merge, CI trigger, authenticated API call, release or package publish, CODEOWNERS modification — MUST authenticate as a named machine identity: a GitLab Service Account or an appropriately-scoped CI token. Never as a human operator's personal account or session.
This standard defines the provisioning requirements, naming convention, scope rules, and audit obligations for Bluefly GitLab Service Accounts used by autonomous agents.
Scope¶
Applies to every agent with class: AGENT in the
Agent Identity Registry that
performs any of the operations listed under Purpose.
1. The Rule¶
AGENT_GITLAB_IDENTITY ≠ HUMAN_OPERATOR_IDENTITY
Every agent git commit, MR, CI trigger, and API call must carry
the agent's own machine identity, not a human operator's address,
not a personal-account session token.
Violation indicators:
- Git author is a human operator's address on a commit authored by an autonomous agent session.
GITLAB_TOKENin an agent environment resolves to a personal access token.glabauthenticated as a human account (flux423,bluefly) in an agent session.
R1 — Dedicated account, no borrowing¶
Each agent role MUST have exactly one GitLab service account. No two agents share an account. No agent uses a human's account.
2. Naming Convention (R2)¶
Pattern: bluefly-<role-slug>-agent
Examples: bluefly-drupal-agent
bluefly-blu-agent
bluefly-mayor-agent
bluefly-harbormaster-agent
bluefly-sentinel-agent
bluefly-refinery-agent
The bluefly- prefix signals machine identity; the -agent suffix signals
autonomous operation; <role-slug> matches the gc_role in the Agent
Identity Registry, lowercased. All service accounts are created at the group
level (blueflyio/) with the minimum GitLab role required for the agent's
actual operations.
3. Required Scope Per Role (R4 — least privilege)¶
| Role | Minimum GitLab Group Role | Additional Scopes |
|---|---|---|
bluefly-drupal-agent |
Developer | api, write_repository scoped to Drupal rigs |
bluefly-blu-agent |
Reporter | read_api — routing/observation only |
bluefly-sentinel-agent |
Reporter | read_api — security observation |
bluefly-refinery-agent |
Developer | api, write_repository — governed delivery |
Default scope for a role not listed above: read_repository +
write_repository + create_mr. CI trigger, release, and package-publish
scopes require explicit approval before they are added.
No service account is granted Owner or Maintainer at group level. Elevated operations go through CI pipelines with a scoped
CI_JOB_TOKEN.
4. Secret Delivery (R3)¶
Service account tokens are delivered via 1Password Service Accounts using
op:// references. See Authentication and Secrets Constitution
for the full rotation and delivery contract. Token values are never:
- written to files in the repository;
- passed as shell arguments (process-table and wrapper-echo exposure);
- printed in logs or session transcripts;
- stored in
city.tomlor any tracked config file as plaintext; - placed in an environment file that 1Password does not manage.
See Authentication and Secrets Constitution §14–16 for the full rotation and delivery contract.
5. Git Config Per Agent Session (R6)¶
Git author metadata MUST reflect the agent's identity, not the human operator's. Each agent session configures:
git config user.name "Bluefly <Role> Agent"
git config user.email "bluefly-<role-slug>[email protected]"
These values MUST match the service account profile on GitLab. git config
is set at worktree initialisation, never globally — a global machine identity
bleeds into human sessions.
6. CODEOWNERS Entry (R5)¶
Every provisioned service account must have an entry in agent-identity-registry.yaml with gitlab_principal set to the actual GitLab username — not NOT_YET_PROVISIONED. Unprovisioned entries remain at NOT_YET_PROVISIONED until the service account is verified in production GitLab.
Every service account MUST be listed in the CODEOWNERS file of every repository it is authorised to merge into:
* @bluefly-<role-slug>-agent
The human reviewer remains in CODEOWNERS as final gatekeeper. Agent accounts are secondary approvers only, never sole gatekeeper.
7. Protected Branches (R8)¶
Service account tokens MUST operate under protected-branch rules that prevent
force push on main and release/*. Enforced at the GitLab project level,
not by convention.
8. Registry Obligation and Verification Before Use (R7)¶
Every provisioned service account must have an entry in
agent-identity-registry.yaml
with gitlab_principal set to the actual GitLab username. An entry remains
provisioning_status: NOT_YET_PROVISIONED until all of the following are
confirmed and recorded in the provisioning playbook:
- The GitLab account exists and its username matches §2.
glab api /userwith that account's token returns the correct username.- A 1Password Service Account exists and delivers the token.
- Git config is set correctly in the agent's session template.
- At least one test push was made and the commit author matches §5.
9. Audit and Enforcement¶
CI gate validate-agent-identity (not yet implemented) validates that:
- every
AGENTandSERVICEclass entry in the registry hasgitlab_principal ≠ NOT_YET_PROVISIONED, or an explicit tracking note; - no human email appears as
gitlab_principal; - the registry validates against
agent-identity-registry.schema.json.
Until that gate exists, the registry is hand-audited on each MR that touches
Engineering-Standard/catalog/. In addition:
gc lint(viablucity-packs) validates that agent session config includes agit_identityblock before anyformula.cookon a formula withcontract = "gitlab".- ContractPlane ChangeRecipe validation enforces that the commit author matches the registered service account before MR creation.
10. Non-Compliance¶
An agent pushing under a human identity is a critical identity violation. On detection:
- The MR is closed without merge.
- A P0 bead is created:
SECURITY: autonomous agent used human GitLab identity. - The agent session is suspended pending provisioning.
- The incident is recorded in
machine-identity-catalog.mdwithprovisioning_status: VIOLATION.
11. Provisioning Procedure¶
See
gitlab-service-account-provisioning-drupal.md
for the step-by-step provisioning playbook, starting with
bluefly-drupal-agent (PLY-GITLAB-SA-DRUPAL-001).
Related: Agent Identity Registry · Machine Identity Catalog · Identity Contract