Import a public repository owned by another account as an upstream mirror #194

Closed AtlantisPleb opened this 4d ago

Evidence

Shipped in the release at 815a5b0, promoted 2026-08-26.

1 pushes receipt

Every import path requires that the source repository's GitHub owner is you, or
an organization whose namespace you hold. There is no way to bring in a public
repository someone else owns.

Where the gate is

Three layers, and only the third is the real one:

  • The picker lists only your own. OpenAgents.GitHub.repository_page/3
    requests /user/repos with
    affiliation=owner,collaborator,organization_member
    (lib/openagents/github.ex:182), so RepositoryImportLive cannot show a
    repository you have no affiliation with.
  • Resolution does not gate.
    GitHubProjection.import_source/2
    (lib/openagents/repositories/github_projection.ex:71) takes any
    owner/name and reads it with your token, so a public repository resolves
    fine. This is not where the refusal happens.
  • Creation gates on owner identity. Repositories.create_user_import/4
    requires source_owner_id == user.github_id
    (lib/openagents/repositories.ex:288), and the organization path requires
    source_owner_id == namespace.provider_account_id
    (lib/openagents/repositories.ex:310). Otherwise
    :source_namespace_mismatch.

Confirmed against production:

$ openagents repo import tobi/walgit --public
openagents: tobi is not an eligible GitHub namespace for this account.

$ openagents api user/repos/imports --method POST \
    --input body.json -H "Idempotency-Key: $(uuidgen)"
HTTP 403  source_namespace_mismatch  "Source namespace is not eligible"

The CLI message names the wrong thing — it reports the destination namespace
as ineligible when the destination was the personal namespace and the source
owner is what failed.

Why this is a decision, not a missing flag

Relaxing the check to "any repository your token can read" would let a public
repository owned by someone else become a repository owned by you on this
forge, with your name on it, no upstream recorded, and no statement of where
it came from. That is wrong in a way a flag does not fix.

What the forge is missing is a distinct upstream mirror: a repository whose
content comes from a public source it does not own, which

  • names the upstream on every surface that shows the repository, so a reader is
    never misled about origin,
  • is one-way by construction. There is no push to tobi/walgit, and nothing
    should imply there is. Local pushes to a mirror must be refused rather than
    silently diverging,
  • carries the upstream's license, or records that none was found,
  • keeps its own refs honest against EXIT-004: a mirror is still a forge
    repository, and a clone of it must serve. See #179 for what happens when a
    repository arrives by a path that does not record its own boundary.

Whether a mirror refreshes on a schedule, on demand, or once is a second
question. Once is enough to close this issue; say what the others would need.

Done when

  • A public repository owned by another account can be brought in through the
    CLI and the API, as a mirror, with the upstream recorded and shown.
  • The distinction between an owned repository and a mirror is visible in the
    API response and on the repository page, not only in the database.
  • A push to a mirror is refused with a message that says why.
  • openagents repo import reports the source owner when the source is what
    failed, rather than naming the destination namespace.
  • The existing owner-identity gate still refuses a source owned by someone else
    for a normal import, and a proof asserts a mirror cannot be created by that
    path.
  1. AtlantisPleb opened this issue 4d ago
  2. AtlantisPleb closed this as completed in 7d21158 4d ago
Sign in with GitHub to comment on this issue.