Skip to content

bridge, commands: fix credential selection and dangling identity handling - #1663

Open
mcepl wants to merge 12 commits into
git-bug:trunkfrom
openSUSE-Python:fix/bridge-identity-creds
Open

mcepl wants to merge 12 commits into
git-bug:trunkfrom
openSUSE-Python:fix/bridge-identity-creds

Conversation

@mcepl

@mcepl mcepl commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This change fixes three failure modes when setting up bridges and managing credentials:

  1. Configured user identities pointing to missing objects aborted bridge setup and left orphan credentials in the keyring.
  2. Keyring lookups returned credentials in arbitrary order, causing bridges to pick stale or revoked tokens over newly created ones.
  3. bridge auth add-token lacked a base URL flag, making it impossible to add valid tokens for self-hosted GitLab or Jira instances.

Changes

Dangling user identity recovery

  • bridge/core.FinishConfig now inspects the configured user identity before checking login metadata. If the identity is missing from the repository, it repairs configuration by adopting an existing identity matching the login, or by creating a fresh one and setting it as current.
  • Factored user identity validation in commands/execenv into ensureUser(). When a configured identity is missing, commands report clear guidance pointing to git bug user adopt and git bug user new instead of returning a raw not-found error.

Deterministic, newest-first credential listing

  • bridge/core/auth.List now sorts credentials by creation time descending, using the credential ID as a tie breaker.
  • Updated auth.Store to serialize creation timestamps using time.RFC3339Nano so tokens added in the same second preserve order.
  • Updated repository.ParseTimestamp to support RFC 3339 nano strings while keeping backward compatibility with legacy unix epoch integers.

Base URL flag for token auth

  • Added -b / --base-url to git bug bridge auth add-token to store the target instance URL in token metadata.
  • Improved validation for --user to return a specific error when the provided prefix does not match any known identity.
  • Regenerated man and markdown documentation.

RetriggerConfidence Score: 5/5

The PR appears safe to merge based on the changes since the previous review.

Summary

The PR repairs dangling identity handling, orders credentials newest-first, and adds base-URL-aware token setup. Changes since the previous review retain Jira’s validated credential until explicit reconfiguration and fail clearly when that credential is removed.

  • Jira credential selection now keeps the configured credential pinned rather than silently rotating or replacing it.
  • Tests cover explicit token replacement and removal.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Jira import or export] --> B{Configured credential ID?}
    B -- No --> C[Select compatible stored credential]
    B -- Yes --> D{Pinned credential available and matching?}
    D -- Yes --> E[Use pinned credential]
    D -- No --> F[Require bridge reconfiguration]
Loading

Reviews (9) · Last reviewed commit: "bridge/jira: require explicit rotation o..."

Comment thread bridge/core/auth/credential.go
Comment thread commands/bridge/bridge_auth_addtoken.go
mcepl added 5 commits October 4, 2026 22:26
When git-bug.identity in the local git config points to an identity
that doesn't exist in the repository (removed, never pulled, or the
config was copied from another repository), several code paths failed
with the cryptic "identity doesn't exist" error:

- core.FinishConfig, used by every bridge's "bridge new", only treated
  identity.ErrNoIdentitySet as "no user configured" and aborted on any
  other error. Bridge configuration could therefore never complete,
  while the credential had already been stored, so every retry left
  another orphaned token in the keyring.

- LoadRepoEnsureUser / LoadBackendEnsureUser returned the raw
  ErrNotFound, giving the user no hint about what is missing or how to
  fix it (identity.GetUserIdentity silently unsets the dangling config
  at that point too).

FinishConfig now checks the configured user identity first. When a
dangling identity is detected, it prints a notice and repairs it by
adopting an existing identity tagged with the bridge login if one exists,
or by creating a new tagged identity and setting it as current. The
ensure-user helpers are factored into ensureUser(), which turns the
not-found case into an actionable message pointing to
"git bug user adopt" / "git bug user new".

Regression tests cover FinishConfig with a dangling identity, both
when a matching identity exists and when a new one must be created.
auth.List returned credentials in whatever order the keyring backend
listed its keys, which is arbitrary. Callers in all bridges (github,
gitlab, jira importers and exporters) simply use creds[0], so when
several matching credentials exist, e.g. after a token was regenerated
or a bridge configuration was retried, the bridge could keep picking an
old, revoked token. The newly added valid one was silently ignored and
every pull failed with an authentication error from the remote.

Sort the result by creation time, most recent first, with the ID as a
tie breaker so that the order is fully deterministic. Stored timestamps
preserve full RFC3339Nano resolution so credentials added in the same
second still sort deterministically newest-first, while remaining backward
compatible with legacy integer timestamps. Adding a fresh credential now
supersedes older ones for every caller without having to touch each bridge.
Bridges for self-hosted trackers (gitlab, jira) only select credentials
carrying a "base-url" metadata matching their configuration, but
"bridge auth add-token" had no way to set it. Tokens added through it
were therefore never used by those bridges, without any warning.

Add a -b/--base-url flag, consistent with "bridge new", which stores
the value as base-url metadata on the token.

Also report a clear error when --user doesn't match any identity.
"-u" means --user here but --url in "bridge new", which makes it easy
to pass a URL by mistake; previously that produced only the cryptic
"identity doesn't exist".

The man page and markdown documentation are regenerated.
…lients

In githubExporter.cacheAllClient and gitlabExporter.cacheAllClient, the
loop over credentials built each client from creds[0] instead of the
iterated cred. If tokens existed for multiple accounts, every identity
client was configured with whichever token appeared first in the slice.
Because auth.List orders credentials newest-first, adding a token for a
secondary account caused exports to run with that account's token, even
for the configured default login.

Build each identity client and assign the default token from the
matching iterated token instead of creds[0].
… matching

When bridges for trackers like GitLab and Jira query credentials by base
URL, auth.List uses exact string matching on metadata. Differences such
as a trailing slash (for example, the default "https://gitlab.com/"
versus user input "https://gitlab.com") caused credential lookups to fail
silently, making valid tokens unusable by the bridge.

Introduce auth.NormalizeBaseURL to canonicalize URLs by lowercasing scheme
and host and removing trailing slashes. Apply this normalization when
storing base-url metadata in "bridge auth add-token" as well as in GitLab
and Jira bridge configuration. In auth.List option matching, compare
base-url metadata values after normalization so queries match regardless
of trailing slashes in either the stored credential or the query filter.
@mcepl
mcepl force-pushed the fix/bridge-identity-creds branch from 4d4d7c8 to 2c5ed84 Compare October 4, 2026 20:52
Comment thread bridge/gitlab/config.go Outdated
Comment thread commands/bridge/bridge_auth_addtoken.go
Comment thread bridge/core/auth/credential.go
Comment thread bridge/jira/import.go Outdated
@greptile-apps

This comment has been minimized.

Comment thread bridge/jira/jira.go Outdated
Comment thread bridge/jira/config.go
Comment thread bridge/jira/import.go Outdated
Comment thread bridge/jira/jira.go
Comment thread bridge/jira/jira.go Outdated
Comment thread bridge/jira/jira.go Outdated

This branch has not been deployed

No deployments
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