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.