6.9 KiB
Design Document
Overview
This design addresses two compliance issues flagged during the Charter Jira Data Center service account approval review (ATLSUP ticket), plus the corresponding documentation update. The changes are minimal and surgical — removing one Express route, changing one string literal, and updating one documentation file.
Architecture
Current State
The Jira integration has three layers:
-
Helper layer (
backend/helpers/jiraApi.js): Low-level HTTP functions (jiraGet,jiraPost, etc.) and high-level operations (getIssue,searchIssuesByKeys,searchIssues,createIssue, etc.). All Charter compliance enforcement (rate limits, delays, blocked paths, explicit fields) lives here. -
Route layer (
backend/routes/jiraTickets.js): Express routes mounted at/api/jira. Includes both Jira API integration routes (connection-test, lookup, search, create-in-jira, sync-all, single sync) and local CRUD routes. -
Documentation layer (
docs/api/jira-api-use-cases.md): Documents all Jira API use cases, compliance posture, and estimated daily usage for the ATLSUP reviewer.
Changes Required
Change 1: Remove POST /api/jira/search route
File: backend/routes/jiraTickets.js
Action: Delete the entire router.post('/search', ...) handler (approximately lines 136–196). This route accepts arbitrary JQL from the frontend and passes it to jiraApi.searchIssues(). No frontend code references this endpoint (confirmed via codebase search). The underlying searchIssues() helper function in jiraApi.js is NOT removed — it is still called internally by getIssue() and searchIssuesByKeys().
Impact: None on existing workflows. The four actual workflows (create, lookup, single sync, bulk sync) use dedicated routes that do not depend on the search route.
Change 2: Widen JQL window from -24h to -72h
File: backend/helpers/jiraApi.js
Action: In the searchIssuesByKeys() function, change the JQL string literal from:
`key in (${keyList}) AND updated >= -24h AND project = ${JIRA_PROJECT_KEY}`
to:
`key in (${keyList}) AND updated >= -72h AND project = ${JIRA_PROJECT_KEY}`
Impact: The bulk sync-all flow will now pick up tickets that were updated over the weekend. This increases the potential result set size for Monday morning syncs but remains well within the 1000-result cap (the team tracks dozens to low hundreds of tickets, not thousands).
Change 3: Update API documentation
File: docs/api/jira-api-use-cases.md
Actions:
- Remove the entire "Use Case 8: JQL Search (Bulk Sync)" section that references
POST /rest/api/2/searchwith arbitrary JQL, and renumber it to describe only the scoped bulk sync viaGET /rest/api/2/searchwith the predefined key-based JQL pattern - Update the JQL pattern in the bulk sync use case from
updated >= -24htoupdated >= -72h - Update the Compliance Summary Table: change the "Bulk reads via JQL" row to clarify that JQL is predefined/scoped (not arbitrary)
- Update the "JQL scoping" row to reflect the
-72hwindow - Remove the "JQL search (sync)" row from the Estimated Daily API Usage table or update it to reflect only the scoped bulk sync
- Recalculate the total estimated daily API call range
- Add
POST /rest/api/2/searchto the Blocked Endpoints section since arbitrary JQL search via POST is no longer used
Correctness Properties
Property 1: JQL window is always 72 hours in bulk sync (Invariant)
Requirement: 2.1, 2.3
Property: For any non-empty array of issue keys passed to searchIssuesByKeys(), the generated JQL string SHALL contain the substring updated >= -72h and SHALL contain the substring project =.
Type: Property-based test — the JQL structure must hold for any valid input array of keys.
Test approach: Mock searchIssues() to capture the JQL argument. Generate random arrays of valid-looking issue keys (e.g., KEY-1 through KEY-N). Assert the JQL always contains updated >= -72h and project =.
Property 2: Search route is absent from router (Example)
Requirement: 1.1, 1.2
Property: After the route removal, a POST request to /api/jira/search SHALL return HTTP 404.
Type: Example-based test — single request, single assertion.
Test approach: Mount the router in a test Express app, send POST /api/jira/search with a body, assert 404.
Property 3: Existing routes remain functional after search route removal (Example)
Requirement: 1.3, 1.4, 1.5, 1.6
Property: The routes GET /api/jira/lookup/:issueKey, POST /api/jira/sync-all, POST /api/jira/:id/sync, and POST /api/jira/create-in-jira SHALL continue to respond with non-404 status codes.
Type: Example-based test — verify each route is still registered.
Test approach: Mount the router, send requests to each endpoint, assert none return 404 (they may return 503 if Jira is not configured, which is fine — the point is the route exists).
Property 4: searchIssues helper remains exported (Example)
Requirement: 4.1
Property: The jiraApi module SHALL export searchIssues as a function.
Type: Example-based test — single assertion on module exports.
Property 5: Documentation does not reference removed endpoint (Example)
Requirement: 3.1, 3.3, 3.4
Property: The file docs/api/jira-api-use-cases.md SHALL NOT contain the string POST /api/jira/search or POST /rest/api/2/search as an active use case.
Type: Example-based test — read file, assert absence of the string.
Property 6: Documentation reflects 72-hour window (Example)
Requirement: 3.2
Property: The file docs/api/jira-api-use-cases.md SHALL contain updated >= -72h in the bulk sync use case and SHALL NOT contain updated >= -24h.
Type: Example-based test — read file, assert string presence/absence.
File Changes
| File | Change Type | Description |
|---|---|---|
backend/routes/jiraTickets.js |
Modify | Remove the router.post('/search', ...) handler (~60 lines) |
backend/helpers/jiraApi.js |
Modify | Change -24h to -72h in searchIssuesByKeys() (1 line) |
docs/api/jira-api-use-cases.md |
Modify | Remove search use case, update JQL window, update compliance table, update usage estimates, add POST search to blocked endpoints |
Dependencies
No new dependencies. No changes to package.json. No database migrations. No frontend changes required (no frontend code references the search endpoint).
Risk Assessment
Low risk. All three changes are removals or single-line edits in well-understood code paths:
- The search route removal has zero callers in the frontend codebase
- The JQL window change is a single string literal with no behavioral side effects beyond returning a larger result set
- The documentation changes are purely textual
The only regression risk is if an undiscovered caller depends on POST /api/jira/search. The codebase search confirmed no such caller exists.