fix: migrate Jira search API and add Agile OAuth scopes#111
Conversation
Jira removed /rest/api/3/search (410 Gone) — migrate to the new /rest/api/3/search/jql POST endpoint with cursor-based pagination. Add missing OAuth scopes for the Agile REST API (boards, sprints). - Switch jiraSearchIssues to POST /search/jql with nextPageToken - Add read:board-scope:jira-software, read:sprint:jira-software, read:issue:jira-software, read:project:jira scopes - Update frontend to use nextPageToken and issues.length for count
✅ Deploy Preview for agent-native-fw ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
agent-native-mail | deb1d4a | Commit Preview URL Branch Preview URL |
Mar 31 2026, 04:36 PM |
There was a problem hiding this comment.
Builder has reviewed your changes and found 3 potential issues.
Review Details
PR #111 — Jira Search API Migration + Agile OAuth Scopes
This PR migrates the Jira issue search from the deprecated GET /rest/api/3/search (410 Gone) to the new POST /rest/api/3/search/jql with cursor-based pagination, and adds four new OAuth scopes required for the Jira Agile REST API. The endpoint migration and body/header handling are correctly implemented. The nextPageToken is properly plumbed through the stack from the Jira API → server handler → query params → React hook.
Risk: Standard — OAuth scope changes and API contract changes can affect existing users and displayed data.
Key Findings
🟡 MEDIUM — Issue count footer now shows page size instead of total
Both MyIssuesPage and ProjectIssuesPage replace data.total with data.issues.length. The new cursor-based API doesn't return total, but issues.length represents only the current page (≤50 by default). Users with large projects will see "50 issues" even when hundreds match — actively misleading. A "50+ issues" suffix using nextPageToken presence would be more accurate.
🟡 MEDIUM — Existing Jira connections won't receive the new Agile scopes
The new scopes are only applied during a fresh OAuth consent flow. Existing users whose tokens are stored in oauth_tokens will not be upgraded — OAuth token refresh preserves the originally granted scope set. The boards/sprints 401 errors will persist for all existing connected users until they manually disconnect and reconnect, with no in-app prompt to do so.
🧪 Browser testing: Skipped — changes are in a Jira-specific template that requires live OAuth credentials to exercise end-to-end. The UI changes are minimal footer text updates not testable without a real Jira connection.
Code review by Builder.io
| "write:jira-work", | ||
| "read:jira-user", | ||
| "read:board-scope:jira-software", | ||
| "read:sprint:jira-software", | ||
| "read:issue:jira-software", | ||
| "read:project:jira", |
There was a problem hiding this comment.
🟡 New OAuth scopes don't apply to existing connected users
These scopes only take effect for users who re-authorize after this deploy. Existing users' stored tokens won't include the new scopes (OAuth refresh preserves original grants), so boards/sprints will continue to 401 for them. Consider detecting missing scopes on getClient() and surfacing a reconnect prompt rather than relying on users to manually disconnect.
React with 👍 or 👎 to help me improve.
There was a problem hiding this comment.
Acknowledged, but this is expected OAuth behavior and not a regression — existing users never had Agile scopes. When they navigate to boards/sprints, existing error handling surfaces the issue. A scope-detection reconnect prompt is a good follow-up but out of scope for this PR.
Restructure issue detail view with inline properties grid, mobile-friendly back navigation, and single-scroll layout. Migrate routes to _index convention. Enhance board/sprint handlers with better error handling and pagination. Handle string descriptions from older Jira instances and skip empty comments.
Addresses PR feedback — footer now indicates truncation with a "+" suffix when nextPageToken is present.
There was a problem hiding this comment.
Builder has reviewed your changes and found 3 potential issues.
Review Details
PR #111 — Incremental Review (Updated)
This round adds significant UI improvements on top of the original API migration: a responsive full-screen issue detail layout, skeleton loading states, an AtlassianApiError class, graceful 403/404 handling on board/sprint endpoints, and route restructuring with useMatch/Outlet for nested issue detail views.
Risk: Standard 🟡 — The changes now span API behaviour, routing architecture, and error handling.
✅ Previous Feedback Addressed
- Issue count footer (both pages): Fixed — now correctly appends
"+"whennextPageTokenis present, accurately signalling truncated results.
New Findings
🔴 HIGH — Activity tab always shows "No activity recorded"
getIssue switched from expand: ["changelog"] to expand: ["renderedFields"], but IssueActivity still reads issue.changelog?.histories. Jira only includes changelog data when expand=changelog is explicitly requested, so the Activity tab is silently broken for all issues. Fix: use expand: ["changelog", "renderedFields"].
🟡 MEDIUM — 403 from Agile APIs silently becomes an empty list
listBoards and listSprints catch AtlassianApiError 403/404 and return { values: [], total: 0 } with HTTP 200. Since the new Agile scopes trigger exactly these 403s for existing users, they will see "No boards" / "No sprints" with no indication they need to reconnect — the same silent failure path that the AtlassianApiError class was added to improve.
🟡 MEDIUM — Existing OAuth tokens won't receive new Agile scopes
Still unaddressed from the previous review. No scope validation or reconnect prompt on stored tokens.
🟡 MEDIUM — useMatch/Outlet pattern loses list state on navigation
When navigating to/from an issue detail, the isExact check unmounts the page component entirely and mounts it fresh from the child route. Local state (search text, focused index, scroll position) resets every time a user opens or closes an issue.
🧪 Browser testing: Skipped — template requires live Jira OAuth credentials to exercise end-to-end.
Code review by Builder.io
| if ( | ||
| err instanceof AtlassianApiError && | ||
| (err.status === 403 || err.status === 404) | ||
| ) { |
There was a problem hiding this comment.
🟡 403 from Jira Agile silently becomes an empty board/sprint list
listBoards and listSprints return { values: [], total: 0 } on 403, so users missing the new Agile scopes see "No boards" / "No sprints" with no actionable error. Consider propagating 403 (like getBoardConfig does) so the UI can prompt reconnection.
React with 👍 or 👎 to help me improve.
| "write:jira-work", | ||
| "read:jira-user", | ||
| "read:board-scope:jira-software", | ||
| "read:sprint:jira-software", | ||
| "read:issue:jira-software", | ||
| "read:project:jira", |
There was a problem hiding this comment.
🟡 New OAuth scopes don't apply to existing connected users
These scopes only take effect for users who re-authorize after this deploy. Existing stored tokens won't include the new Agile scopes and will continue to 401/403 on board/sprint endpoints with no in-app prompt to reconnect.
React with 👍 or 👎 to help me improve.
The expand param was changed from ["changelog"] to ["renderedFields"] which broke the Activity tab. Now uses both.
Summary
/rest/api/3/search(410 Gone) to new/rest/api/3/search/jqlPOST endpoint with cursor-based paginationread:board-scope:jira-software,read:sprint:jira-software,read:issue:jira-software,read:project:jira) to fix 401 errors on boards/sprintsnextPageTokenpagination andissues.lengthfor count displayTest plan
/search/jqlendpoint🤖 Generated with Claude Code