Repository navigation
feat(credentials): record, show, and explain saved token expiry - #9930
Conversation
GitHub reports a personal access token's expiry in the GitHub-Authentication-Token-Expiration response header and GitLab in the expires_at of /personal_access_tokens/self. The token check factory gains an expiresAt reader, keeps only a credible moment (a real calendar time at least an hour ahead, since the vendor just accepted the token), and the create and reconnect paths store it on credential.access_token_expires_at, the column a personal token already uses for the same meaning. A replacement token that states no expiry clears the previous one. The workspace credential contract reports it as an optional expiresAt.
…s it When a provider answers a saved service-account token with a 401 and the credential records a vendor-stated expiry that has passed, the run now reports that the token expired on that date and asks for a new one, instead of the bare authorization failure. The explanation keeps the provider's status, statusText, and body, and classifies as user-actionable like a revoked grant. A token is never refused on the recorded expiry alone: only a refusal the provider already made is explained, for both external requests and internal operations.
A connected credential whose saved token has a recorded expiry shows "expires in N days" or "expired" in the integrations list, the same muted caption API keys use, and a Token expiry section with the date on its detail page.
… GitLab personal token The GitHub and GitLab expiry readers move to one module so the GitLab personal token path reads expires_at the same strict way: a date that does not exist is recorded as no expiry instead of rolling over into another day.
…entials The organization credential presentation reports the same optional expiresAt the workspace one does.
…r's refusal The expired-token explanation is a user failure rather than a revoked grant, so it never triggers the revoked-grant handling, and it inherits the refusal's failure classification, logged mark, and external response body so the failure is still attributed to the provider and logged once.
GitHub states the expiry to the second, so the detail page shows the date and time in UTC rather than a date that can fall on the wrong day locally.
…GitHub's sourced header form Only an expiry that has already passed contradicts the vendor's acceptance; one that is minutes away is real and is now recorded. GitHub does not document the expiration header's value format, so the reader accepts only the numeric-offset form GitHub's own client library records and leaves any other form unread.
…t the provider's refusal The expired-token error extended UserFailure, but the boundary always carries the provider refusal's attribution onto it, so the base did nothing and its docs contradicted the logged classification. It is now a plain Error, and the run message names the date as UTC.
GitHub's octokit.rb spec cassettes record the GitHub-Authentication-Token-Expiration header both with a numeric offset and as 'YYYY-MM-DD HH:MM:SS UTC'. Accept the UTC-marked form as offset zero so those tokens get their expiry recorded; every other zone name stays unread.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
[Medium impact] The PR appears safe to merge; no actionable issues remain. SummaryRecords vendor-reported token expiry, shows it in credential views, and explains provider refusals after a saved token expires.
|
There was a problem hiding this comment.
All reported issues were addressed across 22 files
Reply with feedback, questions, or to request a fix.
Turn on auto-fix | Re-trigger cubic
… past GitLab personal-token expiry The integrations list and detail captions re-read the clock when the day count drops or the token expires, instead of only on render. A GitLab personal token's stated expiry that is already past is dropped, the same check the service-account validators apply, now shared as credibleTokenExpiry.
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 24 files
Reply with feedback, questions, or to request a fix.
Turn on auto-fix | Re-trigger cubic
…and reject out-of-range GitHub offsets
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
Summary
credential.access_token_expires_atcolumn. An expiry that has already passed contradicts the vendor accepting the token, so it is dropped. An imminent one is kept.expires_atfrom/personal_access_tokens/self, and the token stops working at midnight UTC on that date (GitLab docs).GitHub-Authentication-Token-Expirationheader (changelog). GitHub does not document the header's value format. The reader accepts the two forms seen in the API responses that GitHub's own octokit.rb records: a numeric offset (2023-04-19 16:34:22 -0700) and aUTCmarker (2022-09-20 23:45:13 UTC). It leaves any other form unread. In that case the token is still accepted, just with no expiry recorded.expiresAt.<date> UTCand asks for a new one. The provider's status and body are kept, and the refusal stays attributed to the provider in logs. A token is never refused on the recorded expiry alone.expires_atwith the same strict parser.xoxe.refusal stays.Deploy notes
Type of Change
Testing
executeTool, for external requests and internal operationssaved-token-expiry.integration.ts, covers create, list, reconnect replace/clear, org-owned credentials, and the expired-token message.Checklist