Skip to content

Feat/bch-1186-promote-to-poam#212

Merged
gusfcarvalho merged 6 commits into
mainfrom
feat/bch-1186-promote-to-poam
Mar 31, 2026
Merged

Feat/bch-1186-promote-to-poam#212
gusfcarvalho merged 6 commits into
mainfrom
feat/bch-1186-promote-to-poam

Conversation

@AKAbdulHanif
Copy link
Copy Markdown
Contributor

Summary

This PR implements the UI for the Risk → POAM promotion journey introduced in the API (compliance-framework/api#362). It allows a user to promote a risk that is in investigating status directly to a POAM item, transitioning the risk to mitigating-planned in a single action. It also adds the Mark Mitigating Implemented button for the subsequent lifecycle step.

File What Changed
src/types/poam-items.ts Added risk-promotion source type and PromoteRiskToPoamRequest interface
src/composables/usePoamItems.ts Added usePromoteRiskToPoam() composable for POST /api/risks/:id/promote-to-poam
src/utils/risk-workflow.ts Added canPromoteToPoam() and canMarkMitigatingImplemented() helpers; updated ALLOWED_RISK_TRANSITIONS to match API fixes; removed BCH-1206 TODO
src/components/risk/PromoteToPoamModal.vue New modal — status transition banner, editable title, deadline, resource fields, milestone template preview
src/views/risk/RiskDetailView.vue Promote to POAM button (violet, investigating only), Mark Mitigating Implemented button (teal, mitigating-planned only), modal wiring, submit handlers
src/utils/risk-workflow.spec.ts 6 new tests for canPromoteToPoam, canMarkMitigatingImplemented, and updated transitions
src/composables/__tests__/usePoamItems.spec.ts 4 new tests for usePromoteRiskToPoam (URL, URL encoding, payload, empty payload)

Tests

File New Tests
src/utils/risk-workflow.spec.ts 6 — canPromoteToPoam (all statuses), canMarkMitigatingImplemented (all statuses), updated transition map assertions
src/composables/__tests__/usePoamItems.spec.ts 4 — URL construction, URL encoding of riskId, payload forwarding, empty payload

Dependencies

  • Requires feat(poam): BCH-1186 — promote risk to POAM item api#362 to be merged and deployed before the promotion endpoint is live.
  • The templateMilestoneTitles prop on PromoteToPoamModal is intentionally empty in this PR. A follow-up ticket should wire in the risk's remediation template tasks once the template-fetch composable is available.

Checklist

  • Types updated (PromoteRiskToPoamRequest, risk-promotion source type)
  • Composable follows existing useDataApi pattern
  • Workflow helpers follow existing can* pattern
  • Modal follows existing v-model:visible / @submit pattern
  • All lifecycle transitions preserved (no existing paths removed)
  • Unit tests added for all new helpers and composable
  • vue-tsc --noEmit passes
  • ESLint passes
  • All 415 existing tests continue to pass

Align UI types and components with the API model change that removes
free-text poc_name/poc_email fields in favour of the structured
primaryOwnerUserId FK.

- PoamItem: add primaryOwnerUserId, resourceRequired; remove pocName/pocEmail
- CreatePoamItemRequest / UpdatePoamItemRequest: same additions
- CCFPoamItemsListView: rename POC column to Owner, display primaryOwnerUserId
  (UUID display is intentional placeholder pending a user-lookup component)

Relates to: BCH-1186 / PR #362 review comment (gusfcarvalho)
Implements the Risk -> POAM promotion journey (BCH-1186 Phase 2) in the UI.

Changes:
- types/poam-items.ts: add 'risk-promotion' PoamSourceType and
  PromoteRiskToPoamRequest interface for POST /api/risks/:id/promote-to-poam
- composables/usePoamItems.ts: add usePromoteRiskToPoam composable
- utils/risk-workflow.ts:
  - add canPromoteToPoam() helper (true only when status is 'investigating')
  - add canMarkMitigatingImplemented() helper (true only when 'mitigating-planned')
  - update ALLOWED_RISK_TRANSITIONS to align with API PR #362 fixes:
    mitigating-planned can fall back to investigating (failed mitigation)
    mitigating-implemented can transition to remediated
  - remove BCH-1206 TODO comment (now implemented)
- components/risk/PromoteToPoamModal.vue: new modal with status transition
  banner, editable title, deadline, resource fields, and milestone preview
- views/risk/RiskDetailView.vue:
  - add 'Promote to POAM' button (violet, visible when investigating)
  - add 'Mark Mitigating Implemented' button (teal, visible when mitigating-planned)
  - mount PromoteToPoamModal with v-model:visible
  - add submitPromoteToPoam() and submitMarkMitigatingImplemented() handlers
  - add canPromoteToPoamAction and canMarkMitigatingImplementedAction computed
  - reset showPromoteToPoamModal in loadRisk()

Tests:
- risk-workflow.spec.ts: 6 new test cases covering canPromoteToPoam,
  canMarkMitigatingImplemented, and the updated transition map
- usePoamItems.spec.ts: 4 new test cases covering usePromoteRiskToPoam
  (URL construction, URL encoding, payload forwarding, empty payload)

All 415 tests pass. Zero TypeScript errors. Zero ESLint warnings.
…ateMilestoneTitles

- RiskDetailView.vue: replace risk.value.id (does not exist on Risk type)
  with getRiskIdentifier(risk.value) which reads uuid/riskUuid/id/riskId
  in priority order — resolves TS error at L2939/2942
- PromoteToPoamModal.vue: add null guard on templateMilestoneTitles before
  calling .length — prop is optional (string[] | undefined), resolves
  'possibly undefined' TS error at L77
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the frontend flow for promoting an investigating Risk to a CCF POAM item (Risk → POAM), plus adds a follow-on workflow action to mark mitigation as implemented, aligning UI workflow transitions with the updated API behavior.

Changes:

  • Adds a new “Promote to POAM” modal + wiring in Risk Detail, and a “Mark Mitigating Implemented” action.
  • Introduces a usePromoteRiskToPoam() composable and corresponding request/type additions for the promotion endpoint.
  • Updates risk workflow transition rules and extends unit tests around workflow helpers and the new composable.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/views/risk/RiskDetailView.vue Adds promote/transition buttons, promotion modal integration, and submit handlers.
src/components/risk/PromoteToPoamModal.vue New modal UI for promotion inputs (title/deadline/resource) and milestone preview.
src/composables/usePoamItems.ts Adds usePromoteRiskToPoam() for POST /api/risks/:id/promote-to-poam.
src/types/poam-items.ts Adds risk-promotion source type + PromoteRiskToPoamRequest, extends POAM item fields.
src/utils/risk-workflow.ts Updates allowed transitions and adds canPromoteToPoam / canMarkMitigatingImplemented.
src/utils/risk-workflow.spec.ts Adds tests for new helpers and updated transition map.
src/composables/tests/usePoamItems.spec.ts Adds tests for promotion composable URL/payload behavior.
src/views/poam/CCFPoamItemsListView.vue Adjusts list column from POC fields to primaryOwnerUserId.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 50 to 64
<th class="p-2 border">Title</th>
<th class="p-2 border">Status</th>
<th class="p-2 border">Deadline</th>
<th class="p-2 border">POC</th>
<th class="p-2 border">Owner</th>
<th class="p-2 border">Updated</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id" class="text-sm">
<td class="p-2 border">{{ item.title }}</td>
<td class="p-2 border">{{ item.status }}</td>
<td class="p-2 border">{{ item.deadline ?? '-' }}</td>
<td class="p-2 border">
{{ item.pocName ?? '-' }}
<span v-if="item.pocEmail">({{ item.pocEmail }})</span>
{{ item.primaryOwnerUserId ?? '-' }}
</td>
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This table now labels the column "Owner" but renders primaryOwnerUserId, which will typically be a UUID and not user-friendly. Either resolve the userId to a display name/email (similar to risk owner rendering elsewhere) or rename the column to something explicit like "Owner ID" to avoid confusing users.

Copilot uses AI. Check for mistakes.
Comment thread src/views/risk/RiskDetailView.vue Outdated
v-model:visible="showPromoteToPoamModal"
:submitting="promotingToPoam"
:risk-title="risk?.title"
:template-milestone-titles="[]"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

template-milestone-titles is currently always passed as an empty array, which will cause PromoteToPoamModal to render its "No remediation template found" fallback copy even when the template just isn’t wired yet. Consider passing undefined (or a separate loading/unknown state) until the remediation template tasks are actually fetched, so the UI doesn’t present a false negative.

Suggested change
:template-milestone-titles="[]"
:template-milestone-titles="undefined"

Copilot uses AI. Check for mistakes.
Comment on lines +97 to +98
No remediation template found for this risk. Milestones can be added
to the POAM item after promotion.
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback message shown when templateMilestoneTitles is empty says "No remediation template found for this risk", but callers may pass an empty array simply because milestones aren’t loaded/wired yet. Consider distinguishing between undefined (unknown/not loaded) vs [] (known none), or add an explicit boolean prop so the modal doesn’t make an incorrect claim.

Suggested change
No remediation template found for this risk. Milestones can be added
to the POAM item after promotion.
Remediation milestones are not currently available. Milestones can be
added to the POAM item after promotion.

Copilot uses AI. Check for mistakes.
Comment on lines +219 to +222
if (parsed.getTime() <= Date.now()) {
validationError.value = 'Planned completion date must be in the future.';
return;
}
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The modal enforces that the planned completion date must be in the future. Elsewhere in the POAM UI, planned completion dates appear to allow today/past dates (overdue is a valid state), so this validation may unnecessarily block legitimate promotions (e.g., when promoting an already-overdue risk). Consider aligning this validation with the API/business rules used for POAM item creation/editing (or downgrade to a warning).

Suggested change
if (parsed.getTime() <= Date.now()) {
validationError.value = 'Planned completion date must be in the future.';
return;
}

Copilot uses AI. Check for mistakes.
AKAbdulHanif and others added 3 commits March 27, 2026 07:38
- CCFPoamItemsListView.vue: rename 'Owner' column header to 'Owner ID'
  to accurately reflect that the value is a raw UUID, not a resolved
  display name — avoids confusing users (Copilot comment #1)
- RiskDetailView.vue: pass :template-milestone-titles="undefined" instead
  of "[]" so the modal correctly represents an unloaded state rather than
  asserting no template exists (Copilot comment #2)
- PromoteToPoamModal.vue: update fallback text from 'No remediation
  template found for this risk' to 'Remediation milestones are not
  currently available' — avoids false negative when milestones are simply
  not yet loaded (Copilot comment #3)
- PromoteToPoamModal.vue: remove future-date enforcement on
  plannedCompletionDate — POAM items legitimately allow past/today dates
  (overdue is a valid state); aligns with API business rules (Copilot #4)

All 415 tests pass. Zero TypeScript errors. Zero ESLint warnings.
Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
@gusfcarvalho gusfcarvalho merged commit 68b6826 into main Mar 31, 2026
2 checks passed
@gusfcarvalho gusfcarvalho deleted the feat/bch-1186-promote-to-poam branch March 31, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants