Update .kiro: remove SQLite hooks, add PostgreSQL migration hook, add workflow steering, sync specs
This commit is contained in:
1
.kiro/specs/jira-api-compliance-cleanup/.config.kiro
Normal file
1
.kiro/specs/jira-api-compliance-cleanup/.config.kiro
Normal file
@@ -0,0 +1 @@
|
||||
{"specId": "9b8872ac-5b3f-430b-ac55-c243cf049756", "workflowType": "requirements-first", "specType": "feature"}
|
||||
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.
|
||||
68
.kiro/specs/jira-api-compliance-cleanup/requirements.md
Normal file
68
.kiro/specs/jira-api-compliance-cleanup/requirements.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
The STEAM Security Dashboard integrates with Charter's Jira Data Center via a service account. A service account approval request (ATLSUP ticket) was submitted and the reviewer identified two compliance issues that must be resolved before production approval:
|
||||
|
||||
1. The `POST /api/jira/search` Express route accepts arbitrary JQL from the frontend and proxies it to `POST /rest/api/2/search`, which is not an approved Jira API pattern. This endpoint must be removed entirely — the dashboard's actual workflows (create, sync, lookup) are already served by other endpoints.
|
||||
2. The `searchIssuesByKeys()` bulk-sync function uses `updated >= -24h` in its JQL, but the team works Monday–Friday, meaning the worst-case gap between syncs is Friday evening to Monday morning (~60 hours). The window must be widened to `-72h` to cover weekends.
|
||||
3. The API use-cases documentation (`jira-api-use-cases.md`) must be updated to reflect both changes so the compliance summary remains accurate for the ATLSUP reviewer.
|
||||
|
||||
## Glossary
|
||||
|
||||
- **Dashboard**: The STEAM Security Dashboard Node.js/Express backend application
|
||||
- **Search_Route**: The `POST /api/jira/search` Express route in `backend/routes/jiraTickets.js` that accepts arbitrary JQL from the frontend
|
||||
- **SearchIssuesByKeys_Function**: The `searchIssuesByKeys()` helper function in `backend/helpers/jiraApi.js` used by the bulk sync-all flow
|
||||
- **SearchIssues_Function**: The `searchIssues()` helper function in `backend/helpers/jiraApi.js` that executes JQL queries via `GET /rest/api/2/search`
|
||||
- **Sync_All_Route**: The `POST /api/jira/sync-all` Express route that bulk-refreshes all tracked Jira tickets
|
||||
- **JQL_Window**: The `updated >= -Xh` clause appended to JQL queries to limit results to recently-changed issues
|
||||
- **API_Documentation**: The file `docs/api/jira-api-use-cases.md` that documents all Jira API use cases for the ATLSUP reviewer
|
||||
- **Compliance_Summary_Table**: The table in the API_Documentation that summarizes Charter compliance posture
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: Remove the arbitrary JQL search route
|
||||
|
||||
**User Story:** As a service account reviewer, I want the dashboard to not expose an arbitrary JQL search endpoint, so that the integration only uses approved Jira API patterns.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN the Dashboard starts, THE Dashboard SHALL NOT register a `POST /api/jira/search` route
|
||||
2. WHEN a client sends a `POST` request to `/api/jira/search`, THE Dashboard SHALL respond with HTTP 404
|
||||
3. WHILE the Search_Route is removed, THE Sync_All_Route SHALL continue to function by calling the SearchIssuesByKeys_Function
|
||||
4. WHILE the Search_Route is removed, THE Dashboard SHALL continue to support single-ticket lookup via `GET /api/jira/lookup/:issueKey`
|
||||
5. WHILE the Search_Route is removed, THE Dashboard SHALL continue to support single-ticket sync via `POST /api/jira/:id/sync`
|
||||
6. WHILE the Search_Route is removed, THE Dashboard SHALL continue to support ticket creation via `POST /api/jira/create-in-jira`
|
||||
|
||||
### Requirement 2: Widen the bulk-sync JQL time window to 72 hours
|
||||
|
||||
**User Story:** As a dashboard administrator, I want the bulk sync to use a 72-hour JQL window, so that tickets updated over the weekend are captured on Monday morning.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN the SearchIssuesByKeys_Function builds a JQL query, THE SearchIssuesByKeys_Function SHALL include the clause `updated >= -72h` instead of `updated >= -24h`
|
||||
2. WHEN the Sync_All_Route processes a batch of ticket keys, THE Sync_All_Route SHALL receive results that include tickets updated within the last 72 hours
|
||||
3. WHILE the JQL_Window is set to 72 hours, THE SearchIssuesByKeys_Function SHALL continue to include the `project = <KEY>` clause in the JQL query
|
||||
4. WHILE the JQL_Window is set to 72 hours, THE SearchIssuesByKeys_Function SHALL continue to cap `maxResults` at 1000
|
||||
|
||||
### Requirement 3: Update the API use-cases documentation
|
||||
|
||||
**User Story:** As a service account reviewer, I want the API documentation to accurately reflect the dashboard's current Jira API usage, so that the ATLSUP approval can proceed without discrepancies.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN the API_Documentation is updated, THE API_Documentation SHALL NOT contain a use case entry for `POST /api/jira/search` or arbitrary JQL search
|
||||
2. WHEN the API_Documentation is updated, THE API_Documentation SHALL show the JQL pattern for the bulk sync use case as `updated >= -72h` instead of `updated >= -24h`
|
||||
3. WHEN the API_Documentation is updated, THE Compliance_Summary_Table SHALL accurately reflect that all JQL queries use scoped, predefined patterns with no arbitrary JQL passthrough
|
||||
4. WHEN the API_Documentation is updated, THE API_Documentation SHALL update the estimated daily API usage table to remove the row for the arbitrary JQL search endpoint
|
||||
5. WHEN the API_Documentation is updated, THE API_Documentation SHALL update the total estimated daily API call range to reflect the removal of the search endpoint
|
||||
|
||||
### Requirement 4: Preserve the internal searchIssues helper for scoped callers
|
||||
|
||||
**User Story:** As a developer, I want the internal `searchIssues()` helper to remain available for use by `getIssue()` and `searchIssuesByKeys()`, so that existing scoped JQL operations continue to work.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHILE the Search_Route is removed, THE SearchIssues_Function SHALL remain exported from `jiraApi.js` for use by internal callers
|
||||
2. WHEN the `getIssue()` function is called, THE SearchIssues_Function SHALL execute the JQL query and return the matching issue
|
||||
3. WHEN the SearchIssuesByKeys_Function is called, THE SearchIssues_Function SHALL execute the bulk JQL query and return matching issues
|
||||
28
.kiro/specs/jira-api-compliance-cleanup/tasks.md
Normal file
28
.kiro/specs/jira-api-compliance-cleanup/tasks.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Tasks
|
||||
|
||||
## Task 1: Remove the POST /api/jira/search route
|
||||
|
||||
- [x] 1.1 Delete the `router.post('/search', ...)` handler from `backend/routes/jiraTickets.js` (the entire block from the JSDoc comment through the closing `});`)
|
||||
- [x] 1.2 Verify no other code in the routes file references the removed handler
|
||||
- [x] 1.3 Verify the server starts without errors after the route removal
|
||||
|
||||
## Task 2: Widen the JQL time window to 72 hours
|
||||
|
||||
- [x] 2.1 In `backend/helpers/jiraApi.js`, change the `searchIssuesByKeys()` JQL string from `updated >= -24h` to `updated >= -72h`
|
||||
- [x] 2.2 Update the JSDoc comment on `searchIssuesByKeys()` if it references the 24-hour window
|
||||
|
||||
## Task 3: Update the API use-cases documentation
|
||||
|
||||
- [x] 3.1 In `docs/api/jira-api-use-cases.md`, update the bulk sync use case (Use Case 8) to reflect the `-72h` JQL window and remove any reference to arbitrary JQL or `POST /rest/api/2/search`
|
||||
- [x] 3.2 Update the Compliance Summary Table to reflect that JQL queries use predefined scoped patterns (no arbitrary JQL passthrough) and the `-72h` window
|
||||
- [x] 3.3 Update the Estimated Daily API Usage table to remove the arbitrary JQL search row and recalculate the total
|
||||
- [x] 3.4 Add `POST /rest/api/2/search` to the Blocked Endpoints section with an explanation that arbitrary JQL search via POST is not used
|
||||
|
||||
## Task 4: Write property-based test for JQL window invariant
|
||||
|
||||
- [x] 4.1 Create a property-based test that verifies `searchIssuesByKeys()` always generates JQL containing `updated >= -72h` and `project =` for any non-empty array of issue keys
|
||||
|
||||
## Task 5: Write example-based tests for route removal and remaining routes
|
||||
|
||||
- [x] 5.1 Write a test that sends `POST /api/jira/search` and asserts HTTP 404
|
||||
- [x] 5.2 Write tests that verify the remaining Jira routes (`GET /lookup/:issueKey`, `POST /sync-all`, `POST /:id/sync`, `POST /create-in-jira`) still respond with non-404 status codes
|
||||
Reference in New Issue
Block a user