Fix Jira credentials clearing on forbidden task reads (#5757)

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo Hong 2026-06-18 20:22:01 -07:00 committed by GitHub
parent b8f2f95100
commit e3ca72b2b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 25 additions and 2 deletions

View File

@ -364,6 +364,13 @@ describe('Jira client credential storage', () => {
})
})
it('does not treat Jira permission failures as credential revocation', async () => {
const jira = await loadClientModule()
expect(jira.isAuthError(new jira.JiraApiError('Unauthorized', 401))).toBe(true)
expect(jira.isAuthError(new jira.JiraApiError('Forbidden', 403))).toBe(false)
})
it('bridges proxy environment settings before Jira connect requests', async () => {
netFetchMock.mockResolvedValueOnce(
new Response(

View File

@ -574,5 +574,7 @@ export function clearToken(siteId: string): void {
}
export function isAuthError(error: unknown): boolean {
return error instanceof JiraApiError && (error.status === 401 || error.status === 403)
// Why: Jira returns 403 for project/API permission gaps even when /myself
// succeeds, so only 401 means the saved credential itself is invalid.
return error instanceof JiraApiError && error.status === 401
}

View File

@ -390,4 +390,16 @@ describe('createJiraSlice credential errors', () => {
expect(store.getState().jiraStatus.credentialError).toBeUndefined()
})
})
it('keeps Jira connected when an issue read hits endpoint-level forbidden access', async () => {
const store = createTestStore()
store.setState({
jiraStatus: { connected: true, viewer: null, selectedSiteId: 'site-1' }
})
jiraListIssues.mockRejectedValueOnce(new Error('Forbidden'))
await expect(store.getState().listJiraIssues('assigned', 30)).resolves.toEqual([])
expect(store.getState().jiraStatus.connected).toBe(true)
})
})

View File

@ -55,7 +55,9 @@ function evictStaleEntries<T>(
function looksLikeAuthError(error: unknown): boolean {
const msg = error instanceof Error ? error.message : String(error)
return /authenticat|unauthorized|forbidden|401|403/i.test(msg)
// Why: Jira 403 commonly means endpoint/project access is denied while the
// saved token is still valid; do not flip Settings back to disconnected.
return /authenticat|unauthorized|401/i.test(msg)
}
type InflightJiraReadRequest<T> = {