Skip to content

[Fix] Source-control credentials expire during long-running tasks - #1201

Merged
mrubens merged 7 commits into
developfrom
fix/source-control-token-refresh-0f7492hwjjwur
Aug 10, 2026
Merged

[Fix] Source-control credentials expire during long-running tasks#1201
mrubens merged 7 commits into
developfrom
fix/source-control-token-refresh-0f7492hwjjwur

Conversation

@roomote-roomote

@roomote-roomote roomote-roomote Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

​Opened on behalf of @mrubens. Follow up by mentioning @roomote-roomote, in the web UI, or in Slack.

What changed

  • Carry OAuth expiry metadata into task credentials for GitLab, Gitea, Bitbucket, and Azure DevOps Entra/delegated authentication while preserving no-expiry PAT behavior.
  • Refresh credentials before the earliest known provider expiry without ever delaying the existing 45-minute fallback cadence, including short-lived self-managed tokens and mixed-provider runs.
  • Bound token exchange and refresh requests, keep transient provider failures retryable, and require reauthorization only for definitive OAuth failures.
  • Recover when another replica wins a rotating-token refresh race; serialize Azure DevOps delegated refreshes through a transaction-scoped database lock and revalidate the linked account on every resolve.
  • Preserve the GitLab behavior developed in [Fix] Refresh GitLab OAuth tokens before they expire in sandboxes #1196 while reconciling its shared scheduler changes with the merged Gitea fix in [Fix] Gitea credentials expire after task wake-up #1199.

Why this change was made

Long-running and resumed tasks could keep short-lived source-control credentials past expiration because provider lifetimes were not consistently propagated to the shared refresh scheduler. Independent provider implementations also handled timeouts, transient outages, and rotating refresh-token races differently.

Impact

Tasks using any supported source-control OAuth provider refresh credentials before they expire, including mixed-provider workspaces. Temporary provider outages no longer force reconnection, stalled token requests are bounded, and concurrent refreshes cannot discard a newer Azure DevOps delegated token.

pridemusvaire and others added 6 commits August 10, 2026 16:17
Worker refresh used a fixed 45m cadence and ignored OAuth expiry, so a ~2h GitLab access token could sit dead in the sandbox after the last mint. Surface expiresAt from OAuth resolution and schedule refresh from it, with a 10m proactive token rotate.
Keep the soonest multi-provider expiry when merging tokens, return OAuth expiry from resolve metadata instead of process cache, and re-read a still-valid token when concurrent refresh fails instead of forcing reauthorization.
…tion

Expiry-driven scheduling could push a refresh past a credential that reports
no expiry: a run spanning GitHub and GitLab merged to GitLab's ~2h expiry and
left the ~1h GitHub installation token dead for the remainder. Expiry now only
ever shortens the interval. Also require proof that a peer actually rotated
before trusting a connection re-read after a failed refresh, so a real
invalid_grant is not masked into a retry loop, and classify OAuth tokens by
what this process minted rather than guessing from token prefixes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…fetimes

The proactive refresh skew and the worker refresh buffer were fixed windows
sized for GitLab's ~2h default OAuth lifetime. An instance configured with a
shorter TTL would sit permanently inside both windows, refreshing on every
resolve and re-minting at the 60-second floor. Both now cap at a quarter of the
token's life, so short-lived tokens still rotate before expiry without churn.

The instance-reported lifetime is stored on the encrypted connection blob as an
optional field, so an older release reading the same blob simply ignores it and
a connection written before this change falls back to the default windows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@roomote-community

roomote-community Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

No new code issues found. See task

  • packages/ado/src/credentials.ts:254 Cached delegated tokens bypass account validation after the linked Azure DevOps account is removed or replaced.

Reviewed 497ca3c

Comment thread packages/ado/src/credentials.ts Outdated
@mrubens
mrubens marked this pull request as ready for review August 10, 2026 17:15
@mrubens
mrubens merged commit 5cb52af into develop Aug 10, 2026
18 checks passed
@mrubens
mrubens deleted the fix/source-control-token-refresh-0f7492hwjjwur branch August 10, 2026 17:15
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.

2 participants