feat(iace): Phase 5+6 — frontend integration, RAG library search, comprehensive tests
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 34s
CI/CD / test-python-backend-compliance (push) Successful in 33s
CI/CD / test-python-document-crawler (push) Successful in 23s
CI/CD / test-python-dsms-gateway (push) Successful in 19s
CI/CD / validate-canonical-controls (push) Successful in 13s
CI/CD / Deploy (push) Successful in 2s
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 34s
CI/CD / test-python-backend-compliance (push) Successful in 33s
CI/CD / test-python-document-crawler (push) Successful in 23s
CI/CD / test-python-dsms-gateway (push) Successful in 19s
CI/CD / validate-canonical-controls (push) Successful in 13s
CI/CD / Deploy (push) Successful in 2s
Phase 5 — Frontend Integration: - components/page.tsx: ComponentLibraryModal with 120 components + 20 energy sources - hazards/page.tsx: AutoSuggestPanel with 3-column pattern matching review - mitigations/page.tsx: SuggestMeasuresModal per hazard with 3-level grouping - verification/page.tsx: SuggestEvidenceModal per mitigation with evidence types Phase 6 — RAG Library Search: - Added bp_iace_libraries to AllowedCollections whitelist in rag_handlers.go - SearchLibrary endpoint: POST /iace/library-search (semantic search across libraries) - EnrichTechFileSection endpoint: POST /projects/:id/tech-file/:section/enrich - Created ingest-iace-libraries.sh ingestion script for Qdrant collection Tests (123 passing): - tag_taxonomy_test.go: 8 tests for taxonomy entries, domains, essential tags - controls_library_test.go: 7 tests for measures, reduction types, subtypes - integration_test.go: 7 integration tests for full match flow and library consistency - Extended tag_resolver_test.go: 9 new tests for FindByTags and cross-category resolution Documentation: - Updated iace.md with Hazard-Matching-Engine, RAG enrichment, and new DB tables Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/iace"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/ucca"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@@ -25,6 +26,7 @@ type IACEHandler struct {
|
||||
engine *iace.RiskEngine
|
||||
classifier *iace.Classifier
|
||||
checker *iace.CompletenessChecker
|
||||
ragClient *ucca.LegalRAGClient
|
||||
}
|
||||
|
||||
// NewIACEHandler creates a new IACEHandler with all required dependencies.
|
||||
@@ -34,6 +36,7 @@ func NewIACEHandler(store *iace.Store) *IACEHandler {
|
||||
engine: iace.NewRiskEngine(),
|
||||
classifier: iace.NewClassifier(),
|
||||
checker: iace.NewCompletenessChecker(),
|
||||
ragClient: ucca.NewLegalRAGClient(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2325,6 +2328,138 @@ func (h *IACEHandler) SuggestEvidenceForMitigation(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RAG Library Search (Phase 6)
|
||||
// ============================================================================
|
||||
|
||||
// IACELibrarySearchRequest represents a semantic search against the IACE library corpus.
|
||||
type IACELibrarySearchRequest struct {
|
||||
Query string `json:"query" binding:"required"`
|
||||
Category string `json:"category,omitempty"`
|
||||
TopK int `json:"top_k,omitempty"`
|
||||
Filters []string `json:"filters,omitempty"`
|
||||
}
|
||||
|
||||
// SearchLibrary handles POST /iace/library-search
|
||||
// Performs semantic search across the IACE hazard/component/measure library in Qdrant.
|
||||
func (h *IACEHandler) SearchLibrary(c *gin.Context) {
|
||||
var req IACELibrarySearchRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
topK := req.TopK
|
||||
if topK <= 0 || topK > 50 {
|
||||
topK = 10
|
||||
}
|
||||
|
||||
// Use regulation filter for category-based search within the IACE collection
|
||||
var filters []string
|
||||
if req.Category != "" {
|
||||
filters = append(filters, req.Category)
|
||||
}
|
||||
filters = append(filters, req.Filters...)
|
||||
|
||||
results, err := h.ragClient.SearchCollection(
|
||||
c.Request.Context(),
|
||||
"bp_iace_libraries",
|
||||
req.Query,
|
||||
filters,
|
||||
topK,
|
||||
)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "RAG search failed",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if results == nil {
|
||||
results = []ucca.LegalSearchResult{}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"query": req.Query,
|
||||
"results": results,
|
||||
"total": len(results),
|
||||
})
|
||||
}
|
||||
|
||||
// EnrichTechFileSection handles POST /projects/:id/tech-file/:section/enrich
|
||||
// Uses RAG to find relevant library content for a specific tech file section.
|
||||
func (h *IACEHandler) EnrichTechFileSection(c *gin.Context) {
|
||||
projectID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
|
||||
return
|
||||
}
|
||||
|
||||
sectionType := c.Param("section")
|
||||
if sectionType == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "section type required"})
|
||||
return
|
||||
}
|
||||
|
||||
project, err := h.store.GetProject(c.Request.Context(), projectID)
|
||||
if err != nil || project == nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
|
||||
return
|
||||
}
|
||||
|
||||
// Build a contextual query based on section type and project data
|
||||
queryParts := []string{project.MachineName, project.MachineType}
|
||||
|
||||
switch sectionType {
|
||||
case "risk_assessment_report", "hazard_log_combined":
|
||||
queryParts = append(queryParts, "Gefaehrdungen", "Risikobewertung", "ISO 12100")
|
||||
case "essential_requirements":
|
||||
queryParts = append(queryParts, "Sicherheitsanforderungen", "Maschinenrichtlinie")
|
||||
case "design_specifications":
|
||||
queryParts = append(queryParts, "Konstruktionsspezifikation", "Sicherheitskonzept")
|
||||
case "test_reports":
|
||||
queryParts = append(queryParts, "Pruefbericht", "Verifikation", "Nachweis")
|
||||
case "standards_applied":
|
||||
queryParts = append(queryParts, "harmonisierte Normen", "EN ISO")
|
||||
case "ai_risk_management":
|
||||
queryParts = append(queryParts, "KI-Risikomanagement", "AI Act", "Algorithmen")
|
||||
case "ai_human_oversight":
|
||||
queryParts = append(queryParts, "menschliche Aufsicht", "Human Oversight", "KI-Transparenz")
|
||||
default:
|
||||
queryParts = append(queryParts, sectionType)
|
||||
}
|
||||
|
||||
query := strings.Join(queryParts, " ")
|
||||
|
||||
results, err := h.ragClient.SearchCollection(
|
||||
c.Request.Context(),
|
||||
"bp_iace_libraries",
|
||||
query,
|
||||
nil,
|
||||
5,
|
||||
)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "RAG enrichment failed",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if results == nil {
|
||||
results = []ucca.LegalSearchResult{}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"project_id": projectID.String(),
|
||||
"section_type": sectionType,
|
||||
"query": query,
|
||||
"context": results,
|
||||
"total": len(results),
|
||||
})
|
||||
}
|
||||
|
||||
// mustMarshalJSON marshals the given value to json.RawMessage.
|
||||
func mustMarshalJSON(v interface{}) json.RawMessage {
|
||||
data, err := json.Marshal(v)
|
||||
|
||||
@@ -33,6 +33,7 @@ var AllowedCollections = map[string]bool{
|
||||
"bp_dsfa_templates": true,
|
||||
"bp_dsfa_risks": true,
|
||||
"bp_legal_templates": true,
|
||||
"bp_iace_libraries": true,
|
||||
}
|
||||
|
||||
// SearchRequest represents a RAG search request.
|
||||
|
||||
Reference in New Issue
Block a user