feat(iace): hazard block view — parent/child grouping
Build + Deploy / build-admin-compliance (push) Successful in 2m9s
Build + Deploy / build-backend-compliance (push) Successful in 11s
Build + Deploy / build-ai-sdk (push) Successful in 54s
Build + Deploy / build-developer-portal (push) Successful in 10s
Build + Deploy / build-tts (push) Successful in 12s
Build + Deploy / build-document-crawler (push) Successful in 13s
Build + Deploy / build-dsms-gateway (push) Successful in 15s
Build + Deploy / build-dsms-node (push) Successful in 13s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 19s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 3m14s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Failing after 59s
CI / test-python-backend (push) Successful in 40s
CI / test-python-document-crawler (push) Successful in 28s
CI / test-python-dsms-gateway (push) Successful in 22s
CI / validate-canonical-controls (push) Successful in 15s
Build + Deploy / trigger-orca (push) Successful in 2m54s
Build + Deploy / build-admin-compliance (push) Successful in 2m9s
Build + Deploy / build-backend-compliance (push) Successful in 11s
Build + Deploy / build-ai-sdk (push) Successful in 54s
Build + Deploy / build-developer-portal (push) Successful in 10s
Build + Deploy / build-tts (push) Successful in 12s
Build + Deploy / build-document-crawler (push) Successful in 13s
Build + Deploy / build-dsms-gateway (push) Successful in 15s
Build + Deploy / build-dsms-node (push) Successful in 13s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 19s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 3m14s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Failing after 59s
CI / test-python-backend (push) Successful in 40s
CI / test-python-document-crawler (push) Successful in 28s
CI / test-python-dsms-gateway (push) Successful in 22s
CI / validate-canonical-controls (push) Successful in 15s
Build + Deploy / trigger-orca (push) Successful in 2m54s
Backend: - hazard_blocks.go: ComputeHazardBlocks() groups hazards by category + component + zone. Parent = highest risk in group. Children covered by parent's measures are flagged (no separate assessment needed). - iace_handler_blocks.go: GET /projects/:id/hazard-blocks endpoint with summary stats (blocks, covered children, assessments saved) Frontend: - HazardBlockView.tsx: Expandable block view with summary cards, parent-child hierarchy, coverage badges, and "abgedeckt" indicators - hazards/page.tsx: New "Bloecke" tab alongside "Hazard-Liste" and "Risikobewertung" No database schema changes — grouping is computed at runtime. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/iace"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// GetHazardBlocks handles GET /projects/:id/hazard-blocks
|
||||
// Returns hazards grouped into parent-child blocks based on shared category,
|
||||
// component, and zone. The parent hazard in each block has the highest risk.
|
||||
// Children covered by the parent's measures are flagged accordingly.
|
||||
func (h *IACEHandler) GetHazardBlocks(c *gin.Context) {
|
||||
projectID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
|
||||
return
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
|
||||
hazards, err := h.store.ListHazards(ctx, projectID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load hazards"})
|
||||
return
|
||||
}
|
||||
|
||||
assessmentMap, _ := h.store.GetLatestAssessmentsByProject(ctx, projectID)
|
||||
var assessments []iace.RiskAssessment
|
||||
for _, a := range assessmentMap {
|
||||
assessments = append(assessments, a)
|
||||
}
|
||||
mitigations, _ := h.store.ListMitigationsByProject(ctx, projectID)
|
||||
|
||||
blocks := iace.ComputeHazardBlocks(hazards, assessments, mitigations)
|
||||
|
||||
// Compute summary stats
|
||||
totalBlocks := len(blocks)
|
||||
parentOnly := 0
|
||||
coveredChildren := 0
|
||||
uncoveredChildren := 0
|
||||
for _, b := range blocks {
|
||||
if len(b.Children) == 0 {
|
||||
parentOnly++
|
||||
} else if b.ChildrenCoveredByParent {
|
||||
coveredChildren += len(b.Children)
|
||||
} else {
|
||||
uncoveredChildren += len(b.Children)
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"blocks": blocks,
|
||||
"summary": gin.H{
|
||||
"total_blocks": totalBlocks,
|
||||
"parent_only_blocks": parentOnly,
|
||||
"blocks_with_children": totalBlocks - parentOnly,
|
||||
"total_hazards": len(hazards),
|
||||
"covered_children": coveredChildren,
|
||||
"uncovered_children": uncoveredChildren,
|
||||
"assessments_needed": totalBlocks - parentOnly + uncoveredChildren + parentOnly,
|
||||
"assessments_saved": coveredChildren,
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user