Skip to content

Name the Forge and move forge accounts into forge_identities - #1548

Closed
benrfairless wants to merge 3 commits into
chore/1546-omniauth-2-upgradefrom
feature/1546-forge-glossary-and-schema
Closed

benrfairless wants to merge 3 commits into
chore/1546-omniauth-2-upgradefrom
feature/1546-forge-glossary-and-schema

Conversation

@benrfairless

@benrfairless benrfairless commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Part of #1546. Second layer of the stack, on #1547.

What

Two commits. The first is words: CONTEXT.md gains Forge (a service that hosts git repositories and authenticates the people who own them: GitHub or GitLab) and Forge identity (one Owner's account on one Forge), and Owner, Organization, Collaborator, Contributor and Scraper stop being defined in terms of GitHub. Two ADRs record the decisions behind #1546 that are hard to reverse and would puzzle a later reader:

  • ADR 0007: why GitLab repositories will be reached through a preference order of credentials (group access token, then deploy token plus a collaborator's OAuth token, then OAuth token alone) rather than one required kind. GitLab has no App-installation equivalent available to Free-tier users.
  • ADR 0008: why an Owner can hold an identity on each forge while nickname stays the only slug. OAF needs to move scrapers from GitHub to GitLab without their URLs changing.

The second is schema. provider, uid and access_token move off owners into a forge_identities table, one row per Owner per forge, unique on (forge_key, uid) and (owner_id, forge_key). Existing rows are backfilled as GitHub identities. owners.nickname becomes unique, and the migration refuses to run if two Owners already share one rather than choosing silently. On scrapers, github_id becomes forge_repo_id, github_url becomes repo_url, and forge_key (default github) says which forge the repository is on.

User.find_for_github_oauth finds a User by GitHub uid through the identity, and Organizations are found by GitHub id through Organization.find_or_create_from_github!, so a rename on GitHub no longer creates a second Owner.

Verified

  • Migrations run forward and back against rows seeded the old way (a User with a provider, an Organization with a nil provider, a shell contributor User with no uid); the backfill produces the right identities and the rollback restores the columns.
  • spec/models/forge_identity_spec.rb covers sign-in creating and re-finding identities, uid collisions across forges, Organization lookup by GitHub id, and both uniqueness rules.
  • make quick-tests green (853 examples, coverage 77.03%), rubocop clean.

Notes for review

  • The column is forge_key, not forge, so that scraper.forge and identity.forge can return the adapter object in Put a Forge seam between morph.io and GitHub #1549 without clashing with the attribute.
  • Tokens stay plaintext, matching current practice. Encrypting only the new columns while GitHub tokens sit in plaintext beside them would be theatre; whole-table encryption is a separate decision worth its own issue.
  • AGENTS.md and docs/agents/domain.md said there were no ADRs yet, which had been stale since 0001.

Assisted-by: Claude Code:anthropic.claude-fable-5-1

CONTEXT.md gains Forge (a service that hosts git repositories and
authenticates their owners: GitHub or GitLab) and Forge identity (one
Owner's account on one Forge), and Owner, Organization, Collaborator,
Contributor and Scraper stop being defined in terms of GitHub.

Two ADRs record the decisions behind #1546 that are hard to reverse
and would puzzle a later reader: 0007, why GitLab repositories are
reached through a preference order of credentials rather than one
required kind; 0008, why an Owner can hold an identity on each forge
while nickname stays the only slug.

AGENTS.md and docs/agents/domain.md said there were no ADRs yet, which
had been stale since 0001.

Assisted-by: Claude Code:anthropic.claude-fable-5-1
An Owner's account on a forge (provider, uid, access_token) moves off
the owners table into forge_identities, one row per Owner per forge,
unique on (forge, uid) and on (owner_id, forge). This is what lets one
Owner hold both a GitHub and a GitLab identity (ADR 0008). Existing
rows are backfilled as GitHub identities; provider was only ever
written as "github" and was nil on Organizations, so the uid alone
decides.

owners.nickname becomes unique, since it is the one slug behind every
owner URL. The migration refuses to run if two Owners already share a
nickname rather than choosing one silently.

On scrapers, github_id becomes forge_repo_id, github_url becomes
repo_url, and a forge column (default "github") says which forge the
repository is on.

User.find_for_github_oauth now finds a User by GitHub uid through the
identity, and Organizations are found by GitHub id through
Organization.find_or_create_from_github!, so a rename on GitHub no
longer creates a second Owner.

Assisted-by: Claude Code:anthropic.claude-fable-5-1
@benrfairless
benrfairless added this pull request to stack #1550 September 16, 2026 07:18
@benrfairless benrfairless self-assigned this Sep 16, 2026
@benrfairless benrfairless changed the title feature/1546 forge glossary and schema Name the Forge and move forge accounts into forge_identities Sep 16, 2026
FactoryBot.lint with traits builds organization+on_github, whose GitHub
identity takes its login from the nickname, and the factory had none.

Assisted-by: Claude Code:anthropic.claude-fable-5-1
@benrfairless
benrfairless deleted the feature/1546-forge-glossary-and-schema branch September 17, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant