Update .kiro: remove SQLite hooks, add PostgreSQL migration hook, add workflow steering, sync specs
This commit is contained in:
133
.kiro/specs/jira-api-compliance-cleanup/design.md
Normal file
133
.kiro/specs/jira-api-compliance-cleanup/design.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 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:
|
||||
|
||||
1. **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.
|
||||
|
||||
2. **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.
|
||||
|
||||
3. **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/search` with arbitrary JQL, and renumber it to describe only the scoped bulk sync via `GET /rest/api/2/search` with the predefined key-based JQL pattern
|
||||
- Update the JQL pattern in the bulk sync use case from `updated >= -24h` to `updated >= -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 `-72h` window
|
||||
- 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/search` to 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.
|
||||
Reference in New Issue
Block a user