Repository navigation
Conversation
A team that signs in to one GitLab through two OAuth applications holds
two provider connections to that host. A repository bound under one of
them through a credential that died could only be taken over by a
credential of that same connection: the Re-link dialog filtered the
credential list by connection and said nothing could take it, the two
relink commands refused, and neither a connect's carry-forward nor the
repair sweep looked past the dead credential's own connection.
Two connections of a team with the same provider and API root are now
interchangeable for a repository (ProviderInstanceHost, built on
CredentialUrl.SameRoot, one definition for every door).
- The Re-link dialog renders a candidate list the backend computes
(GET /provider-instances/{id}/relink-candidates): the caller's own and
the team's credentials that can still authenticate, on the connection
and its siblings, the same connection first. A static token past its
expiry is not offered, as the credential list already reads it as
rejected (the one definition RemedyResolution.IsLive). Against an API
without the route (any 404 from it: a real older server answers with
its fallback's JSON body, not an empty one) the dialog filters the
credential list itself, as before.
- A candidate on another connection says so beside it: the connection it
is on and that picking it moves the repository there, even when it is
the only candidate. Identities that let a teammate act as themselves
belong to a connection, so the candidate also names the teammates whose
act-as would stop working on the repository until they connect there
(StrandedActAs, read through the act-as resolver's own predicate; one
more resolver method, ListCandidatesOnInstanceAsync, that the
per-repository listing now delegates to). Nothing is read for it when
no candidate is on another connection.
- RelinkRepositoryCredentialCommand and RelinkCredentialBindingsCommand
accept a credential on a sibling connection. The target is asked for
the repository by id and must find it at the path CodeSpace has, then
the repository's credential and connection move together, its hooks
are registered again through the new connection and the old ones
retired. The id, project links, triggers and history stay. Another
host is refused with the message it always got.
- Connect-time carry-forward, the repair sweep and a Disconnect that
names a target follow the same rule, keyed on the same owner. A
repository the new connection cannot take (it already holds the
project, or the credential's scopes cannot register the hook) stays
where it was; a group hook stays with its connection. A repair whose
every repository is refused counts as a failure of that credential so
it backs off instead of holding a place in the pass.
- The service that moves a repository between connections is taken
lazily by the successor service: it reads Webhooks:BaseUrl when built,
and connecting or disconnecting a credential must not need it.
No migration. A repository always has a credential of its own
connection, so older pods, an older SPA and a rollback read every row
this writes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ProviderInstanceHost, built onCredentialUrl.SameRoot, one definition for every door).GET /api/provider-instances/{id}/relink-candidates): the caller's own and the team's credentials that can still authenticate, on the connection and its siblings, the same connection first. A static token past its expiry is not offered, matching how the credential list reads it (RemedyResolution.IsLive). Against an API without the route (any 404 from it) the dialog filters the credential list itself, as before.RelinkRepositoryCredentialCommandandRelinkCredentialBindingsCommandaccept the credential: the target is asked for the repository by id and must find it at the path CodeSpace has, then the repository's credential and connection move together, its hooks are registered again through the new connection and the old ones retired. The id, project links, triggers and history stay; another host is refused with the message it always got.Test plan
ProviderInstanceHost,CredentialUrl.SameRoot; full unit suite 14849 passed, 1 skippedGitLabDoorkeeperStub: relink across connections, stranded teammates named in the candidates, an expired PAT listed as rejected and not offered, the 404 body an older server sends for a missing routeRelinkDialogrenders the backend's set in its order, names the connection and the move when every candidate is on one other connection, names stranded people, and falls back to its own filter on the real older-server 404; lint,tsc --noEmit, full vitest (2717 passed) and build