Skip to main content

Governance

How Eigenoid manages repository naming, lifecycle, configuration, and merge strategy across the organization.

For full decision rationale, see ADR-0007 (lifecycle) and ADR-0011 (naming).

Repository naming convention

Every repository follows a prefix-based naming scheme:

<category>-<descriptive-name>

Names must be kebab-case with a concise descriptive part (2--3 words max).

PrefixDescriptionExample
app-Deployable applicationsapp-studio, app-block-page
svc-Microservicessvc-access
iac-Infrastructure as Code (Terraform)iac-foundation, iac-platform
platform-Internal org toolingplatform-settings, platform-actions
docs-Documentation sitesdocs-internal, docs-external
tpl-Template repositoriestpl-iac, tpl-app

Exceptions: .github (GitHub convention) and published packages that use the package name as the repo name (e.g., eigenoid for the pip package).

The repo creation issue template enforces the convention automatically -- the user selects a category and provides only the descriptive part. The workflow validates format, allowed characters, and duplicates before proceeding.

Suborgs

Each category with two or more repos has a safe-settings suborg file (.github/suborgs/<category>.yml) with shared configuration (labels, properties). Repos are matched by glob pattern:

# .github/suborgs/app.yml
suborgrepos:
- "app-*"
yaml

Repository lifecycle

Repo creation and deletion are fully managed through issue templates and GitHub Actions in platform-settings. Direct creation by org members is disabled at the org level.

Creation

  1. A member opens an issue using the "Request new repository" template.
  2. The new-repo.yml workflow generates a PR with the repo's YAML configuration for safe-settings, using force_create: true.
  3. The PR is authored by eigenoid-settings-bot[bot], includes a summary table and review checklist, and auto-closes the issue on merge.
  4. A reviewer approves and merges the PR.
  5. safe-settings detects the merge and creates the repo with full configuration (labels, rulesets, teams, settings) in a single step.

The repo is born fully governed, with a complete audit trail from issue to PR to merge to creation.

Archival (soft-delete)

  1. A member opens an issue using the "Request repo deletion" template. The notify-lifecycle-approvers.yml workflow notifies @eigenoid/platform-lifecycle-approvers.
  2. A team member applies the approved-deletion label. The archive-repo.yml workflow verifies team membership before proceeding.
  3. The workflow archives the repo on GitHub and records an entry in archived-repos.json with a timestamp, the requester, and the issue reference.

The repo becomes read-only but recoverable. The entry in archived-repos.json starts a 30-day countdown.

Permanent deletion

  1. The delete-archived-repos.yml workflow runs daily via CRON.
  2. It reads archived-repos.json and permanently deletes repos archived for more than 30 days.
  3. It removes the registry entry and notifies the original requester.

Lifecycle ruleset

An org-level ruleset restricts lifecycle operations (creation, deletion, transfer, visibility changes). Only OrganizationAdmin and the eigenoid-settings-bot GitHub App can bypass it. The admin repo (platform-settings) has its own repo-level rulesets to prevent lockout.

safe-settings

safe-settings is the source of truth for GitHub configuration across the org. It runs as a container on Cloud Run and reacts to pushes to the admin repo.

What it manages:

  • Org-level settings: default repo configuration, org rulesets.
  • Per-repo settings: visibility, merge strategy, features (wiki, issues, etc.), labels, team access.
  • Rulesets and branch protection: declared in YAML, enforced on every push. Manual changes are automatically reverted (drift prevention).
  • Suborgs: shared configuration for groups of repos matched by glob pattern.

Configuration lives in platform-settings/.github/ under settings.yml (org-wide), repos/<name>.yml (per-repo), and suborgs/<category>.yml (per-category).

For the operational guide, see safe-settings operations.

For bot details, see the Settings Bot page.

Branch protection and rulesets

All repositories use squash merge as the only allowed merge strategy. This keeps the main branch history clean and linear.

Commits must follow Conventional Commits format (feat:, fix:, docs:, ci:, etc.). PR titles are validated by a dedicated workflow (pr-title.yml) in each repo.

Branch protection is enforced via org-level rulesets in safe-settings:

RulesetTargetRules
main-protectionAll repos (except github-org-settings)No deletion, no force-push, linear history required
require-prAll repos (except github-org-settings)1 approval, stale review dismissal, thread resolution
code-dev-protectionsvc-*, app-* reposProtect dev branch: no deletion, no force-push, 0 approvals
code-qa-protectionsvc-*, app-* reposProtect qa branch: no deletion, no force-push, 1 approval, thread resolution
exception-dev-protectionRepos with branch_strategy: dev-qa-main propertySame as code-dev, for repos outside svc-/app- naming
exception-qa-protectionRepos with branch_strategy: dev-qa-main propertySame as code-qa, for repos outside svc-/app- naming
repo-lifecycle-governanceOrg-levelRestricts repo creation, deletion, transfer, visibility changes

All rulesets allow OrganizationAdmin bypass. Code and exception rulesets also allow the eigenoid-settings-bot Integration as a bypass actor.

Changes to rulesets made manually through the GitHub UI are automatically reverted by safe-settings on the next sync cycle.